OBS StudioからATEM Streaming Bridgeへ出力する方法

# はじめに

ATEM Mini製品(Pro/Pro ISO/Extreme/Extreme ISO)からネットワーク経由でHDMI映像を送信できるATEM Stream Bridgeを購入して、RTMPプロトコルを使用しているので、OBS Studioからもつながるだろうと予想していたら、残念ながらつながらなかった。(ATEM Mini製品しかつながらなかった。)

![スクリーンショット 2021-03-24 22.43.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/1af9d9a3-1005-0feb-a00e-d4f15bf06f57.png)

ラズパイ(Raspberry Pi)にNginx + RTMP module + OMXPlayerをインストールして、ATEM Streaming Bridgeと同じことができると知って試してみたところ、遅延が非常に大きい。(こちらはOBS Studioもつながりました。)

https://qiita.com/kitazaki/items/6b9ad47dcba70329eb8e

# 調査に着手

まず、ATEM Streaming Bridgeの実装を調べるため筐体を開けたところ、xilinx Zynq-7000 SoC (Z7015)が使用されていることがわかりました。

![ExDSeuyVEAAL58H.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/d35087d4-62e1-55b8-0302-e300b80d5663.jpeg)

![ExKUnnpUUAUuQnH.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/8a001975-02ea-f548-a144-68a643a2e674.jpeg)

手がかりが掴めないまま、次にポートミラー機能が付いたギガビットスイッチを使用して、Wiresharkでプロトコルキャプチャーを取得しました。

![ExGAH07VEAYxGqJ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/c03dfd4f-81c2-55e8-ca4b-2e65a6b7d8a5.jpeg)

https://note.com/kitazaki/n/n79c6c20af213

![スクリーンショット 2021-03-22 20.48.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/08d009a6-5708-5eee-86ef-4d886949073c.png)

# ATEM Mini Pro/ExtremeとOBS StudioのRTMPパラメータの差分

一見すると、通常のRTMPプロトコルのように見えますが、OBS StudioからATEM Streaming Bridgeへ接続すると、ハンドシェイク→connect()→createStream()→publish()→＠setDataFrame()の次にATEM Streaming Bridgeから切断(TCP reset)されていました。
＠setDataFrame()は以下の差分がありました。

### ATEM Mini Pro/Extreme

```text:
[verbose] RTMP_ClientPacket, received: notify 371 bytes
[verbose] (object begin)
[verbose] Property: <Name:           no-name., STRING:    onMetaData>
[verbose] Property: <Name:           no-name., ECMA_ARRAY>
[verbose] (object begin)
[verbose] Property: <Name:                2.1, BOOLEAN:    FALSE>
[verbose] Property: <Name:                3.1, BOOLEAN:    FALSE>
[verbose] Property: <Name:                4.0, BOOLEAN:    FALSE>
[verbose] Property: <Name:                4.1, BOOLEAN:    FALSE>
[verbose] Property: <Name:                5.1, BOOLEAN:    FALSE>
[verbose] Property: <Name:                7.1, BOOLEAN:    FALSE>
[verbose] Property: <Name:      audiochannels, NUMBER:    2.00>
[verbose] Property: <Name:       audiocodecid, STRING:    mp4a>
[verbose] Property: <Name:      audiodatarate, NUMBER:    64.00>
[verbose] Property: <Name:    audiosamplerate, NUMBER:    48000.00>
[verbose] Property: <Name:    audiosamplesize, NUMBER:    16.00>
[verbose] Property: <Name:           duration, NUMBER:    0.00>
[verbose] Property: <Name:            encoder, STRING:    Blackmagic Design AVC Encoder>
[verbose] Property: <Name:           fileSize, NUMBER:    0.00>
[verbose] Property: <Name:          framerate, NUMBER:    60.00>
[verbose] Property: <Name:             height, NUMBER:    1080.00>
[verbose] Property: <Name:             stereo, BOOLEAN:    TRUE>
[verbose] Property: <Name:       videocodecid, STRING:    avc1>
[verbose] Property: <Name:      videodatarate, NUMBER:    9000.00>
[verbose] Property: <Name:              width, NUMBER:    1920.00>
[verbose] (object end)
[verbose] (object end)
```

### OBS Studio

