コロナ禍でライブ配信が注目されてますね。ええ。コロナ禍と言いたかっただけです。
ZOOMのようなビデオチャットや、Youtube Live ニコニコ生放送のような
1対多の生放送アプリまで、実際に集まって行う会議やイベント、
あるいは授業なんかもライブ配信で済ませている。そんな時代が一気に訪れました。
ここではWebRTCなどを使った双方向のビデオチャットではなく、いわゆる映像配信と言われる1対多のストリーミングサービスの話題が中心です。
そんな中、セキュリティの関係もあり自分でライブ配信プラットフォームを作れないかという相談が寄せられた人もいることでしょう。
これまでは、Adobe Media ServerやWowzaを動かしてそこにRTMPで打ち上げ、Flash Playerで視聴といったアプリケーションが一般的でしたが、ライセンス料をはじめ、非常にサーバーのコストがかかりました。
また、映像送信側では現役で使われているRTMPも、現在では視聴環境側のブラウザでは、
RTMPの受信に必須であるFlash Playerのサポートを打ち切られているなどすでに終わった技術になりつつあります。
RTMPで打ち上げるのはいいけどじゃあどうやって見るの?という話になるわけです。
いくつか方法があり、
サーバーでHTTP Live Streaming形式に変換し、HTTPプロトコルでのストリーミング視聴を可能にする
同じくMPEG-DASH形式にしてHTTPプロトコルでのストリーミング視聴を可能にする
主に使われているのはこの2種類です。
どちらも仕組みとしては、配信したい映像を、一定時間に区切ったTSファイルにして、TSファイルの構成を示したプレイリストと一緒にブラウザでダウンロード、プレイリストにしたがって再生、プレイリストを逐次更新してまた新しいTSファイルをダウンロードという形で、HTTP GETを繰り返ししていくことにより映像をつながった状態で見られる仕組みです。
RTMPで打ち上げた映像をそのままHLS形式に変換してくれる機能まで持ったのが、Nginx-RTMP-moduleです。
https://github.com/arut/nginx-rtmp-module
WebサーバーとしてはおなじみのNginxのモジュールで、設定をするとRTMPサーバーとして動作、HLSファイルの生成をONにしてWebサーバーでホストするとTSファイルとM3U8プレイリストを生成して、HLSの配信環境も作ることができます。
これはすでに試している方も多いと思います。
HLSはサポートしているブラウザも多く、スマホでもPCでも安定して視聴できます。
しかし、先に述べた仕組みなので、
TSファイルの長さ分、録画した動画ファイルを生成してからプレイリストに乗せて、ブラウザがダウンロード、再生ということでその分遅延が大きくなります。
このへんは調べるか、実際にやってみるとよく分かると思います。
僕が限界までチューニングした結果3秒くらいの遅延までは縮められましたが、回線が遅くなったりするとすぐ映像が途切れてしまうピーキーな感じになってしまいました。
毎回前置きが長いですが、そこでタイトルのNginx-http-flv-moduleの出番です。
https://github.com/winshining/nginx-http-flv-module
まずはサクッとインストールから。
WSLでUbuntuを使っています。
sudo apt-get update sudo apt-get upgrade -y sudo apt-get install build-essential libpcre3 libpcre3-dev libssl-dev zlib1g-dev -y
Nginx-flv-moduleをダウンロードしてビルド
git clone https://github.com/winshining/nginx-http-flv-module.git wget http://nginx.org/download/nginx-1.19.1.tar.gz tar -zxvf nginx-1.19.1.tar.gz cd nginx-1.19.1/ ./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf \ --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock \ --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp \ --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \ --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module \ --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module \ --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module \ --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream \ --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-g -O2 \ -fdebug-prefix-map=/data/builder/debuild/nginx-1.19.0/debian/debuild-base/nginx-1.19.0=. -fstack-protector-strong -Wformat -Werror=format-security \ -Wp,-D_FORTIFY_SOURCE=2 -fPIC' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie' \ --add-module=./../nginx-http-flv-module
make sudo make install
Nginxの設定
sudo vi /etc/nginx/nginx.conf
#追加 include /etc/nginx/streams-enabled/*;
sudo vi /etc/nginx/sites-available/vod
server { listen 80; server_name vod.example.com; server_name localhost; location /flv { flv_live on; chunked_transfer_encoding on; add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Credentials' true; } }
RTMPサーバー用設定ファイルを作る。
各パラメーターの詳細はNginx-RTMP-Moduleのドキュメントに書いてあります。
sudo mkdir /etc/nginx/streams-available sudo mkdir /etc/nginx/streams-enabled
sudo vi /etc/nginx/streams-available/rtmp
rtmp_auto_push on; rtmp_auto_push_reconnect 1s; rtmp_socket_dir /tmp; rtmp { out_queue 4096; out_cork 8; max_streams 8; timeout 15s; drop_idle_publisher 15s; log_interval 5s; log_size 1m; server { listen 1935; server_name rtmp.example.com; server_name localhost; application rtmp { live on; } } }
設定有効化(sites-available、sites-enabledにリンク)
sudo rm /etc/nginx/sites-enabled/default sudo ln -s /etc/nginx/sites-available/vod /etc/nginx/sites-enabled/vod sudo ln -s /etc/nginx/streams-available/rtmp /etc/nginx/streams-enabled/rtmp sudo /usr/sbin/nginx
こんな感じで設定したらOBSなどでRTMPの配信を受けられます。
そして、プレイヤーの画面を作っていきます。
プレイヤーにはbilibiliのflv.jsを使います。
から、flv.min.jsをダウンロードしてwwwrootに置きます。
同じくプレイヤーのHTMLを作ります。
sudo vi /var/www/html/player.html
<script src="flv.js"></script> <video id="videoElement" muted autoplay controls></video> <script> if (flvjs.isSupported()) { var videoElement = document.getElementById('videoElement'); var flvPlayer = flvjs.createPlayer({ type: 'flv', url: '/flv?port=1935&app=ingest&stream=stream01' }); flvPlayer.attachMediaElement(videoElement); flvPlayer.load(); flvPlayer.play(); } </script>
これでhttp://localhost/player.htmlを見ると、
rtmp://localhost/rtmp/stream01宛にRTMPで送った映像が見られます。
仕組みとしては、 /etc/nginx/sites-available/vodに設定を書きましたが、
受け取ったRTMPストリームを、80番ポートで再配信しています。
これにより、RTMPストリーム(FLV)を直接HTTP GETできるようになっています。
Flash playerがないとRTMPを再生できないのは、ブラウザがrtmp://プロトコルをサポートしていないのが主な要因ですが、HTTPプロトコルでストリームが受信できるとなると話は別です。
flv.jsは、RTMP over HTTPのストリームをデコードしてHTML5プレイヤーで再生できます。
視聴中の通信イメージとしては、ずっと配信が続く限り無限に終わらない動画のダウンロードをしている感じです。
視聴中の通信イメージとしては、ずっと配信が続く限り無限に終わらない動画のダウンロードをしている感じです。
実際に試してみると、VPSサーバーに作った配信サーバーでも2秒くらいの遅延で配信ができました。
OBSのブラウザが遅延してるんだわ。— じてんしゃっぷ (@jitenshap) July 8, 2020
配信画面と比較したら2秒ちょい。早い!! pic.twitter.com/oNAar7DfDY
チャット付きのライブ配信や監視系など、遅延が大きすぎると問題なアプリケーションではとても威力を発揮しそうです。