虎の穴開発室ブログ

虎の穴ラボ株式会社所属のエンジニアが書く技術ブログです

MENU

ローカル環境で 生放送 をとりあえず試したい

みなさん、いかがお過ごしでしょうか? ラボのおっくんです。

以前、ローカル環境でストリーミングをとりあえず試したいという記事で、事前に動画ファイルをストリーミング用に変換をしておき、ストリーミング形式の動画再生を行いました。

toranoana-lab.hatenablog.com

今回は、配信するファイルを事前の変換しておくのではなくリアルタイムに変換を行い配信する、いわゆる「生放送」を試してみます。

実行環境

  • OS:macOS : Catalina 10.15.4
  • Node.js : 12.13.1
  • OBS Studio : 25.0.8
  • Docker Desktop : 2.2.0.5

全体の構成

今回作成する生放送の実行に当たり全体の流れを先に示します。

  1. OBS Studio を使って docker 上に用意した nginx に RTMP *1でコンテンツを配信する。
  2. docker 上に用意した nginx が、受け取ったコンテンツをストリーミング形式に変換して保存する。
  3. 保存先は docker のホストマシンを共有してあり、http-server の配信ファイル配下になっている。
  4. ブラウザが http-server から、ファイルを受信・再生する。

図にすると以下のようになります。

f:id:toranoana-lab:20200520095244p:plain

準備

OBS Studio インストール

今回は、コンテンツの配信元として「OBS Studio」を使用します。 インストーラを入手してインストールしてください。

obsproject.com

配信ページの用意

今回の配信環境を整備するディレクトリを用意し、以下のコマンドで、ディレクトリを用意します。

npm init -y
# http-serverをインストール
npm install http-server --save-dev

# http-serverによって配信されるディレクトリ作成
mkdir public

# ストリーミングされるファイルを保管するディレクトリ作成
mkdir public/videos

インストールしたhttp-serverは、シンプルな http サーバーです。

www.npmjs.com

こちらを使用して、.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 プレーヤーフレームワークです。

videojs.com

docker コンテナを作成

RTMP プロトコルを受付してくれる nginx を作成します。 nginx に rtmp を対応させるには、nginx-rtmp-moduleが必要です。

github.com

こちらを入れた nginx をビルドすることで rtmp に対応した nginx を作成することができます。 今回は、既に nginx-rtmp-module を含んだ nginx のイメージを docker で用意します。

tiangolo/nginx-rtmpや、alqutami/rtmp-hlsなど、rtmp に対応させた docker イメージは多くの方が公開されています。
今回はalfg/nginx-rtmpを少しカスタマイズして使うことにします。

hub.docker.com

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の設定を参照できます。

github.com

それでは、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です。 f:id:toranoana-lab:20200520094908g:plain

ブラウザの挙動確認

生放送の再生ができましたが、どのようにファイルをダウンロードしているのか気になります。開発者ツールで、動きを確認してみます。

Chrome の開発者ツールの Network タブを開きます。

f:id:toranoana-lab:20200520141159g:plain

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】」を開催します。
今回はリモートワークに的を絞った内容となります。人数制限はございませんのでぜひご参加ください!

yumenosora.connpass.com

6月12日に「【オンライン開催】とらのあな採用説明会 6/12 オタク企業で働くエンジニアの魅力について」を開催します。
とらのあなラボのエンジニアの働き方など説明します。ぜひ奮ってご参加ください。

yumenosora.connpass.com

*1:Real Time Messaging Protocol。ライブストリーミングのプロトコルです。