みなさん、いかがお過ごしでしょうか? ラボのおっくんです。
以前、ローカル環境でストリーミングをとりあえず試したいという記事で、事前に動画ファイルをストリーミング用に変換をしておき、ストリーミング形式の動画再生を行いました。
今回は、配信するファイルを事前の変換しておくのではなくリアルタイムに変換を行い配信する、いわゆる「生放送」を試してみます。
実行環境
- OS:macOS : Catalina 10.15.4
- Node.js : 12.13.1
- OBS Studio : 25.0.8
- Docker Desktop : 2.2.0.5
全体の構成
今回作成する生放送の実行に当たり全体の流れを先に示します。
- OBS Studio を使って docker 上に用意した nginx に RTMP *1でコンテンツを配信する。
- docker 上に用意した nginx が、受け取ったコンテンツをストリーミング形式に変換して保存する。
- 保存先は docker のホストマシンを共有してあり、http-server の配信ファイル配下になっている。
- ブラウザが http-server から、ファイルを受信・再生する。
図にすると以下のようになります。
準備
OBS Studio インストール
今回は、コンテンツの配信元として「OBS Studio」を使用します。 インストーラを入手してインストールしてください。
配信ページの用意
今回の配信環境を整備するディレクトリを用意し、以下のコマンドで、ディレクトリを用意します。
npm init -y # http-serverをインストール npm install http-server --save-dev # http-serverによって配信されるディレクトリ作成 mkdir public # ストリーミングされるファイルを保管するディレクトリ作成 mkdir public/videos
インストールしたhttp-serverは、シンプルな http サーバーです。
こちらを使用して、.html ファイル他を配信してゆきます。
次にストリーミング再生に使用するページを用意します。
public/index.html
を以下のように作成します。
<html> <head> <meta charset="utf-8" /> <title>ストリーミング</title> <link href="https://unpkg.com/video.js/dist/video-js.min.css" rel="stylesheet" /> <script src="https://unpkg.com/video.js/dist/video.min.js"></script> </head> <body> <video id="view" class="video-js vjs-default-skin vjs-big-play-centered" controls width="640" height="360" preload="auto" > <source src="./video/output.m3u8" type="application/x-mpegURL" /> </video> <script type="text/javascript"> videojs("view"); </script> </body> </html>
CDN を利用して、video.jsを利用しています。 video.js は、オープンソース HTML5 プレーヤーフレームワークです。
docker コンテナを作成
RTMP プロトコルを受付してくれる nginx を作成します。 nginx に rtmp を対応させるには、nginx-rtmp-moduleが必要です。
こちらを入れた nginx をビルドすることで rtmp に対応した nginx を作成することができます。 今回は、既に nginx-rtmp-module を含んだ nginx のイメージを docker で用意します。
tiangolo/nginx-rtmpや、alqutami/rtmp-hlsなど、rtmp に対応させた docker イメージは多くの方が公開されています。
今回はalfg/nginx-rtmpを少しカスタマイズして使うことにします。
alfg/nginx-rtmpは、入力されたストリームを複数の画質やサイズに調整する仕組みを持っていますが、なるべくシンプルにすることを目的に、カスタマイズを行います。
以下のコマンドで、ディレクトリを作成します。http-serverを作成するのに使用したディレクトリと同じでも構いません。
# dockerfileの保存先 mkdir docker # dockerfileでdockerイメージにコピーするnginx.confの保管先 mkdir docker/conf # dockerfileの保管先ディレクトリへ移動 cd docker
ディレクトリを用意できたら、docker イメージのカスタマイズに使用する dockerfile と docker イメージに取り込む nginx.conf を作成します。
docker/dockerfile は以下の通りです。
FROM alfg/nginx-rtmp COPY ./conf/nginx.conf /etc/nginx/nginx.conf.template
後から作成するnginx.conf
を、コンテナ上の/etc/nginx/nginx.conf.template
へコピーします。
alfg/nginx-rtmp は、起動の都度/etc/nginx/nginx.conf.template
を/etc/nginx/nginx.conf
へコピーする仕組みになっているので、大本の/etc/nginx/nginx.conf.template
を書き換えます。
docker/conf/nginx.confは以下のとおりです。
daemon off; error_log /dev/stdout info; events { worker_connections 1024; } rtmp { server { listen ${RTMP_PORT}; application stream { # ライブ配信を受け取る live on; # ストリーミング形式の変換を行う。 hls on; # 変換したファイルの保管先 hls_path /opt/data/hls; # 変換したファイルを定期的に削除する hls_cleanup on; # rtmpで配信しない deny play all; } } }
alfg/nginx-rtmp の nginx.conf は、様々な設定が書かれていますが、今回行うような最低限の動作確認では上記の記述で十分です。
興味があれば、ぜひalfg/nginx-rtmp の nginx.confを読んでみてください。
もともと用意されているnginxの設定を参照できます。
それでは、docker イメージのカスタマイズと、コンテナの起動を行います。
# dockerfileの保管先ディレクトリにいることを確認してから行う # 現在のディレクトリにあるdockerfileを使用してdockerイメージを作成し、`alfg/nginx-rtmp-simple`というタグをつける。 docker image build -t alfg/nginx-rtmp-simple . # dockerコンテナを作成し、起動する。 docker run -d -p 1935:1935 -v [先に作ったvideosディレクトリの絶対パス]:/opt/data/hls --name rtmp-server alfg/nginx-rtmp-simple # コンテナの起動を確認 docker container ls
OBS Studio の設定
OBS Studio を起動し、設定を開きます。 配信設定を開き、以下の様に設定します。
項目 | 設定事項 |
---|---|
サービス | カスタム |
サーバー | rtmp://localhost1935/stream |
ストリームキー | test |
変更を適用します。 設定できたら、OBS Studio から配信開始します。
動作確認
以下コマンドで、http-server を起動します。
npx http-server -p 3000 -c-1
生配信は、逐次配信ファイルの内容が変わります。
ですので、-c-1
を付与してファイルのキャッシュ無効化しておきます。
http://localhost:3000
にアクセスしてみます。
再生ボタンを押すと、十数秒から数十秒のラグがありますが、OBS Studio で配信した内容が表示されます。
左がOBS Studioの画面、右がChromeです。
ブラウザの挙動確認
生放送の再生ができましたが、どのようにファイルをダウンロードしているのか気になります。開発者ツールで、動きを確認してみます。
Chrome の開発者ツールの Network タブを開きます。
test.m3u8
ファイルを逐次取得し、次に取得する.ts
ファイルの情報を得ていることがわかります。
まとめ
OBS Studio と docker コンテナを使うことで、生放送の環境を用意することができました。 生放送の環境を自前で用意することができれば、特定のプラットフォームに寄らずコンテンツの配信が可能になります。
今回使用した docker イメージalfg/nginx
は、アップロードされた動画を複数のフォーマットに変換する機能が用意されています。
ご興味あれば、ぜひ素のalfg/nginx
も使ってみることや、はたまた自身で nginx にrtmp-module
を含めたビルドからやってみることも理解を深める一助となるかもしれません。
P.S
虎の穴ラボでの開発に少しでも興味を持っていただけた方は、採用説明会やカジュアル面談という場でもっと深くお話しすることもできます。ぜひお気軽に申し込みいただければ幸いです。
カジュアル面談では虎の穴ラボのエンジニアが、開発プロセスの内容であったり、「今期何見ました?」といったオタクトークから業務の話まで何でもお応えします。
カジュアル面談や採用情報はこちらをご確認ください。
yumenosora.co.jp
※現在はオンラインカジュアル面談のみ受け付けております。(2020/5/8時点)
現在行っているオンラインによるWeb面談についてはこちらの記事をご参照ください。
toranoana-lab.hatenablog.com
先日のブログでフルリモートワークに移行したお話を掲載させていただきましたが、
5月27日に「【オンライン開催】リモートワークノウハウLT【とらのあなLT】」を開催します。
今回はリモートワークに的を絞った内容となります。人数制限はございませんのでぜひご参加ください!
6月12日に「【オンライン開催】とらのあな採用説明会 6/12 オタク企業で働くエンジニアの魅力について」を開催します。
とらのあなラボのエンジニアの働き方など説明します。ぜひ奮ってご参加ください。
*1:Real Time Messaging Protocol。ライブストリーミングのプロトコルです。