```text:
verbose] RTMP_ClientPacket, received: notify 387 bytes
[verbose] (object begin)
[verbose] Property: <Name:           no-name., STRING:    onMetaData>
[verbose] Property: <Name:           no-name., ECMA_ARRAY>
[verbose] (object begin)
[verbose] Property: <Name:           duration, NUMBER:    0.00>
[verbose] Property: <Name:           fileSize, NUMBER:    0.00>
[verbose] Property: <Name:              width, NUMBER:    1920.00>
[verbose] Property: <Name:             height, NUMBER:    1080.00>
[verbose] Property: <Name:       videocodecid, NUMBER:    7.00>
[verbose] Property: <Name:      videodatarate, NUMBER:    2500.00>
[verbose] Property: <Name:          framerate, NUMBER:    25.00>
[verbose] Property: <Name:       audiocodecid, NUMBER:    10.00>
[verbose] Property: <Name:      audiodatarate, NUMBER:    160.00>
[verbose] Property: <Name:    audiosamplerate, NUMBER:    48000.00>
[verbose] Property: <Name:    audiosamplesize, NUMBER:    16.00>
[verbose] Property: <Name:      audiochannels, NUMBER:    2.00>
[verbose] Property: <Name:             stereo, BOOLEAN:    TRUE>
[verbose] Property: <Name:                2.1, BOOLEAN:    FALSE>
[verbose] Property: <Name:                3.1, BOOLEAN:    FALSE>
[verbose] Property: <Name:                4.0, BOOLEAN:    FALSE>
[verbose] Property: <Name:                4.1, BOOLEAN:    FALSE>
[verbose] Property: <Name:                5.1, BOOLEAN:    FALSE>
[verbose] Property: <Name:                7.1, BOOLEAN:    FALSE>
[verbose] Property: <Name:            encoder, STRING:    obs-output module (libobs version 26.1.0)>
[verbose] (object end)
[verbose] (object end)
```

# OBS Studioのコード修正

＠setDataFrame()の差分箇所を変更するためには、/plugins/obs-outputs/flv-mux.cを修正する必要があります。修正内容は以下のとおりです。

```bash
$ diff flv-mux.c flv-mux.c_org
72,73d71
< 	struct dstr videocodecid_name = {0};
< 	struct dstr audiocodecid_name = {0};
89,93c87
< //	enc_num_val(&enc, end, "videocodecid", VIDEODATA_AVCVIDEOPACKET);
< 	dstr_printf(&videocodecid_name, "avc1");
< 	enc_str_val(&enc, end, "videocodecid", videocodecid_name.array);
< 	dstr_free(&videocodecid_name);
< 
---
> 	enc_num_val(&enc, end, "videocodecid", VIDEODATA_AVCVIDEOPACKET);
97,101c91
< //	enc_num_val(&enc, end, "audiocodecid", AUDIODATA_AAC);
< 	dstr_printf(&audiocodecid_name, "mp4a");
< 	enc_str_val(&enc, end, "audiocodecid", audiocodecid_name.array);
< 	dstr_free(&audiocodecid_name);
< 
---
> 	enc_num_val(&enc, end, "audiocodecid", AUDIODATA_AAC);
118c108
< 	dstr_printf(&encoder_name, "Blackmagic Design AVC Encoder");
---
> 	dstr_printf(&encoder_name, "%s (libobs version ", MODULE_NAME);
120,125c110,115
< // #ifdef HAVE_OBSCONFIG_H
< //	dstr_cat(&encoder_name, OBS_VERSION);
< //#else
< //	dstr_catf(&encoder_name, "%d.%d.%d", LIBOBS_API_MAJOR_VER,
< //		  LIBOBS_API_MINOR_VER, LIBOBS_API_PATCH_VER);
< //#endif
---
> #ifdef HAVE_OBSCONFIG_H
> 	dstr_cat(&encoder_name, OBS_VERSION);
> #else
> 	dstr_catf(&encoder_name, "%d.%d.%d", LIBOBS_API_MAJOR_VER,
> 		  LIBOBS_API_MINOR_VER, LIBOBS_API_PATCH_VER);
> #endif
127c117
< //	dstr_cat(&encoder_name, ")");
---
> 	dstr_cat(&encoder_name, ")");
```

修正済のflv-mux.cをgithubに置きました。
https://github.com/kitazaki/OBS-Studio_for_ATEM_Streaming_Bridge

# OBS Studioのビルド

ラズパイ、Jetson NanoでのOBS Studioのビルド手順はこちらです。(WindowsとmacOSのビルド手順は公式ページを参照してください、)

https://qiita.com/kitazaki/items/36b9f9ba80cec12164f9

https://qiita.com/kitazaki/items/fe037d195f497eb54427

https://qiita.com/kitazaki/items/3950c48a68bab1766fb6

# OBS Studioの配信設定

「配信」項目は、カスタム設定でATEM Streaming BridgeのIPアドレスとURIにappを指定します。

![Screenshot_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/1014f8fa-b4dd-898f-5fc3-af1b70a45124.png)

「出力」項目は、出力モードを簡単→詳細へ変更し、配信タブのプロファイルはmainを選択します。
(プロファイルを指定しなかったり、main以外を指定するとATEM Streaming BridgeからのHDMI出力がカラフルな砂嵐みたいな映像になりました。)

![Screenshot_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/5237e8ff-409c-2884-ee41-7efb5bbb08fc.png)

「映像」項目は、出力(1920x1080)とFPS共通値(24、30、60)を設定します。

![Screenshot_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/71c31380-9fe9-45c5-61da-c02b72a2f551.png)

# 結果

無事にOBS StudioからATEM Streaming Bridgeへ出力できました。
Camera2: ATEM Streaming Bridge
Camera3: OBS Studio (Jetson Nano)
ラズパイ(Nginx + RTMP module + OMXPlayer)よりも遅延が少なくて良い感じです。

では、良き配信ライフを！

<iframe width="560" height="315" src="https://www.youtube.com/embed/Un2gZhHbCEY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>