ffmpeg/ffserverで保存した動画ファイルをRTSP配信を試す


2021/07/20
蛸壺の中の工作室|ffmpeg/ffserverで保存した動画ファイルをRTSP配信を試す

今回は
ffmpegとDocker版のffserverを使った動画配信用のテスト環境を作る方法を今更ながら取りまとめてみます。


ffmpegのインストール

ffmpegは高度な動画・音声の再生と録画やそのフォーマット変換できる定番のフリーソフトで、登場から20年以上を経過してもなお根強い人気を誇ります。

特に対応コーデックが充実しているため、配信用の動画を変換で利用している方も多いと思います。

Debian/Ubuntu系のLinuxでは、

            $ sudo apt install ffmpeg
        
でパッケージインストールすることですぐに利用できます。

LinuxでWebカメラに接続した状態で、カメラデバイスが
/dev/video0ある場合、そのカメラのサポートする動画用エンコードコーディックの一覧を表示させてみると以下のようになります。

            $ ffmpeg -f video4linux2 -list_formats all -i /dev/video0
ffmpeg version 4.1.6-1~deb10u1+rpt2 Copyright (c) 2000-2020 the FFmpeg developers
  built with gcc 8 (Raspbian 8.3.0-6+rpi1)
  configuration: --prefix=/usr --extra-version='1~deb10u1+rpt2' --toolchain=hardened --incdir=/usr/include/arm-linux-gnueabihf --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-omx-rpi --enable-mmal --enable-neon --enable-rpi --enable-vout-drm --enable-v4l2-request --enable-libudev --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared --libdir=/usr/lib/arm-linux-gnueabihf --cpu=arm1176jzf-s --arch=arm
  libavutil      56. 22.100 / 56. 22.100
  libavcodec     58. 35.100 / 58. 35.100
  libavformat    58. 20.100 / 58. 20.100
  libavdevice    58.  5.100 / 58.  5.100
  libavfilter     7. 40.101 /  7. 40.101
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  3.100 /  5.  3.100
  libswresample   3.  3.100 /  3.  3.100
  libpostproc    55.  3.100 / 55.  3.100
[video4linux2,v4l2 @ 0x510eb0] Raw       :     yuv420p :     Planar YUV 4:2:0 : {32-3280, 2}x{32-2464, 2}
[video4linux2,v4l2 @ 0x510eb0] Raw       :     yuyv422 :           YUYV 4:2:2 : {32-3280, 2}x{32-2464, 2}
[video4linux2,v4l2 @ 0x510eb0] Raw       :       rgb24 :     24-bit RGB 8-8-8 : {32-3280, 2}x{32-2464, 2}
[video4linux2,v4l2 @ 0x510eb0] Compressed:       mjpeg :            JFIF JPEG : {32-3280, 2}x{32-2464, 2}
[video4linux2,v4l2 @ 0x510eb0] Compressed:        h264 :                H.264 : {32-3280, 2}x{32-2464, 2}
[video4linux2,v4l2 @ 0x510eb0] Compressed:       mjpeg :          Motion-JPEG : {32-3280, 2}x{32-2464, 2}
[video4linux2,v4l2 @ 0x510eb0] Raw       : Unsupported :           YVYU 4:2:2 : {32-3280, 2}x{32-2464, 2}
[video4linux2,v4l2 @ 0x510eb0] Raw       : Unsupported :           VYUY 4:2:2 : {32-3280, 2}x{32-2464, 2}
[video4linux2,v4l2 @ 0x510eb0] Raw       :     uyvy422 :           UYVY 4:2:2 : {32-3280, 2}x{32-2464, 2}
[video4linux2,v4l2 @ 0x510eb0] Raw       :        nv12 :         Y/CbCr 4:2:0 : {32-3280, 2}x{32-2464, 2}
[video4linux2,v4l2 @ 0x510eb0] Raw       :       bgr24 :     24-bit BGR 8-8-8 : {32-3280, 2}x{32-2464, 2}
[video4linux2,v4l2 @ 0x510eb0] Raw       :     yuv420p :     Planar YVU 4:2:0 : {32-3280, 2}x{32-2464, 2}
[video4linux2,v4l2 @ 0x510eb0] Raw       : Unsupported :         Y/CrCb 4:2:0 : {32-3280, 2}x{32-2464, 2}
[video4linux2,v4l2 @ 0x510eb0] Raw       : Unsupported :  32-bit XBGR 8-8-8-8 : {32-3280, 2}x{32-2464, 2}
/dev/video0: Immediate exit requested
        
