Ubuntuでcrtmpserverを試す

メディアサーバーのcrtmpserverが稼働する環境をUbuntu上に構築し、メディア配信に関する知識を増強しようと考えた。
今回は以下を参考にPCのブラウザで動画再生ができる環境を構築して見た。

RTMPストリーミング — pdoc 0.1 documentation

処理フロー:MP4 → [ffmpeg] → FLV → [crtmpserver] → RTMP → [flowplayer]

【動作環境】

【パッケージインストール】

apt-get install でUbuntuに以下のパッケージをインストールする。
( [ ] 内にインストールしたときのバージョンを記した。)

  • crtmpserver [1.0~dfsg-5]
  • lua5.2 [5.2.3-1]
  • apache2 [2.4.7-1ubuntu4.13]

ffmpegのインストール】

Ubuntuでffmpegをビルドする にしたがってffmpeg(バージョン:git-2017-01-02-aa95292)をインストールする。

【crtmpserver設定の表示】

crtmpserverの設定ファイルは /etc/crtmpserver 以下に存在する。
そのディレクトリにあるインストール直後のcrtmpserver.luaの末尾は

-- print("__________________________")
-- table_print(configuration)
-- print("__________________________")

となっているので -- を削除してコメントを外す。さらに、以下の不具合を修正する。

if ( app:match("^#.*$") or app:match("^$") or app:match("^\s+$") ) then
                                                          ↓
if ( app:match("^#.*$") or app:match("^$") or app:match("^%s+$") ) then

そして、 lua crtmpserver.lua を実行すると、以下のように設定内容が表示される。

[applications] => table
    (
       [1] => table
           (
              [name] => applestreamingclient
              [protocol] => dynamiclinklibrary
              [description] => Apple Streaming Client
              [aliases] => table
                  (
                     [1] => asc
                  )
           )
       [2] => table
           (
              [validateHandshake] => true
              [acceptors] => table
                  (
                     [1] => table
                         (
                            [port] => 1935
                            [protocol] => inboundRtmp
                            [ip] => 0.0.0.0
                         )
                     [2] => table
                         (
                            [port] => 8080
                            [protocol] => inboundRtmpt
                            [ip] => 0.0.0.0
                         )
                  )
              [name] => appselector
              [protocol] => dynamiclinklibrary
              [description] => Application for selecting the rest of the applications
              [default] => true
           )
       [3] => table
           (
              [externalStreams] => table
                  (
                  )
              [aliases] => table
                  (
                     [1] => simpleLive
                     [2] => vod
                     [3] => live
                     [4] => WeeklyQuest
                     [5] => SOSample
                     [6] => oflaDemo
                  )
              [mediaFolder] => /var/lib/crtmpserver/mediaFolder
              [protocol] => dynamiclinklibrary
              [seekGranularity] => 1.5
              [keyframeSeek] => true
              [validateHandshake] => true
              [name] => flvplayback
              [clientSideBuffer] => 12
              [description] => FLV Playback Sample
              [acceptors] => table
                  (
                     [1] => table
                         (
                            [protocol] => inboundLiveFlv
                            [port] => 6666
                            [waitForMetadata] => true
                            [ip] => 0.0.0.0
                         )
                     [2] => table
                         (
                            [port] => 9999
                            [protocol] => inboundTcpTs
                            [ip] => 0.0.0.0
                         )
                  )
           )
       [4] => table
           (
              [targetServers] => table
                  (
                     [1] => table
                         (
                            [localStreamName] => stream1
                            [keepAlive] => true
                            [targetStreamType] => live
                            [targetUri] => rtmp://gigi:spaima@localhost/vod
                            [emulateUserAgent] => My user agent
                         )
                  )
              [abortOnConnectError] => true
              [name] => proxypublish
              [protocol] => dynamiclinklibrary
              [description] => Application for forwarding streams to another RTMP server
              [acceptors] => table
                  (
                     [1] => table
                         (
                            [port] => 6665
                            [protocol] => inboundLiveFlv
                            [ip] => 0.0.0.0
                         )
                  )
           )
       [5] => table
           (
              [active] => false
              [protocol] => dynamiclinklibrary
              [targetServer] => localhost
              [streams] => table
                  (
                     [1] => mp4:lg.mp4
                  )
              [randomAccessStreams] => false
              [name] => stresstest
              [numberOfConnections] => 10
              [description] => Application for stressing a streaming server
              [targetApp] => vod
           )
       [rootDirectory] => /usr/lib/crtmpserver/applications
    )
