カテゴリー: 技術情報

HTLM5、JavascriptでiOS版Safari「だけ」Audioオブジェクトの.load()が必要だった件

2月くらいにHTLM5、JavascriptでAudioオブジェクトのcurrentTime = 0では頭出しができなくなる現象についてと言う記事を書いたのですが、お客さんからiOSだけ動かないとか連絡が来て「Appleまたお前か」となってしまいました。
結論から言うとiOS版Safariだけメディアストリーミングデーターの扱いが異なっていた訳です。

どうやらiOS版Safariとデスクトップ版Safariを含む他のブラウザには以下の様な差異があったようです。

  1. デスクトップ版Safariを含む他のブラウザではAudioオブジェクトの.srcに何か入れただけでファイルの読込みが発生するがiOS版Safariでは.load()が実行されるまで何もしない
  2. デスクトップ版Safariを含む他のブラウザではAudioオブジェクトの.load(メディアファイルのURL)を実行すると確実に実行されるがiOS版SafariではメディアファイルのURLが元の値と同じ場合は実行されない

他のブラウザの対応を見るとガーベイジコレクションとの兼ね合いで.load()メソッドはメディアファイルの初期化に使われる格好になって居るのですが、iOS版Safariだけは頑なに「loadはloadじゃん、他の意味なんてないわい」と言っているようです。

まぁ別にSafariだけ違うって話なら「まぁAppleだし仕方ないか」と思わなくもないのですが、iOS版だけ違うと言うのはどうにも納得いかないですね。
特に2については致命的で解消するには.loadの都度URLの後ろに”?+Date.new()”とか”?+Math.random()”みたいな重複しない値をくっつけるしか手は無い訳ですが、これをやるとキャッシュが効かなくなるわけで、一々サーバーにデーターを取りに行く事になり「モバイル向けブラウザのくせに全然モバイル通信に優しくない」だけでなく「プリロードの意味が無いじゃん」ってなる気がするデス。

一方でプリロードしたメディアファイルの初期化は.load()メソッドを使うと言う点は他のブラウザと変わりがない訳で、どうにも一貫していないんですよね。

やっぱりAppleは呪われるべきですわ。


HTLM5、JavascriptでAudioオブジェクトのcurrentTime = 0では頭出しができなくなる現象について

非常にご無沙汰をしております。tongでございます。
ここまで間があいてしまいますと「あんた誰?」みたいな方ばかりかと思いますが、自己紹介は無しの方向でお願いします。
私事で色々ございましてなりを潜めておりましたが生活の為にお仕事はする訳で、そこで「ちょいとハマった」事があって調べても中々わからなかったので、ここに書いておけば誰かの助けになるかなと言う事で書いておこうと思います。

背景説明としてはWebアプリの開発から7年くらい離れていたのですが、色々あって昔 自分がFlashで作った真面目な仕事のWebアプリ化を断ったら他所に頼んだけど失敗したので再度舞い戻って来た。って感じの話。

記事内容はタイトルの通りで、ネットワークの遅延を防ぐために100個位の短い音声ファイル(えっちぃ声じゃ無いよ)を先読みしてユーザー操作に応じて再生するって感じの挙動。

引っかかったのは2点で、一つは動的にAudio「タグ」を大量に生成してHTMLのエレメントに追加するとFirefoxでは読み込みに引っ掛かりが出る場合があること。
今回はAudioタグのコントロールを表示したりしないので、Javascriptのオブジェクトとして扱ってやれば回避可能でした。

もう一つは、Mac OS XのApple Safariのみ先読みした音声ファイルの2度目の再生が出来ない、あるいは途中から再生されると言う現象。
最初は「またアップルかっ!」とキレそうになるも、そこはホレ大人ですから落ち着いてよく考えてみる。
すると、まず途中から再生されるのは1回目の再生時に最後まで再生されない場合に再生位置が残っているのでは無いかと言う推察に至ります。

途中から再生されちゃダメなら再生前に頭出しすりゃ良いじゃん。って事で「currentTime = 0」を入れる訳ですが、これが出来ない。

なにこれ?

ReadOnlyでもないプロパティーに値がセットできないのは変です。異常です。
この辺をWebで検索するとSafariとChromeの自動再生回避ばかりが引っかかるんだけど、そうじゃないんだよね・・・
って事でさらに調べて行くと「new Audio(‘URL’)でAudioオブジェクトを再度作るとcurrentTime = 0じゃ無くても頭出しできるよっ」みたいな記述がSafari開発者のコミュニティーで見つかったので早速実装。

ふむ、確かにSafariでは動く。しかし他のブラウザでテストを行うとFireFoxで動かないでは無いか。
件のページにも今のSafariは「さすがはSafari、大量にオブジェクトを作っても何とも無いぜ」だけど昔は大量にオブジェクトをnewすると動作が不安定になったってあって「やっぱりアップル関係者はSafariしか考えてないなっ!」となって居た訳です。