基本的にカメラから映像を取得する場合には、対応の動画フォーマットでしか取得できませんのでデバイスを良く確認することが必要です。


配信用のテスト動画を撮る

ここではLinuxOSのパソコンから配信用の動画をmp4形式で用意することを考えます。

何か利用できるカメラがあればそのデバイスから録画することでテスト用の動画が取得できますが、カメラが無くてもデスクトップ画面をそのまま映像ソースにすることも可能です。

デスクトップ画面をキャプチャする

最初にデスクトップ画面から動画を取得する方法を試します。(※もちろんGUIモードで動作するLinux前提の話です。)

ffmpegへのディスプレイ入力の調べ方として、環境変数
DISPLAYを覗いてみます。

            $ echo $DISPLAY
:0.0
        
これで画像入力オプションが-i :0.0で利用できるます。またLinuxでのデスクトップ映像の出力フォーマットは-f x11grabとします。(余談でWindowsの場合にはこれらのオプションは、ディスプレイデバイスは-i desktop、出力フォーマット-f gdigrabで置き換えられます。)

では試しにデスクトップを録画を以下のコマンドで取り込んでみます。

            $ ffmpeg -s 1920x1080 \
    -r 30 \
    -f x11grab \
    -i :0.0 \
    -c:v libx264 \
    -pix_fmt yuv420p desktop.mp4
        
(※ QuickTimeなどのプレイヤーでlibx264コーディックの動画を再生する場合には、-pix_fmt yuv420pのオプションが必要になります。)

録画を止めるのはQキーを押すことで可能です。

出力された
desktop.mp4を何かのプレイヤーで再生できたらサンプル動画の完成です。

なおffmpegのオプションは非常に多いので、
公式ドキュメントを確認するか、ffmpeg --helpをチェックしてみてください。

Linuxカメラから動画を撮る

ほぼ同じ要領で、video4lunux2ドライバーに対応したカメラデバイスから動画を取得してみます。

ここではラズパイに接続したカメラモジュールからmp4画像のテスト取りをしてみます。

            $ ffmpeg \
    -f v4l2 \
    -s 640x480 \
    -thread_queue_size 8192 \
    -i /dev/video0 \
    -c:v h264_omx \
    -b:v 768k \
    output.mp4
        
ちゃんとカメラから何らかの画像が取り込めていたらOKです。


ffserverを立てる

先ほど取れた動画を利用してffserverから動画を配信して、ffplayから再生してみます。

ffserverの注意点

ffmpegをインストールすると手軽にストリーミングサーバーが立てられる付属ツールの扱いであったffserverでしたが、2018年1月のバージョンから開発サポートが廃止され、ffmpegからは外されています。

これからffmpegを使った本格的なストリーミングサーバーを検討する場合には
nginxを使って構築するほうが良いのですが、簡単なffmpegからのストリーミングを手元で試すにはffserverのほうがまだ楽ちんです。動画関連のアプリケーション開発のツールといった用途で、まだ一定数需要がありそうです。

ffserver用のDockerコンテナを作成する

既にffmpegにはパッケージされていないため、現状でffserverを利用するためには自前でソースビルドが基本になるのですが、ビルド環境を構築するのも面倒です。

こちらの方が
ffserver用のDockerイメージを公開されていますので、これを参考にしてffserverを構築してみる方法を紹介します。

ちなみにこのDockerイメージは少し前のalpineのイメージにffmpegをパッケージインストールして使っているというだけの代物です。(よって、alpine:edgeをベースにffmpegをインストールするとffserverはやはり外されていますので注意が必要です。)

