もちろん音ありで。
いわゆるWebRTCでの複数人ビデオチャットみたいなケース。
ただ普通に動画ファイルでもHLSでもなんでも、複数同時再生したいならこの問題にハマるはず。
現状の縛り
現時点のiOS Safari(確認したのはiOS 11なのでSafari 11)で、`video`を複数再生するためには、いくつかの条件がある。
- 無音であること
- `video.muted = true`にする
- Audioのトラックが元々含まれないメディアである
- `playsinline`が効くこと
- 古いほうのWebViewだと使えないとかなかったっけ?(覚えてない)
この両方に当てはまる場合なら、複数の`video`を同時に再生できる。
ちなみに、自動再生はまた別のトピックなので割愛。
問題
WebRTCなコードで頻出するコレ。
video.autoplay = video.playsInline = true;
video.srcObject = stream;
リモートのピアから送られてきたストリームを、`video`で再生したい。
もちろんカメラ映像だけでなく、マイク音声も乗ってるストリーム。
ただこれだと最初に書いたように、無音でないため同時に再生できない。
2つ目以降を再生しようと(`srcObject`に代入)すると、それまで再生されてた`video`が止まって、最後に再生しようとした`video`だけが音ありで再生される。
もちろん`muted`にしてる場合は、複数の`video`は再生できるので、映像だけは届く。ただし音がでない。意味ない。
別にWebRTCだからではなく、普通の動画ファイルでさえも、複数同時に再生することはできない。
どうにかするには
`video`は`muted`で再生できるようにしつつ、`audio`で音を鳴らす。
// さっきのコードに加えて // 必ずミュート video.muted = true; video.srcObject = stream; // 音はaudioで audio.autoplay = true; audio.srcObject = stream;
これだと、思った通りに動作する。
<!-- これの代わりに --> <video src="" playsinline autoplay /> <!-- こうするってこと --> <video src="" muted playsinline autoplay /> <audio src="" autoplay />
現時点ではコレが一番リーズナブルな選択肢かなーと。
おそらくWebAudioで再生する方式でもいけるけど、根本的には同じなので、個人的には特にやる意義が見いだせない。
昔のAndroidで、`video`と`audio`を使って2chで音を鳴らそうと頑張ってた時のことを思い出して悲しくなった。
おまけ
なんとか`video`だけでやれんかと考えて試したあれこれ。
まず`muted`で再生してから解除
WebRTCで取ってきたストリームではなく、ローカルにある動画ファイルで試した。
すると、
- `loop autoplay playsinline`な`video
- すべて無音で再生される
- すべて`muted = false` にする
- そのループ中だけは音ありで再生できる
- 2ループ目からは、1つの`video`を残して再生が止まる
なにこのバグっぽい動き。
`video`はひとつ、あとは`canvas`で
見えてる要素としての`video`を1つだけにして、後は裏方で`canvas`に書けばいいのでは?作戦。
- `video`は1つなので音ありで再生できる
- `canvas`は音がでないので、裏でWebAudioか`audio`で音を出す
- 実質、JavaScriptで音を担当するパターンと同じ
- `audio`タグ併用パターンのがコスパがいい
まあなんというか試す時間の無駄だった。
音を出す`video`は1つにする
UIと相談できるなら。
そもそもモバイルで表示領域も少ないし、複数`video`再生しても全部見れんわ!っていう前提のもと。
まあこれはこれで良い解決策だとは思う。