FFmpegでSRTを確認する
いまさらながら、FFmpegでSRT(Secure Reliable Transport)をサポートしていることを知ったので動作確認してみた。
参考URL
SRT
FFmpeg+SRT
当初は正しく動作させることができず、ChatGPTに聞きながら、トライ&エラーを実施。
インストール
Windows
下記を参考にインストール
Linux(Lubuntu)
ここはノーコメント。
$ apt -y install ffmpeg
やること
SRTを利用して、下記を実施。
- 動画ファイルの転送
- リアルタイムに動画を転送
- 途中経路でパケットをロスさせ、SRTの再送などを確認
環境
Windows PC(Macですが)上のVM(Lubuntu)から、ホストであるWindowsにSRTによる通信(転送)を実施。また、VM上のI/Fである”enp0s3”でパケットをロスさせる。
FFmpegコマンド
利用したコマンド+オプションを紹介。
カメラ情報
コマンドで指定するカメラ情報を取得する。なおオプションの詳細(説明)は、参考URLなどを参照されたし。
Windows
まずはカメラ名を見つける。
>ffmpeg -list_devices true -f dshow -i dummy
[dshow @ 00000258222ce400] "FaceTime HD Camera" (video)
[dshow @ 00000258222ce400] Alternative name "@device_pnp_\\?\pci#ven_14e4&dev_1570&subsys_157014e4&rev_00#000000ffff00000000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\global"
[dshow @ 00000258222ce400] "Internal Microphone (Cirrus Logic CS4208 (AB 126))" (audio)
[dshow @ 00000258222ce400] Alternative name "@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\wave_{6EF45010-B330-48B3-8C88-9D30D7580AB8}"
- -f dshow:入力フォーマットWindowsのカメラ/オーディオデバイス(DirectShow)
- -list_devices true:デバイス一覧表示
- -i dummy:ダミー入力(表示のみ)
”FaceTime HD Camera”が用いるPCのカメラデバイスとなる。”FaceTime HD Camera”の能力は下記のとおり。
>ffmpeg -f dshow -list_options true -i video="FaceTime HD Camera"
[dshow @ 0000020a5e70f2c0] DirectShow video device options (from video devices)
[dshow @ 0000020a5e70f2c0] Pin "キャプチャ" (alternative pin name "0")
[dshow @ 0000020a5e70f2c0] pixel_format=yuyv422 min s=320x240 fps=30 max s=320x240 fps=30
[dshow @ 0000020a5e70f2c0] pixel_format=yuyv422 min s=640x480 fps=30 max s=640x480 fps=30
[dshow @ 0000020a5e70f2c0] pixel_format=yuyv422 min s=1280x720 fps=30 max s=1280x720 fps=30
- -f dshow:入力フォーマットWindowsのカメラ/オーディオデバイス(DirectShow)
- -list_options true:カメラ能力表示
- -i video="FaceTime HD Camera":カメラデバイス
Lubuntu
カメラデバイスを見つける。
$ v4l2-ctl --list-devices
VirtualBox Webcam - FaceTime HD (usb-0000:00:06.0-2):
/dev/video0
/dev/video1
/dev/media0
コマンド(v4l2-ctl)は、Windowsと異なる。”--list-devices”により対応デバイスファイルを見つける。通常、”/dev/video0”を使えばいいらしい。カメラデバイスの能力は下記となる。
$ ffmpeg -f v4l2 -list_formats all -i /dev/video0
[video4linux2,v4l2 @ 0x637c773d8380] Compressed: mjpeg : Motion-JPEG : 320x240 640x480 1280x720
v4l2-ctl --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
Type: Video Capture
[0]: 'MJPG' (Motion-JPEG, compressed)
Size: Discrete 320x240
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 640x480
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
Size: Discrete 1280x720
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.050s (20.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Interval: Discrete 0.100s (10.000 fps)
Interval: Discrete 0.200s (5.000 fps)
- -f v4l2:入力フォーマットVideo4Linux2
- -list_formats all:対応フォーマット表示
- -i /dev/video0:カメラデバイス
待ち受け(受信側)
Windows、Lubuntu共通である。画面上に動画が表示される。
ffplay -fflags nobuffer -autoexit "srt://192.168.56.1:8888?mode=listener"
- 192.168.56.1:待ち受けする機器のIPアドレス
- 8888:ポート番号
- mode=listener:待ち受け
- -fflags nobuffer:バッファを減らして低遅延化
- -autoexit:転送完了後プログラムを終了
ファイル転送(送信側)
こちらもWindows、Lubuntu共通である。
ffmpeg -re -i ファイル -f mpegts srt://192.168.56.1:8888
- 192.168.56.1:送信先機器のIPアドレス
- 8888:ポート番号
- -i:送信する動画ファイル名
- -re:リアルタイムで入力を読む(ストリーミング向け)
- -f mpegts:出力フォーマットをMPEG-TSに指定(ストリーミングやデジタル放送向け)
リアルタイム転送(送信側)
Windows
ffmpeg -f dshow -video_size 640x480 -framerate 30 -pixel_format yuyv422 -i video="FaceTime HD Camera" -pix_fmt yuv420p -c:v libx264 -preset ultrafast -f mpegts "srt://192.168.56.1:8888?pkt_size=1316"
- -f dshow:入力フォーマットWindowsのカメラ/オーディオデバイス(DirectShow)
- -video_size 640x480:解像度
- -framerate 30:フレームレート(1秒間に30フレーム)
- -pixel_format yuyv422:ピクセルフォーマットyuyv422(YUYV 4:2:2)
- -i video="FaceTime HD Camera": カメラデバイス
- -pix_fmt yuv420p:出力フォーマットyuv420p(YUV 4:2:0)
- -c:v libx264:ビデオコーデックH.264
- -preset ultrafast:エンコード速度を最速(低遅延化)
- -f mpegts:出力フォーマットMPEG-TS(SRT向け)
- 192.168.56.1:転送先IPアドレス
- 8888:転送先ポート
- pkt_size=1316:パケットサイズ1316(MPEG-TS向け)
Lubuntu
ffmpeg -f v4l2 -video_size 640x480 -framerate 30 -input_format yuyv422 -i /dev/video0 -pix_fmt yuv420p -c:v libx264 -preset ultrafast -f mpegts "srt://192.168.56.1:8888?pkt_size=1316"
- -f v4l2:入力フォーマットVideo4Linux2
- -video_size 640x480:解像度
- -framerate 30:フレームレート(1秒間に30フレーム)
- -pixel_format yuyv422:ピクセルフォーマットyuyv422(YUYV 4:2:2)
- -i /dev/video0: カメラデバイス
- -pix_fmt yuv420p:出力フォーマットyuv420p(YUV 4:2:0)
- -c:v libx264:ビデオコーデックH.264
- -preset ultrafast:エンコード速度を最速(低遅延化)
- -f mpegts:出力フォーマットMPEG-TS(SRT向け)
- 192.168.56.1:転送先IPアドレス
- 8888:転送先ポート
- pkt_size=1316:パケットサイズ1316(MPEG-TS向け)
ファイル作成(参考)
Windows
ffmpeg -f dshow -video_size 640x480 -framerate 30 -pixel_format yuyv422 -i video="FaceTime HD Camera" -pix_fmt yuv420p -c:v libx264 -preset ultrafast -t 10 ファイル
- -f dshow:入力フォーマットWindowsのカメラ/オーディオデバイス(DirectShow)
- -video_size 640x480:解像度
- -framerate 30:フレームレート(1秒間に30フレーム)
- -pixel_format yuyv422:ピクセルフォーマットyuyv422(YUYV 4:2:2)
- -i video="FaceTime HD Camera": カメラデバイス
- -pix_fmt yuv420p:出力フォーマットyuv420p(YUV 4:2:0)
- -c:v libx264:ビデオコーデックH.264
- -preset ultrafast:エンコード速度を最速(低遅延化)
- -t 10:録画時間(10秒)
- -an:音声なし
- ファイル:作成するファイル名
Lubuntu
ffmpeg -f v4l2 -video_size 1280x720 -framerate 30 -input_format yuyv422 -i /dev/video0 -pix_fmt yuv420p -c:v libx264 -preset ultrafast -an -t 10 ファイル
- -f v4l2:入力フォーマットVideo4Linux2
- -video_size 640x480:解像度
- -framerate 30:フレームレート(1秒間に30フレーム)
- -input_format yuyv422:ピクセルフォーマットyuyv422(YUYV 4:2:2)
- -i /dev/video0: カメラデバイス
- -pix_fmt yuv420p:出力フォーマットyuv420p(YUV 4:2:0)
- -c:v libx264:ビデオコーデックH.264
- -preset ultrafast:エンコード速度を最速(低遅延化)
- -t 10:録画時間(10秒)
- -an:音声なし
- ファイル:作成するファイル名
検証
FFmpegでSRT転送を行い、Wiresharkで取得したデータの解説。
正常
- 送信側IPアドレス”10.0.2.15”、受信側IPアドレス”192.168.56.1”(以降共通)
- 相互のControl:UMSG_HANDSHAKEによるネゴシエーション(赤枠)
- DATAによる実際のデータ送信(赤枠)
- 受信側Control:UMSG_ACK/送信側Control:UMSG_ACKACKによるデータ受信確認(青枠)
- Control:UMSG_ACK:シーケンス番号”1869575761”まで受信確認(1868575760かもしれない)
- Control:UMSG_ACKACK:UMSG_ACKの確認
- 送信側Control:UMSG_SHUTDOWNによる転送終了(赤枠)
- 青枠DATAの受信側のデータ受領確認は行っていないかもしれない(?)
パケットロス
下記Linuxコマンドにより、Lubuntu(送信側)からWindows(受信側)へのパケットを20%ドロップさせる。
$ sudo tc qdisc add dev enp0s3 root netem drop 20%
- Control:UMSG_LOSSREPORTにより、受信側”192.168.56.1”がシーケンス番号”1340075526”を受信していないことを送信側に通知
- シーケンス番号”1340075526”のDATA再送(Retransmitted)(赤枠)
- 青枠のメッセージ番号”msgno”と比べると、まとめて再送を実施している様子
- 参考:再送でない場合、”Original”
- ”srt.type == 3”でフィルターすると、Control:UMSG_LOSSREPORTのみ表示
- 20%Loss設定だが、実際には12.3%のロス(詳細不明)
参考、下記は入出力グラフ(上:SRT全体、下:Control:UMSG_LOSSREPORTのみ)。
終わりに
FFmpegは多数のオプションあり。低ビットレートの回線を想定した転送もオプションにより実現できるようだ。
EOF