お手元の環境にはDockerとDocker-composeがインストールされているとして、まずは以下のDockerfileを作成します。

            FROM alpine:3.8

RUN apk add --no-cache ffmpeg

COPY ffserver.conf /etc/

EXPOSE 554 8090

ENTRYPOINT ["ffserver"]
        
そしてdocker-compose.ymlを以下の内容にしておきます。

            version: '3'

services:
    ffserver:
        build: .
        container_name: my_ffserver
        image: ffserver:alpine3.8
        ports:
            - "554:554"
            - "8090:8090"
        volumes:
            - ./ffserver.conf:/etc/ffserver.conf
            - ./data:/data
        restart: always
        
続いてffserverの設定ファイルであるffserver.confを作成し、以下のような内容にしておきます。

            HTTPPort 8090
HTTPBindAddress 0.0.0.0

RTSPPort 554
RTSPBindAddress 0.0.0.0

MaxClients 100
MaxBandwidth 100000
CustomLog -

<Feed feed.ffm>
File /data/feed.ffm
</Feed>

<Stream video.mp4>
Format rtp
Feed feed.ffm
VideoCodec libx264
VideoFrameRate 24
VideoBitRate 100
VideoSize 640x480
AVPresetVideo default
AVPresetVideo baseline
AVOptionVideo flags +global_header
NoAudio
ACL allow 127.0.0.1
ACL allow 192.168.0.0 192.168.255.255
</Stream>

<Stream status.html>
Format status
ACL allow 127.0.0.1
ACL allow 192.168.0.0 192.168.255.255
</Stream>
        
またdataというフォルダを作って、上記で録画した画像データをvideo.mp4という名前で保存しておきます。

これでテスト配信用のリソースの準備は完了で、プロジェクトは以下のようなフォルダ構造になっているはずです。

            $ tree
.
├── Dockerfile
├── data
│   └── video.mp4
├── docker-compose.yml
└── ffserver.conf
        
このffserver用のコンテナを起動するには、

            $ docker-compose build
        
でイメージをビルドし、

            $ docker-compose up -d
        
とすることで、ffserverがバックグラウンドで立ち上がっています。

なおffserverを停止させる場合には、

            $ docker-compose down
        
を利用します。

テスト用の動画をコンテナ内から配信してみる

ではdata/video.mp4を使ってffserverへテスト配信してみます。

通常、動画を配信するクライアント側からffmpegで配信する場合には以下のコマンドを使います。

            $ ffmpeg -re -i output.mp4 http://localhost:8090/feed.ffm
        
で、ffserver用のコンテナ内部からのテスト配信を行う場合にはdocker-compose exec <サービス名>からこのコマンドを使って配信します。

            $ docker-compose exec ffserver ffmpeg -re -i data/video.mp4 http://localhost:8090/feed.ffm
        
この配信ストリームを受け取るにはffplayを利用します。

            $ ffplay -i rtsp://localhost:554/video.mp4
        
ストリームの配信プロトコルはrtspで554ポートから受け取るように設定していたので、rtsp://localhost:554/video.mp4というアドレスから入力を得ることができます。正しく動画を受信してプレイヤーが再生開始されていればffserverから動画が配信されていることになります。


まとめ

今回はffmpegとffserverを利用したローカルな動画配信方法をざっと検証してみました。

今日日、ffserverの開発は終了し非推奨な扱いになってしまったため、ffserverの実用性はなくなって来ています。

既にffserverは古き過去のものになってはしまいましたが、ローカル環境でffmpegからTCP/UDPストリームで配信をテストする場合などでまだ使い道があるかもしれません。

参考サイト

Linuxでffmpegとffserverを利用してライブ配信を行う

記事を書いた人

記事の担当:taconocat

ナンデモ系エンジニア

電子工作を身近に知っていただけるように、材料調達からDIYのハウツーまで気になったところをできるだけ細かく記事にしてブログ配信してます。