こんにちはjunです。今回の記事は一風変わって物理世界をちょっと扱います。いつもはPC内で行えることばかりやっていますが、今回はGoproをつかってタイトルの通りライブ映像を再生したいと思います。RTMPサーバーをローカルで作成し、そこに送信できるかのテストをしてみたかった感じです。
ローカルPCのDockerにNignxをインストールしてRTMPの設定をしてブラウザから見れるようにします。この記事ではまずなぜ、このようなことを始めたいのかという理由から述べます。実装内容をさっさと知りたい方は「RTMPサーバー実装」へ移動してください。
経緯としては私がyoutubeライブをやりたくなったからです笑。単純にyoutubeライブをやりたいだけならば、さっさとwebカメラからやればいいのですが、私はサイクリングが趣味でなのでその風景をライブしたいと思っていました。持っているアクションカメラがGoproであり、一応公式のスマホアプリを使用することでyoutubeライブをすることができるのですが以下の懸念がありました。
Goproは簡単にライブ配信ができるのですが、以下の様なカメラ・スマホ側の要因によってライブが中断される可能性があります。
本当に中断されるかは 未検証 ですが可能性があるのでこれを避けるためには「Gopro側からライブの設定を制御するのでなく、Goproからは音声と映像を取得するのみで配信は別環境で行う」ことがベストな気がします。
ライブ配信では映しっぱなしでもいいのですが、撮影禁止の箇所だったり環境によって映像のON/OFFを切り替えたいと思っています。Goproアプリは確かにライブ配信は簡単なのですが、より細かい設定や制御は実装されていません。
スマホ通じてライブ配信をする場合はどうやら50人が必要でしたが、RTMPやPCからであれば0人でもOKでした。
登録者的な問題だったり、より細かい制御を実装するために以下のような構成を考えた結果、まずは自前RTMPサーバーへの映像の送信と再生ができるかをテストしてみたかった次第です。最終的にはRTMPサーバーから映像を取得してyoutubeに流します。サーバーでは映像の表示制御やyoutubeのコメント読み上げなど配信に関係する機能を管理するものとします。
この記事での目標は
まずはRTMPサーバーの実装を行います。使用しているOSはmacOs Catalina 10.15.5でdockerは3.5.2です。実装の手順としては
ここまで出ているRTMPとはReal Time Messaging ProtocolのことでTCP上のプロトコルで映像、音声、データを細かいフラグメントに分けてストリーミング送信ができます。今回のようなリアルタイムに映像を撮影してサーバーに送信する際にも利用されます。
NginxではRTMPモジュールというのがあり、インストールしてconfファイルに少し記述するだけで1935ポートにrtmp://example.com/live
のようなURLでサーバーに送信できます。
では早速やっていきましょう。rtmptest
みたいな適当なディレクトリを作成して、Dockerfile
とdocker-compose.yml
ファイルを作成します。また、webとconfファイルを格納してボリュームしておくディレクトリも作成します。
mkdir rtmptest
cd rtmptest
touch Dockerfile docker-compose.yml
mkdir html conf
Dockerfileは以下のようにしておきます。
FROM tiangolo/nginx-rtmp
VOLUME ["/usr/share/nginx/html","/etc/nginx"]
今回はrtmpの設定があるnginxのイメージを利用します。
docker-compose.yml
は以下の通りです。
version: '2'
services:
app:
build: .
ports:
- "8085:80"
- "1935:1935"
volumes:
- ./html:/usr/share/nginx/html
- ./conf/nginx.conf:/etc/nginx/nginx.conf
- ./conf/default.conf:/etc/nginx/conf.d/default.conf
nginxのconfファイルを調整してRTMPとwebアクセスができるようにします。
RTMPはnginx.confというapacheで言うhttp.confに以下のように記述します。
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
rtmp_auto_push on;
rtmp {
server {
listen 1935;
listen [::]:1935 ipv6only=on;
access_log /var/log/rtmp_access.log;
chunk_size 4096;
timeout 10s;
application live {
live on;
# HLSの記述欄
hls on;
# ここに映像ファイルが配置される
hls_path /usr/share/nginx/html/hls;
hls_fragment 10s;
}
}
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
このファイルはコンテナ内のnginx.conf
にボリュームします。tiangolo/nginx-rtmpのイメージで生成されるnginx.confはRTMPのために最低限の記述しかないので上記のようにします。
RTMPでは以下の設定です。
rtmp {
server {
listen 1935;
listen [::]:1935 ipv6only=on;
access_log /var/log/rtmp_access.log;
chunk_size 4096;
timeout 10s;
application live {
live on;
# HLSの記述欄
hls on;
# ここに映像ファイルが配置される
hls_path /usr/share/nginx/html/hls;
hls_fragment 10s;
}
}
}
ここでは1935ポートでRTMPをリッスンし、またrtmp://example.com/live
というURLでアップロードできるようにしています。
webは以下のようにしておきます。ドキュメントルートは/usr/share/nginx/html
です。
server {
listen 80;
listen [::]:80;
server_name localhost;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
RTMPを含むNginxの設定はこれでOKです。
html/test.html
として以下のように作成します。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>MediaElement</title>
<!-- MediaElement style -->
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/mediaelement/4.2.9/mediaelementplayer.css" />
</head>
<body>
<!-- MediaElement -->
<script src="//cdnjs.cloudflare.com/ajax/libs/mediaelement/4.2.9/mediaelement-and-player.js"></script>
<video id="player" width="640" height="360">
</body>
<script type="text/javascript">
var player = new MediaElementPlayer('player', {
success: function(mediaElement, originalNode) {
console.log("Player initialised");
}
});
player.setSrc("hls/.m3u8");
</script>
</html>
hlsが再生できるようにjsの再生ライブラリを用意します。hls/.m3u8
については後述します。
docker-compose up -d
を用いてdockerイメージを起動しましょう。
今回のはMac上にRTMPサーバを立てたのでMacのIPを確認しておきます。「システム環境設定」から「ネットワーク」を選択し、Wi-FiからIPアドレスを確認します。このPCは「192.168.0.3」なので
RTMPはrtmp://192.168.0.3/live
、webはhttp://192.168.0.3/index.html
でアクセスできます。
Goproとアプリのテザリングなどは省略します。
公式アプリ(app store) 公式アプリ(android)
goproとアプリを接続して、「ライブの設定」に移動
その他、RTMPを選択
Macと同じwi-fiに接続してrtmp://192.168.0.3/live
をURLに入力
設定が完了したらライブ配信を開始します。
ライブ配信を開始するとRTMPのURLへ動画がアップされていきます。サーバーの方ではドキュメントルートにこの映像のHLSが配置されるようにしたので、マウントの関係上以下のようなディレクトリが発生していると思います。
先程のHTMLにあった「hls/.m3u8
」はサーバーにアップロードされた映像の元でもあるファイルを示しています。
ではhttp://localhost:8085/index.html
でPCから映像を見てみましょう。再生ボタンを押すと以下のようになりました。
しっかりとGoproが写している映像が表示され、音声も流れました。画面を写していましたが、いろいろカメラを回すと確かに映像・音声も切り替わります。
とりあえずこれでライブ配信映像を自前で実装したサーバに送ることが確認できました。今度はサーバー内での映像をyoutubeのlivestreaming apiなどを通じて実際にライブ映像に流せるようにしてみます。
今回参考にした資料です。非常に助かりました。
コメント
コメント読み込み中..