その後もcurrentTime = 0関連で、メモリー上に「先頭が0以外の値のAudioストリームデーターはcurrentTimeを0に出来ない」とか、色々出てきて「先頭が0以外の値のAudioストリームデーター」ってどんなよ?ってなるのですが、「あぁユーザーがコントローラーで再生位置をジャンプしたりするとそうなるか、メモリー上に無いなら出来ないわな」。
そして「new Audio(‘URL’)」で解消できるって事はダメな時はメモリー上にデーターが無かったって事であり、currentTime = 0に気を取られていたけど、これはもっと別の現象なのではと言う考えに至り・・・

そう、そうなんです。
これは「何らかの原因でメモリー上に音声データーが無い」事が原因なんですね。

ここで種明かしをすると、この現象はガーベイジコレクトが原因なんですね。
と言うか昔、同じECMAスクリプトであるActionScriptでも同じ現象に出くわした事が有った気がしてきました。

ガーベイジコレクトとは使用メモリーの節約機能で、ロードやアクセスしてから時間が経ったオブジェクトはエントリのためのオブジェクトのガワだけ残して実体はメモリーから削除されちゃうんです。
このため最初の頃はちゃんと再生できていた音声が時間が経つと正しく再生できなかったり、頭出しが出来ない等の現象が起きてしまう訳です。

では具体的にはどう対策したらよいのかと言いますと、new Audio(‘URL’)でAudioオブジェクトを大量に作ると言う方法ではAudioオブジェクトの作り過ぎでスマートじゃない。何よりFireFoxで動かないなどの弊害があります。
これを回避するには、新しくオブジェクトを作るのではなくAudioオブジェクト.load(‘URL’)とします。

//先読みでデーターをロードする
let soundObj_0 = new Audio(‘sound/sound_0.mp3’); //プリロード


//どのタイミングで音声データーが使われるか分からないので
//使うときはとにかくloadしてしまう
soundObj_0.load(‘sound/sound_0.mp3’); //再生前に無条件にロード
soundObj_0.currentTime = 0;  //念のために再生位置を0リセット
soundObj_0.play();  //音声再生

こんな感じですかね。

なお、2回目のload(‘URL’)はブラウザ キャッシュからロードが行われるので読み込みにネットワークの遅延は出ないようです。

めでたしめでたし。


方言ツイートまとめ

最近X(旧ツイッター)でブログ更新の告知を各地の方言でつぶやくのがマイブーム(死語)になっています。方言って萌えますよね。そのため萌え研究の一貫としていろいろ調べてはいたのですが、あいさつだけでなく本文まで方言で書き始めたら自分でもよくわからなくなってきました。需要は無視してここにまとめてみます。

方言はネットで調べて書いていますが、地域差や個人差もあって正解がわからないので、間違っていたらごめんなさい。


サークルページ更新

数年ぶりにサークルのホームページを更新しました(表示がおかしかったらブラウザの更新ボタンを押してね)。

ついでにタブレット/スマートフォンにも対応するよう、可変幅のレスポンシブに。タグも XHTML から HTML5 に変更。テーブルでレイアウトしていたものをフル CSS で書き直したため、ほぼ全ページのプログラム書き直しですが…

ということでやっとこさ新作の予告をアップしました。ていうかこんなんに時間かけるより、絵を描けと…

余談ですが、以前記事に書いたアダルトサイト用の META タグは、最近では以下の一行でいいんですって。

<meta name="rating" content="adult" />

参考:セーフサーチとウェブサイト | Google 検索セントラル

これを <head>~</head> 間に追記すると、Google のセーフサーチが有効な場合に検索結果が制限されるんだとか。早速こちらのブログにも仕込んでおきました。一応、18禁サイトが不意に未成年の目に触れないようにするのもオトナの義務ってことで…


Photoshop CS 5.1 の多角形選択ツール不具合

私が制作に使っているのは何年も前に買った Adobe Creative Suite 5.5。月額制の CC(Creative Cloud)を契約しても、寡作な同人制作では元が取れませんから。

しかし最近絵描きを再開したらなんだか Photoshop CS 5.1 (64 Bit) の挙動がおかしいことに気づきました。多角形選択ツールで選択範囲を追加(Shift キー押しながら再選択)/ 削除 (Alt キー押しながら再選択) することができないんです。範囲選択中に Shift / Alt キーを押すとポイントが打てなくなり、Escape 操作も不能に。なげなわツールは大丈夫なのに。うーん、困りました。

多角形選択ツール

すでにサポート切れの CS ですから修正パッチは期待できません。仕方なく選択範囲をクイックマスクに切り替え、再度選択ツールかけて消したり塗りつぶしたりしていたんですが、すごく面倒。

ググってみたらどうやら Windows アップデートが犯人らしいです。おのれマイク■ソフト。でも以下の解決方法を見つけました。

Adobe Support Comunity – なげなわツール使用中にAltを押しても多角形選択ツールに切り替わらない

なんと Microsoft IME が原因とのこと。結論から言うと IME を以下の手順で古いバージョンに戻したら直りました。Windows 10 のバージョンは 21H1、OSビルド 19043.1348 です。