[pathSeparator] => /
[logAppenders] => table
    (
       [1] => table
           (
              [name] => console appender
              [type] => coloredConsole
              [level] => 6
           )
       [2] => table
           (
              [name] => file appender
              [type] => file
              [fileName] => /var/log/crtmpserver/main.log
              [level] => 6
           )
    )
[daemon] => true

crtmpserver.luaで外したコメントは元に戻しておくこと。

【crtmpserverログの確認】

crtmpserverのログファイルは /var/log/crtmpserver に存在するので、Servicesテーブルを確認する。

+-----------------------------------------------------------------------------+
|                                                                     Services|
+---+---------------+-----+-------------------------+-------------------------+
| c |      ip       | port|   protocol stack name   |     application name    |
+---+---------------+-----+-------------------------+-------------------------+
|tcp|        0.0.0.0| 1935|              inboundRtmp|              appselector|
+---+---------------+-----+-------------------------+-------------------------+
|tcp|        0.0.0.0| 8080|             inboundRtmpt|              appselector|
+---+---------------+-----+-------------------------+-------------------------+
|tcp|        0.0.0.0| 6666|           inboundLiveFlv|              flvplayback|
+---+---------------+-----+-------------------------+-------------------------+
|tcp|        0.0.0.0| 9999|             inboundTcpTs|              flvplayback|
+---+---------------+-----+-------------------------+-------------------------+
|tcp|        0.0.0.0| 6665|           inboundLiveFlv|             proxypublish|
+---+---------------+-----+-------------------------+-------------------------+

ffmpegからストリーム送信】

以下のコマンドを実行し、ffmpegからcrtmpserverにストリームを送信する。

ffmpeg -stream_loop -1 -re -i hoge.mp4 -vcodec copy -metadata streamName=ffmpeg -f flv tcp://localhost:6666

各パラメーターの詳細は以下の通り。

参考:最新ffmpegのオプションまとめ - MobileHackerz Knowledgebase Wiki

  • -stream_loop -1
    入力メディアを永久に繰り返し出力する。
  • -re
    入力メディアと同じスピードで出力する。このオプションを指定しないと、最初から最後まで再生されない(試して見て欲しい)。
  • -i hoge.mp4
    入力メディアとして便宜上hoge.mp4を指定する。
  • -vcodec copy
    入力メディアの映像データーをそのままコピーする(CPU負荷が低い)。
  • -metadata streamName=ffmpeg
    ffmpegと言う名前でストリームを配信する。その名前は再生対象のメディアを指定するときのキーワードとなる。
  • -f flv
    FLVフォーマットでメディアを出力する。
  • tcp://localhost:6666
    crtmpserverのinboundLiveFlvプロトコルスタック、flvplaybackアプリケーションに出力する(現段階では意味を正確に理解していないため、これ以上は説明できないので悪しからず)。

上記のコマンドを実行することで、crtmpserverのログには以下のように出力される。

1483539098:3:/build/buildd/crtmpserver-1.0~dfsg/thelib/src/netio/epoll/tcpacceptor.cpp:154:Accept:Client connected: 127.0.0.1:42042 -> 0.0.0.0:6666
1483539098:6:/build/buildd/crtmpserver-1.0~dfsg/thelib/src/protocols/liveflv/inboundliveflvprotocol.cpp:46:Initialize:parameters:
<MAP name="" isArray="false">
    <STR name="ip">0.0.0.0</STR>
    <UINT16 name="port">6666</UINT16>
    <STR name="protocol">inboundLiveFlv</STR>
    <STR name="sslCert"></STR>
    <STR name="sslKey"></STR>
    <BOOL name="waitForMetadata">true</BOOL>
