rch850 の上澄み

技術的な話題とか、雑談とか。タイトルを上澄みに変えました @ 2020/09/02

世にも奇妙な Safari の audio 要素の挙動

audio 要素というか HTMLAudioElement ってありますけど、あれの play 関数の挙動が Safari だとえらい奇妙だったって話です。ちなみに macOS, iOS どちらの Safari も同じでした。

2回目以降の play の再生開始が遅延する

Safari で次の codepen の Play を押して再生すると「さん、に、いち、はい」と聞こえます。再生が終わってもう一度 Play を押すと「ぁん、に、いち、はい」と、最初の s が聞こえません。new AudioContext() ボタンを押すと、この問題が起こらなくなります。

See the Pen Safari HTMLAudioElement.play delay bug by rch850 (@rch850) on CodePen.

codepen にも書いてますが、StackOverflow の HTML5 Audio tag on Safari has a delay のコメントにこのソリューションが書いてありました。なぜ直るかはわからないそうですが、とにかく直ります。

ちなみに、AudioContext をいくつも new してるとエラーになった記憶があるし、そういったことを言っている2015年の記事もあって、無尽蔵に new するのはいけないと思っていたのですが、今は100個作ってもエラーにならないようです。とはいえ不必要に何個も作るのは避けたほうがいいでしょう。

多分 python -m http.server で立てたサーバが返した mp3 だと2回目以降再生されない

遅延どころか再生できないのかよって話なんですが、できないんです。じゃぁ最初の遅延に気づいたのはなぜかっていうと、そっちは npm run serve 的なもので見てたからです。

最初は localhost 限定の現象かと思ったのですが、ngrok を通してちゃんとしたドメインかつ https にしても変わらなかったので、これは python の http.server のせいだな、と勘付きました。

audio 要素の src に指定する URL を外部の URL にすれば鳴るので、src に指定するファイルの供給のされ方に原因があると推測しました。

python -m http.server する代わりに npx http-server したら直りました。

まとめ

  • Safari で HTMLAudioElement (audio タグ) の動作に奇妙なところがある。
  • 2回目以降の play の再生開始が遅延する → new AudioContext() すればよい。
  • 2回目以降の play で再生されない → python -m http.server を使っているなら npx http-server など他の手段にするといい。