console.lealog();

@leader22のWeb系に関する勉強めもブログですのだ

iOSのSafariでvideoを複数再生したい

もちろん音ありで。

いわゆる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`再生しても全部見れんわ!っていう前提のもと。

まあこれはこれで良い解決策だとは思う。