同時多発的YouTubeライブを1画面で観たいあなたに送るOBSのソース設定

# 経緯
俺はYouTubeでゲーム実況を見るのが日課である。なかでも、 [兄者弟者 \- YouTube](https://www.youtube.com/channel/UC2GuoutVyegg6PUK88lLpjw) の動画をよく見る。
彼らはチームで配信をしているのだが、YouTubeライブを行う際に、チームメンバーで編集担当の[おついち氏](https://www.youtube.com/channel/UC6KnFuHBByTI20VENcsoNjg)と、同時放送することが[たまによくある](https://dic.nicovideo.jp/a/%E3%81%9F%E3%81%BE%E3%81%AB%E3%82%88%E3%81%8F%E3%81%82%E3%82%8B)。

大抵の場合、同時放送が行われているとしても、その両方を同時に見ることは殆どない。どちらかをリアルタイムで見て、もう片方をアーカイブで確認しながら「舞台裏」的な楽しみ方をするものだろうと思う。

ただ、俺はそれを同時にみたいのだ。別に常に監視しているわけでもないので、1画面に両方並んでいても煩わしさはない。しかし、今のYouTubeではそれができない（そういう機能を使った配信を過去に彼らがやっていたのだが、切り替えにラグがあるせいか、それ以降行なっているのを見たことがない。あれは何だったのだろう）。

で。

YouTubeのライブ配信も、所詮は動画データなので、なにかツールを使えば1つにまとめられるのではないか、と考えた。最初はffmpegでゴニョゴニョしようと思ったのだが、入力ソースを自由にレイアウトして表示できるツールがあることを思い出した。[Open Broadcaster Software](https://obsproject.com/ja)である。

# 目的
- 複数の同時配信YouTubeライブを、1つの画面にまとめて表示して、一気観する。

# 必要なもの
- [OBS Studio](https://obsproject.com/ja)
- [youtube\-dl コマンド](https://ytdl-org.github.io/youtube-dl/index.html)
- 観覧したい YouTube ライブのストリーミングURL（.m3u8）

# 1. ストリーミングURLの取得
OBSでYouTubeライブを観覧するには、そのストリーミングのファイルURLが必要になる（.m3u8）。なのでまずはこれを取得する必要があるのだが、このURLは一般にはわかりやすくは公開されていない。
そこで、[youtube\-dl コマンド](https://ytdl-org.github.io/youtube-dl/index.html)を用いて、そのURLを取得する。 [^1]

YouTubeに限らず、様々なオンライン動画配信サイトに対応してる[youtube\-dl](https://ytdl-org.github.io/youtube-dl/index.html)だが、この便利なツールを用いても、一発でURLを取得することができない。なので、段階的に情報を取得しよう。

## 1.1. Format Code の取得

まずは対象の動画のFormat Codeを、下記コマンドで取得する。<動画URL>はYouTubeの動画URLを入力しよう。

```bash
$ youtube-dl -F <動画URL>
```

そうすると、下記のような出力を得られる。この時、一番左にある数字がFormat Codeだ。resolution等を参考に、取得したい解像度のFormat Codeを覚えておく。下記の例で言えば「95」だ。

```
format code  extension  resolution note
91           mp4        256x144    HLS  197k , avc1.42c00b, 30.0fps, mp4a.40.5@ 48k
92           mp4        426x240    HLS  338k , avc1.4d4015, 30.0fps, mp4a.40.5@ 48k
93           mp4        640x360    HLS  829k , avc1.4d401e, 30.0fps, mp4a.40.2@128k
94           mp4        854x480    HLS 1380k , avc1.4d401f, 30.0fps, mp4a.40.2@128k
95           mp4        1280x720   HLS 2593k , avc1.4d401f, 30.0fps, mp4a.40.2@256k (best)
```

YouTubeは、受信環境に合わせて、解像度の異なるデータを配信する仕組みがある。これは、配信可能な解像度のリストだ。たくさん表示されることもあるが、おそらく末尾に```(best)```と書かれているものだけを覚えておけばいい。なので、下記のようにgrepをかけてしまうのも手だろう

```bash
$ youtube-dl -F <動画URL> | grep '(best)'
95           mp4        1280x720   HLS 2593k , avc1.4d401f, 30.0fps, mp4a.40.2@256k (best)
```

## 1.2. m3u8ファイルURLの取得
次に、当該解像度のストリーミングURLを取得する。これも下記のようにコマンドを打つことで取得が可能だ。\<Format Code>は上記1.1.で取得した2〜3桁の数字である。

```bash
$ youtube-dl -f <Format Code> -g <動画URL>
```

そうすると、下記のようなURLが表示される。これが目的のストリーミングURLだ。めっちゃ長いが気にしてはいけない。最後が「.m3u8」となっていれば問題ない。これをどこかにコピペしてメモしておこう。

```
https://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1570982960/ei/0PeiXZvXM46Z4AKk0YMo/ip/60.46.209.197/id/coYw-eVU0Ks.0/itag/96/source/yt_live_broadcast/requiressl/yes/ratebypass/yes/live/1/goi/160/sgoap/gir%3Dyes%3Bitag%3D140/sgovp/gir%3Dyes%3Bitag%3D137/hls_chunk_host/r6---sn-3pm76n7s.googlevideo.com/playlist_duration/30/manifest_duration/30/playlist_type/DVR/initcwndbps/9960/mm/44/mn/sn-3pm76n7s/ms/lva/mv/m/mvi/5/pl/17/dover/11/keepalive/yes/fexp/23842630/mt/1570961239/disable_polymer/true/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,live,goi,sgoap,sgovp,playlist_duration,manifest_duration,playlist_type/sig/ALgxI2wwRgIhALqFA8MLVbU_D-PPVDenZyZuw_MvrIdOZQk0L62nTdhzAiEApTkPKm9snHMmdtDH0zJyyEKUczOuOWL1YLrFg4UOplU%3D/lsparams/hls_chunk_host,initcwndbps,mm,mn,ms,mv,mvi,pl/lsig/AHylml4wRAIgNN3CdLDr2xt96YNnf6GImQ7zDv1AlVoaC5HEMqJRSv8CIBusgbbPS0RHZLlFINBrAmdI_WIqZ6qEzGxwEiEgCyWv/playlist/index.m3u8
```

## 1.3. 必要分繰り返す
OBSに読み込ませたいライブ配信の数だけ、上記を繰り返して、取得しておく。

## 1.X. 手動でやる方法

[youtube\-dl コマンド](https://ytdl-org.github.io/youtube-dl/index.html)を使う方法は便利だが、「黒い画面とかよくわかんない」という人にはそれだけでもハードルが高いだろう。そういう方は、下記の記事を参考に、手動で取得してみてほしい。
- [【手動】Youtubeの動画の\.m3u8ファイルURLを取得する \- Qiita](https://qiita.com/TaigaNatto/items/384318fb73b4f4712f6e)

## 1.Y. コマンド２回打つのが面倒？
コマンド打てるなら、シェル組むなりなんなり好きにすればいい
参考: [シェルスクリプトで関数を利用する \- Qiita](https://qiita.com/kaw/items/034bc4221c4526fe8866)

```bash
# 使い方: $ get_m3u8 <動画URL>
function get_m3u8 {
  FORMAT_CODE=`youtube-dl -F $1 | grep '(best)' | cut -d ' ' -f 1`
  URL=`youtube-dl -f $FORMAT_CODE -g $1`
  echo $URL
}
```

# 2. OBSの設定[^2]
必要なURLが取得できたら、次はOBSの設定である。
ストリーミングデータをOBSで取得するには、「[メディアソース](https://obsproject.com/wiki/Sources-Guide#media-source)」というソースを用いる。これは本来、ローカルファイルを読み込ませるためのものだが、設定画面の「ローカルファイル」チェックボックスをOFFにすることで、オンラインのリソースにも対応できるようになる。

## 2.1. メディアソースの設定
OBSのソース欄の下にある「＋」ボタンを押して、メディアソースを選ぶ。「今回追加するメディアソースの名前（任意）」を入力してOKすると、追加と同時に設定画面が開いてくれる。

メディアソース設定画面が開いたら、上記のように「ローカルファイル」チェックボックスをOFFにして、表示される「入力」の欄に、1.で取得したストリーミングURLの1つを入力しよう。それ以外の設定は特に弄る必要はないが、気になるなら「ネットワークバッファリング」を調整してもいいかもしれない。
設定が終わったら、OKボタンを押そう。

![メディアソース設定画面](https://i.gyazo.com/3f57d3d5e7b53601454911998831a90d.png)」

## 2.2. 画面の位置調整
メディアソースが追加されると、そのメディアのサイズに応じて、自動的に表示サイズが決められる。ただ、これはあくまでデフォルトの状態なので、自分がみやすくなるように調整しよう。バウンディングボックスをドラッグしてリサイズしてもいいし、```Ctrl + e```で数値指定してもいい。

![並べてみた](https://i.gyazo.com/2562f677cb89241b44c5237956d990b6.png)

## 2.3. 必要分繰り返す
OBSに読み込ませたいライブ配信の数だけ、上記を繰り返して表示させる。

## 2.4. オーディオの設定
おそらくデフォルトの状態では、映像は表示されるが音が表示されない、という状態になっているだろう。これはOBSの基本機能なのだが、音声のループバックを防ぐために、基本的にはスピーカーから音が出ないようになっている。ただ、場合によってはそれでは不都合があるし、実際今回のように視聴目的だったりすると、音声が出てくれないと困る。そこで、OBSのオーディオ設定を変更して、スピーカーから音が出るようにしよう。

OBSの下部にある「音声ミキサー」というパネルがある。ここには音声入力ソースの状況が並べられているのだが、そこにある「設定ボタン（歯車のアイコン）」をクリックし、表示されるメニューから「オーディオの詳細プロパティ」を選ぼう。ちなみに「オーディオの詳細プロパティ」は、どの「設定ボタン」から開いても同じものが表示される。

現れたウィンドウをみると「音声モニタリング」というカラムを見つけることができる。音声を出力したい入力ソースの「音声モニタリング」のプルダウンをクリックして、「モニターのみ」を選ぼう。多分「モニターと出力」でも問題はない。今回は配信することが目的ではないので、出力については気にしなくていいのだ。

![オーディオの詳細プロパティ](https://i.gyazo.com/6578f4055121c125d85cac6815fc3d27.png)

# 3. 以上だ
これで、同時配信しているライブを、１画面で観ることができるようになった。後は適当にOBSのウインドウサイズ自体を変えればよいだろう。もしデュアルモニター環境で作業しているのであれば、プレビューエリアを右クリックして「全画面プロジェクター」から、目的の出力先を選ぶことで、OBSのプレビュー画面が別モニターに全画面で表示されるようになる。

![全画面で視聴](https://i.gyazo.com/a058e9cb4536f01b01e8ca7949df464a.png)

# 4. 問題点
実際にやってみて、この方法にはいくつか問題点がある。俺が解決方法に気づいてないのか、それともそもそもそういう機能が提供されていないのかはわからないが、誰か対策がある方は是非コメントで教えていただきたい。

## 4.1. 同期/シークできない
同時配信しているライブとはいえ、時間がピッタリ同期されているとは限らない。おそらくは微妙なズレが生じているだろう。ただ、OBSのメディアソースには、このあたりの調整をする設定項目がないのだ。
メディアソースの設定画面を見ると、一番下に「シーク可能」というチェックボックスがある。これをONにしてみたのだが、特にシーク用のUIが表示されることはなかった。

OBSのフォーラムなどを見ていると「[ソースがVLCならできるよ](https://obsproject.com/forum/threads/control-media-source-playback.27804/#post-349087)」みたいなことが書かれていたのだが、だとすれば今回の目的には則さない機能ということになりそうだ。

ちなみに、見出しは「シークができない」としたが、もうちょっと正確に言うと「動画の再生コントロールができない」である。つまり、一時停止/再生などもできない。


### 追記
同時配信の同期には、先に進んでいる方に遅延をつけることで、大枠同期しているように見せることはできる。OBSには、映像/音声フィルターという機能があり、入力ソース単位でそのフィルターを掛けられるのだが、そのフィルターにある「映像の遅延（非同期）」を用いることで、これを実現できるようだ。ただし、１フィルターにつき最大20,000msまでしか指定できないので、それを超える時間差があるようであれば、複数同時に掛ける必要がある。また、遅延するのは「映像のみ」なので、音声は遅れている方の音声を再生しよう。



[^1]: [youtube\-dl コマンド](https://ytdl-org.github.io/youtube-dl/index.html)の基本的な使い方については、ここでは触れない。
[^2]: [OBS Studio](https://obsproject.com/ja)の基本的な使い方については、ここでは触れない。