仕事でマルチ配信の話が出たため、Dockerを用いて一つのライブ出力から複数のRTMPサーバにデータを転送する中継サーバを構築してみました。その際に色々と調べたため備忘録として本記事にまとめます。
背景
そもそものきっかけは
- アプリで配信したライブを自社製のライブPlayer以外にYoutubeやFacebookに対して同時配信したい
- 複数配信先はCMSなどで自由に指定できるようにしたい
- RTMPの出力はアプリからで一つに制限されているため、RTMPを複数の配信先に中継するサーバが必要
- そもそもそれは可能なの??
から始まり、勉強がてらdockerを用いてローカルに中継サーバを構築してみることにしました。
成果物・構成
成果物は以下の通りです。
◆ソースコード
◆構成
stream server
にRTMPを渡すために ffmpeg
を使用する構成になっています。
Dockerfile
FROM ubuntu:20.04
RUN apt update
RUN apt upgrade -y
RUN apt auto-remove -y
RUN apt install -y language-pack-ja
RUN update-locale LANG=ja_JP.UTF8
RUN apt install -y build-essential libpcre3 libpcre3-dev libssl-dev libz-dev zlib1g-dev unzip git curl wget vim
WORKDIR /usr/local/src/
RUN curl -LO http://nginx.org/download/nginx-1.20.0.tar.gz
RUN curl -LO https://github.com/arut/nginx-rtmp-module/archive/afd350e0d8b7820d7d2cfc3fa748217153265ce6.tar.gz
RUN tar xvzf nginx-1.20.0.tar.gz
RUN tar xvzf afd350e0d8b7820d7d2cfc3fa748217153265ce6.tar.gz
WORKDIR /usr/local/src/nginx-1.20.0
RUN ./configure --with-http_ssl_module --add-module=../nginx-rtmp-module-afd350e0d8b7820d7d2cfc3fa748217153265ce6 --with-debug
RUN make
RUN make install
COPY conf/nginx.conf /usr/local/nginx/conf/nginx.conf
COPY conf/nginx_single.conf /usr/local/nginx/conf/nginx_single.conf
WORKDIR /var/local/www/hls
RUN chmod 777 /var/local/www/hls
# ffmpeg install
WORKDIR /usr/local/src/
RUN wget https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz \
&& tar Jxvf ffmpeg-release-amd64-static.tar.xz \
&& cp ffmpeg-*-amd64-static/ffmpeg /usr/bin/
WORKDIR /var/local/www/hls
マルチ配信の仕組み
RTMPの通信はnginxの nginx-rtmp-module を用いています。Dockerfile
のnginxとnginx-rtmp-moduleのインストールしてる箇所は以下の通りです。
RUN apt install -y build-essential libpcre3 libpcre3-dev libssl-dev libz-dev zlib1g-dev unzip git curl wget vim
WORKDIR /usr/local/src/
RUN curl -LO http://nginx.org/download/nginx-1.20.0.tar.gz
RUN curl -LO https://github.com/arut/nginx-rtmp-module/archive/afd350e0d8b7820d7d2cfc3fa748217153265ce6.tar.gz
RUN tar xvzf nginx-1.20.0.tar.gz
RUN tar xvzf afd350e0d8b7820d7d2cfc3fa748217153265ce6.tar.gz
WORKDIR /usr/local/src/nginx-1.20.0
RUN ./configure --with-http_ssl_module --add-module=../nginx-rtmp-module-afd350e0d8b7820d7d2cfc3fa748217153265ce6 --with-debug
RUN make
RUN make install
RTMPを受信し、複数のRTMPサーバへ転送するための設定ファイルは以下の通りです。
# ~~~省略~~~~
rtmp {
server {
# ~~~省略~~~~
application live {
# ~~~省略~~~~
allow publish all; # RTMP push 許可
allow play 127.0.0.1; # RTMP pull 有効(ffmpegに対して)
# 変換コマンド
exec ffmpeg -re -i rtmp://localhost/${app}/${name} -codec:v libx264 -g 3 -f flv rtmp://localhost/stream1/${name};
exec ffmpeg -re -i rtmp://localhost/${app}/${name} -codec:v libx264 -g 3 -f flv rtmp://localhost/stream2/${name};
}
# ~~~省略~~~~
}
}
http {
# ~~~省略~~~
}
処理の順番は以下の通りです。
-
allow play 127.0.0.1;
で受信したRTMPを再度localhostに転送 - localhostに転送したものを2プロセスのffmpegを用いてそれぞれのストリームサーバ
rtmp://localhost/streamN/${name};
に転送exec ffmpeg -re -i rtmp://localhost/${app}/${name} -codec:v libx264 -g 3 -f flv rtmp://localhost/stream1/${name};
exec ffmpeg -re -i rtmp://localhost/${app}/${name} -codec:v libx264 -g 3 -f flv rtmp://localhost/stream2/${name};
感想
勉強目的で作ってみましたが、大部分は nginx
と ffmpeg
の機能を用いて実現しているためコーディングはせずに構築することができました。
今回の成果物では配信先は同じコンテナ内のRTMPサーバに対してですが、ffmpeg
コマンドを書き換えることでYoutubeやFacebookに対して配信することは可能です。
勉強後に後から知ったのですがAWS Elemental MediaLiveでRTMP出力が可能であることが判明しました。実サービスでマルチ配信を実現する際は負荷などを考慮すると素直にAWSに頼るのが良さそうです。
参考サイト