</MAP>
1483539098:6:/build/buildd/crtmpserver-1.0~dfsg/thelib/src/protocols/liveflv/inboundliveflvprotocol.cpp:51:Initialize:_waitForMetadata: 1
1483539098:4:/build/buildd/crtmpserver-1.0~dfsg/thelib/src/netio/epoll/iohandlermanager.cpp:100:RegisterIOHandler:Handlers count changed: 6->7 IOHT_TCP_CARRIER
1483539098:6:/build/buildd/crtmpserver-1.0~dfsg/thelib/src/protocols/liveflv/baseliveflvappprotocolhandler.cpp:45:RegisterProtocol:protocol CTCP(10) <-> TCP(100) <-> [ILFL(101)] registered to app flvplayback
1483539098:3:/build/buildd/crtmpserver-1.0~dfsg/thelib/src/protocols/liveflv/inboundliveflvprotocol.cpp:184:SignalInputData:Stream metadata:
<MAP name="" isArray="true">
    <MAP name="__index__value__0" isArray="true">
        <DOUBLE name="audiocodecid">10.000</DOUBLE>
        <DOUBLE name="audiodatarate">125.000</DOUBLE>
        <DOUBLE name="audiosamplerate">44100.000</DOUBLE>
        <DOUBLE name="audiosamplesize">16.000</DOUBLE>
        <STR name="compatible_brands">isommp42</STR>
        <DOUBLE name="duration">0.000</DOUBLE>
        <STR name="encoder">Lavf57.61.100</STR>
        <DOUBLE name="filesize">0.000</DOUBLE>
        <DOUBLE name="framerate">29.970</DOUBLE>
        <DOUBLE name="height">720.000</DOUBLE>
        <STR name="major_brand">mp42</STR>
        <STR name="minor_version">0</STR>
        <BOOL name="stereo">true</BOOL>
        <STR name="streamName">ffmpeg</STR>
        <DOUBLE name="videocodecid">7.000</DOUBLE>
        <DOUBLE name="videodatarate">2172.205</DOUBLE>
        <DOUBLE name="width">1280.000</DOUBLE>
    </MAP>
</MAP>

【FlowPlayerのインストール】

FlowPlayerでMP4を再生する にしたがってFlowPlayerをインストールする。

【FlowPlayerにRTMPプラグインを追加】

以下のページからRTMP Streaming Pluginをダウンロードする。
(今回はバージョン 3.2.13をダウンロードした。)

flash.flowplayer.org

上記ページのDownloadセクションからダウンロードしたZIPファイルをFlowPlayer本体をインストールしたディレクトリ /var/www/html/flowplayer に展開する。

.
├── LICENSE.txt
├── README.txt
├── example
│   ├── hoge.mp4
│   ├── index.html
│   └── style.css
├── flowplayer-3.2.13.min.js
├── flowplayer-3.2.18.swf
├── flowplayer.controls-3.2.16.swf
└── flowplayer.rtmp
    ├── LICENSE.txt
    ├── README.txt
    └── flowplayer.rtmp-3.2.13.swf

2 directories, 11 files

【sample1.htmlの作成】

前述のtree表示内容に記載のexampleディレクトリにsample1.htmlを以下の内容で作成する。

<html>
    <head>
        <title>Play RTMP via crtmpserver</title>
        <script src="../flowplayer-3.2.13.min.js"></script>
    </head>
    <body>
        <a style="display:block;width:854px;height:480px;" id="player"></a>
        <script>
            $f("player", "../flowplayer-3.2.18.swf", {

                clip: {
                    url: 'ffmpeg',
                    live: true,
                    provider: 'rtmp'
                },

                plugins: {
                    rtmp: {
                        url: '../flowplayer.rtmp/flowplayer.rtmp-3.2.13.swf',
                        netConnectionUrl: 'rtmp://192.168.1.28/flvplayback'
                    }
                }
            });
        </script>
    </body>
</html>

上記 192.168.1.28 はサーバーのIPアドレスなので、インストール環境に合わせて適宜変更して欲しい。

【ブラウザで再生】

ブラウザで http://サーバーのIPアドレス/flowplayer/example/sample1.html にアクセスしてRTMPを再生する。