nginx-rtmp-module + FFmpeg + HLSで動画配信ができるdocker-composeをつくった
タイトルのdocker-composeをつくっていきます。ローカルで配信確認したいときにシュッと起動できるようにします。
次のような構成でつくりました。
コンテナ構成
それぞれのコンテナについてまとめます。
RTMP server
- RTMP serverは`rtmp context`でストリームを受け取るapplicationを追加(`application encoder`)。
- `application encoder`はストリームを受け取るとFFmpegで動画を3つのビットレードにエンコードする。
- `application encoder`でエンコードした動画をHLS変換する`application hls`へストリームする。
- `application hls`は変換したm3u8、tsファイルを`/data/hls`に配置する。
- `/data/hls`はホストで同期されていてStreaming serverからもm3u8、tsファイルを参照できるようにしている。
rtmp { server { listen 1935; application encoder { live on; exec ffmpeg -i rtmp://localhost:1935/$app/$name -c:a aac -strict -2 -b:a 32k -c:v libx264 -x264opts bitrate=128:vbv-maxrate=128:vbv-bufsize=128 -rtbufsize 100M -bufsize 256k -preset veryfast -f flv rtmp://localhost:1935/hls/${name}_low -c:a aac -strict -2 -b:a 64k -c:v libx264 -x264opts bitrate=256:vbv-maxrate=256:vbv-bufsize=256 -rtbufsize 100M -bufsize 512k -preset veryfast -f flv rtmp://localhost:1935/hls/${name}_mid -c:a aac -strict -2 -b:a 128k -c:v libx264 -x264opts bitrate=512:vbv-maxrate=512:vbv-bufsize=512 -rtbufsize 100M -bufsize 1024k -preset veryfast -f flv rtmp://localhost:1935/hls/${name}_high; } application hls { live on; hls on; hls_path /data/hls; hls_nested on; hls_fragment 2s; hls_variant _low BANDWIDTH=160000; hls_variant _mid BANDWIDTH=320000; hls_variant _high BANDWIDTH=640000; } } }
Broadcast server
- mp4ファイルをFFmpegを使いループ再生させRTMP serverへストリームしている。
- Broadcast serverはコンテナの1つのためlocalhostではRTMP serverに接続できない。
- 次のように環境変数を参照するようにしている。
ffmpeg -re -stream_loop -1 -i '/data/broadcast_source.mp4' -f flv "${RTMP_SERVER_URL}/${STREAM_NAME}"
Streaming server
- NginxでHTTP serverをたてる。
- typesに'm3u8'と'ts'を追加している。
- rootを'/data'としてRTMP serverと同期しているm3u8とtsファイルにアクセスしている。
server { listen 80; location /hls { types { application/vnd.apple.mpegurl m3u8; video/mp2t ts; } root /data; add_header Cache-Control no-cache; add_header Access-Control-Allow-Origin *; } } }
docker-compose
ホストとコンテナでファイルを同期しているのでdindを使いホストもコンテナ化しています。
ホスト側のdocker-compose
version: "3" services: dind_streaming_host: container_name: streaming_host image: docker:1.13.0-dind privileged: true ports: - 5301:2375 - 1935:1935 - 80:80 - 5000:5000 volumes: - ./video/clouds_over_the_mountain_hd_stock_video.mp4.mp4:/var/container/data/broadcast_source.mp4
コンテナに必要なポートと`Broadcast server`から配信する動画をコンテナに同期しています。
コンテナ群のdocker-compose
version: "3" services: rtmp: container_name: rtmp_server build: ./container/nginx_rtmp ports: - 1935:1935 volumes: - /var/container/data:/data - /var/container/log/rtmp/nginx/:/var/log/nginx stream: container_name: stream_server build: ./container/nginx_stream ports: - 80:80 volumes: - /var/container/data:/data - /var/container/log/stream/nginx/:/var/log/nginx broadcast: container_name: broadcast_server build: ./container/ffmpeg_broadcast depends_on: - rtmp environment: RTMP_SERVER_URL: "rtmp://rtmp:1935/encoder" STREAM_NAME: broadcast volumes: - /var/container/data/:/data
起動方法と動画配信方法
ホストとコンテナでファイルを同期しているのでdindを使いホストもコンテナ化しているので起動にはdindとdirenvが必要です。
docker-composeの起動方法
まずはホスト側の起動から。
もしdindのイメージがなければプルします。
docker pull docker:1.13.0-dind
ホスト側を起動します。
$ cd (path-to 'streaming-host-sample') $ docker-compose up -d
続いてコンテナ群をまとめているdocker-composeを起動します。
$ cd (path-to 'streaming_host') direnv: loading .envrc direnv: export +DOCKER_HOST $ docker-compose up -d
※ 'streaming_host'ディレクトではdirenvによってディレクトリでは環境変数`DOCKER_HOST`が先に起動したdockerのホストに切り替わっています。
これですべてのコンテナが起動できました。
動画の確認方法
コンテナが起動できたらsafariで`http://localhost/hls/broadcast.m3u8`にアクセスすると`Broadcast server`から配信している動画を再生できます。
今回はプレイヤーを用意せずsafariで直接m3u8を参照しています。
サンプルの動画はDISTILLからDLしました。