はじめに
ATEM Mini製品(Pro/Pro ISO/Extreme/Extreme ISO)からネットワーク経由でHDMI映像を送信できるATEM Stream Bridgeを購入して、RTMPプロトコルを使用しているので、OBS Studioからもつながるだろうと予想していたら、残念ながらつながらなかった。(ATEM Mini製品しかつながらなかった。)
ラズパイ(Raspberry Pi)にNginx + RTMP module + OMXPlayerをインストールして、ATEM Streaming Bridgeと同じことができると知って試してみたところ、遅延が非常に大きい。(こちらはOBS Studioもつながりました。)
調査に着手
まず、ATEM Streaming Bridgeの実装を調べるため筐体を開けたところ、xilinx Zynq-7000 SoC (Z7015)が使用されていることがわかりました。
手がかりが掴めないまま、次にポートミラー機能が付いたギガビットスイッチを使用して、Wiresharkでプロトコルキャプチャーを取得しました。
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
[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
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を修正する必要があります。修正内容は以下のとおりです。
$ 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のビルド手順は公式ページを参照してください、)
OBS Studioの配信設定
「配信」項目は、カスタム設定でATEM Streaming BridgeのIPアドレスとURIにappを指定します。
「出力」項目は、出力モードを簡単→詳細へ変更し、配信タブのプロファイルはmainを選択します。
(プロファイルを指定しなかったり、main以外を指定するとATEM Streaming BridgeからのHDMI出力がカラフルな砂嵐みたいな映像になりました。)
「映像」項目は、出力(1920x1080)とFPS共通値(24、30、60)を設定します。
結果
無事にOBS StudioからATEM Streaming Bridgeへ出力できました。
Camera2: ATEM Streaming Bridge
Camera3: OBS Studio (Jetson Nano)
ラズパイ(Nginx + RTMP module + OMXPlayer)よりも遅延が少なくて良い感じです。
では、良き配信ライフを!