カテゴリー: プログラム

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’)はブラウザ キャッシュからロードが行われるので読み込みにネットワークの遅延は出ないようです。

めでたしめでたし。


WordPress で自動ギャラリーページ

らくがき置き場

以前のブログにあった「ギャラリー」ページですが、WordPress 更新でプラグインが動かなくなってしまったので久方止めていました。でも「あれ? この画像、前にも上げなかったっけ」と思うことがあり、最近の WordPress はメディアライブラリも一気に一覧表示されなくなったので、確認にちょっと不便。

元々使っていたプラグインは特定のカテゴリーに投稿した画像を一気に抜いて表示するものだったんですが、他のを探してもそれっぽいのがない。WordPress のギャラリー機能を使おうにも、過去画像に遡ってタグ付けしないとならないようで、ちょー面倒。

結局、固定ページのテンプレートを自作しちゃいました(笑) 2日ぐらいかかったので、素直にメディアライブラリでタグ付けした方が良かったかも…

→らくがき置き場

でも記事をカテゴリー分けするだけで、勝手に固定ページに投稿画像が追加されるので便利ですよ。たぶん。

需要はないかもですが、主要な部分のソースコード(page-gallery.php)置いておきますね。一応、出力タグは <figure> とか使って Gutenberg に遵守。なお前後のコードは使用中のテーマファイルの page.php に合わせないと、デザインが崩れると思うのであしからず。


Adobe Animate CC(旧Flash Professional CC)の不具合メモ

現在作成中のゲームはFlash Professional CCを使ってAdobe Air で開発していますが、先日Flash ProfessionalがAdobe Animate CCに名称変更されました。
で、インストールして試してみましたが致命的なバグがあったのでメモしておきます。

  • 作成しているAriアプリケーションの内容
    XMLに記述されているファイル一覧を元に外部ファイルを読み込みユーザーの操作に応じて適宜再生表示する。
  • 不具合発生の経緯
    Adobe Animate CCからAri インストーラーを書き出してインストール実行しAir アプリケーションを起動しても、自動で読み込まれるはずのファイルが読み込まれず停止する。
  • 不具合の考察
    試しにインストール先のフォルダに読み込むファイルを全部コピーすると正常に起動するのでファイル名が異常かファイル一覧の文字化けのどちらかが疑われる。
  • と言う事で外部ファイルが入っているフォルダをエクスプローラーで開くと一部、全く同名のファイルが2つ存在する!と言うなかなかシュールな絵面になっている事を発見。

    Adobe AnimateCCの不具合

    Adobe AnimateCCの不具合

と言う事でコマンドプロンプトで「Dir」を掛けてみるとファイル名が2バイト文字かつ「濁点、半濁点」を含んでいた場合に元の文字+「゛」または「゜」と言う感じにファイル名が変わっている事が判明(ただし、エクスプローラーでは正しいファイル名の様に見える)

Flash Professionalではこのような現象は発生していないので当面はFlash Professionalに戻して開発を続けてます。

まぁファイル名に2バイト文字を使うなって話かもしれませんが、やらなくても良いアップデートでファイル操作と言う基本的な個所にバグを混入してくるのはマジ勘弁って感じです。


AEアニメについての知見

開発中のゲームは「いじりゲー」にカテゴライズされます。
そして「いじりゲー」に不可欠なのがエロいアニメーションです。
ご存じのとおりアニメには2Dと3Dがあり、当方的には今から使い慣れたツールであるPhotoshopのデーターからアニメーションを起こせるAfterEffectsを使って2Dアニメを作るのが一番リーズナブルかなと考え、ここ数年試行錯誤を繰り返してきました。
ところがWebでAEアニメ関連のノウハウを探してもあまり見つからないんですよね。
なので、覚書も兼ねて当方の気付いたことを書いておこうかなと思います。

  1. 絵を作りこむPSDとAEに読み込むPSDは別物にする。
    これは読み込んだ時点には存在していたレイヤーがなくなった場合など、PSDのレイヤー構造が途中で変わるとAE側でエラーが出る事を防ぐ事が目的です。
    例えば、img_101_org.psdをコピーしてレイヤーやレイヤーグループを整理したimg_101_integrated.psdを作成してAEにはこれを読み込ませます。
    AEの読み込んだ後にPSDを変更する必要が生じたときはimg_101_org.psdを修正して修正したレイヤーをimg_101_integrated.psdに複製して再統合、レイヤー名を合わせて保存すると、AE側で開いたときエラーもなく変更が反映された状態になります。
  2. AEに読み込むPSDはレイヤーグループをなるべく使わずシンプルにする。
  3. 絵を作りこむPSDの塗はグループマスクを使う
    AEに読み込ませる絵は一枚絵の場合とは異なり動く部分の影になる所まで書き込む必要があります。そのため、例えば手や足の絵と胴体のレイヤーを分けて描かなくてはなりません。
    またレイヤー分けした手足と胴体は主線が無い場合がほとんどなので「アルファ―チャネルで滑らかに繋げる」ことが必須です。
    通常肌の塗等は複数レイヤーを使う方が多いと思うのですが、各レイヤー毎にやわらかい消しゴムで消してしまうと作業が増えるだけでなく、レイヤー毎でボケ足が統一できない等の不具合が起きます。
    その場合は複数ある塗りのレイヤーをレイヤーグループにまとめレイヤーグループにボケ足の着いたマスクを掛ける事で回避できます。

あと、AEではなくてFlashのActionScript3のTipですがマウスイベントは複数のイベントリスナーを設定した場合、イベントが伝わるのに「時差」がある事を最近発見しました。
しかも、その時差は実行するパソコンの処理能力に左右されるのでタイミングが関係するような処理はイベントリスナーを複数使うと意図した動作に「ならない場合」があります。
(ただし、これはマウスイベントに限定した現象らしく他のイベントでは発生しないみたいです)

最近は「Live2D」や「Spine」などPSDからアニメーションを起こすツールも増えてきましたがこの覚書の内容はAE以外でも通用するのではないかと思います。(と言うか最近Adobeの品質劣化が激しいのでCLIP STUDIOSpineUNITY に移行してやろうか等と考えている当方だったりします)