スマートフォン向けのページで音を鳴らす方法は、大きく分けて audio 要素と Web Audio API の 2 つです。どちらを使う場合も、自動再生の決まりや端末ごとの制限を知っておかないと、「パソコンでは鳴るのに、スマートフォンでは鳴らない」ということになります。ここでは、これまでの記事の内容を含めて、スマートフォンの Web で音を鳴らすときの要点をまとめます。
audio 要素と Web Audio API の使い分け
| audio 要素 | Web Audio API | |
|---|---|---|
| 向いている音 | BGM、話し声、長い音声 | 効果音、短い音の繰り返し |
| 読み込み | 少しずつ読みながら再生できる | 全体を読み込んで展開してから鳴らす |
| 重ねて鳴らす | 苦手 (要素を増やすと不安定) | 得意 (同じ音をいくつでも重ねられる) |
| タイミング | 多少ずれる | 細かく指定できる |
| 再生ボタンなどの部品 | controls で用意される | 自分で作る |
audio 要素は、ファイルを少しずつ読みながら再生できるので、長い音声に向いています。controls 属性を付ければ、再生ボタンやシークバーもブラウザーが用意してくれます。
Web Audio API は、音声データをメモリに展開しておき、JavaScript から鳴らす仕組みです。鳴らすまでの遅れが小さく、同じ音を重ねて鳴らしたり、start() に時刻を渡して鳴らすタイミングを細かく決めたりできます。ゲームの効果音や、リズムに合わせた音に向いています。
// 0.5 秒おきに 4 回、同じ音を鳴らす (context と buffer は用意してあるものとする)
const now = context.currentTime;
for (let i = 0; i < 4; i++) {
const source = context.createBufferSource(); // 音源のノードは鳴らすたびに作る
source.buffer = buffer;
source.connect(context.destination);
source.start(now + i * 0.5); // 鳴らす時刻を秒で指定する
}
ただし、音声データは展開すると元のファイルよりずっと大きくなります。長い音声を全部展開するとメモリを多く使うので、BGM は audio 要素に任せるのが無難です。
自動再生には利用者の操作が要る
今のスマートフォンのブラウザーでは、音の出る再生を、利用者の操作 (タップなど) 無しに始めることはできません。audio 要素の play() も、Web Audio API の AudioContext も、最初の操作の中で再生や resume() を呼ぶ必要があります。音を消した動画の自動再生は許されます。
play() は Promise を返すので、失敗したときに再生ボタンを見せるようにしておきます。どこまでが「操作に続く処理」と見なされるかは、「音声の再生は、利用者の操作の中で始める」で詳しく説明しています。
形式と配信
形式は、MP3 か AAC (.m4a) を用意しておけば、今の主なブラウザーで再生できます。容量を抑えたい場合は Opus などを先に、MP3 を最後にして、audio 要素の中に source 要素を並べます。対応の確かめ方は「Android のブラウザーで音声を再生する」にまとめました。
再生できない原因が、配信する側にあることもあります。プログラムを通して音声を返していると、範囲を指定した要求 (Range リクエスト) に答えられず、Safari で再生できないことがあります。「スマートフォンで音声を再生・シークできないときは、配信のしかたを疑う」を参照してください。
iOS の音量とマナーモード
iOS では、audio 要素の volume プロパティを変えられません。読み取るといつも 1 が返り、音量は端末の音量ボタンで利用者が決めます。ページの中で音量を調整したい場合は、Web Audio API の GainNode を通します。詳しくは「iPhone の Safari で音を鳴らすときの制限と対処」を参照してください。
マナーモード (消音の設定) にしているときに、ページの音が鳴るかどうかは、端末や OS の版、鳴らし方によって違います。audio 要素の音は鳴るのに、Web Audio API の音は鳴らない、といった違いが出ることもあります。音が鳴らないと操作の結果が分からない作りは避け、音と一緒に画面の表示でも結果を伝えるようにします。
かつては Flash で鳴らしていた
audio 要素がまだ広く使えなかったころ、パソコン向けのサイトでは、Flash (Adobe Flash Player で動く仕組み) で音を鳴らすのが一般的でした。ActionScript で効果音を重ねたり、再生の位置を細かく制御したりでき、ブラウザーの違いも気にせずに済んだからです。
しかし、iPhone の Safari は Flash に対応せず、Android でも Flash Player を使えたのは一部の時期・機種に限られました。スマートフォンで音を鳴らすには、audio 要素に頼るしかなかったのです。その後、Web Audio API が広まり、Flash でしていたことの多くはブラウザーだけでできるようになりました。Flash Player は 2020 年末にサポートが終わっていて、今は使えません。Flash で音を鳴らしていたページは、audio 要素や Web Audio API で作り直します。
まとめ
- BGM や長い音声は
audio要素、効果音や重ねて鳴らす音は Web Audio API を使う - 音の出る再生は、利用者の操作の中で始める。
play()の失敗を捕まえ、AudioContextは最初の操作でresume()する - 形式は MP3 か AAC を用意する。
source要素を並べれば、ブラウザーが再生できるものを選ぶ - iOS では
volumeを変えられない。音量の調整はGainNodeで行う - マナーモードのときに鳴るかどうかは端末しだい。音だけに頼らず、画面でも結果を伝える
- Flash はスマートフォンで使えず、2020 年末にサポートも終わった