まだ完成したわけではないが、ここ数日の苦闘を繰り返さないためにメモ。
Goproにはプレビューモードというビデオを録画しないで見る機能がある。
あとから写真を撮るのだが、状況を知るためにビデオでも使いたいと考える。
同様のケースは「家庭内にIPカメラを置き、自宅にWebサーバーをたてて外部からブラウザーで見たい」なんて場合にありえるはず。
でも解決策を書いた人はいないように思える。ここ何日も探したんだけど。。。
GoproのプレビューモードはQUIKで指定すると、GoproがアクセスポイントとなるWiFi接続となることはGoproユーザーならご存知のとおり。
Open Gopro APIでプレビューストリームを流すように命令すると、GoproのAP内でのURL (udp://10.5.5.9:8556)でビデオストリームが流れてくる。
このデータをなんとかhttp接続したブラウザーから見たい。
Goproだけではなんともならないので、Raspberry Piを使う。
世の中にあるRaspberry Piにカメラを接続する例は99%がRaspberry Pi標準のカメラモジュールを接続した話しだ。
そんなものは今さら私が記事を書かなくても、もっといい記事がいくらでもある。
USBカメラを接続した場合は、MJPG StreamerのRaspberry Pi版を使えば可能である。
問題は今回のようなネットワーク経由UDPデータストリームだ。
Raspberry Piに接続したディスプレイで見るのでよいならば、Intel様謹製のCV2でOK.
今回の事例は、ストリーミングをhttp経由で見たいのだ。
調べるとプロトコルは二種類。HLSというAppleが作ったものと、DASHという業界標準。HLSはGoogle Chromeではうまく処理されないという話しを見つけたのでDASHにする。どちらのプロトコルであっても考え方は似たりよったりで、マニフェストファイル(.m3u8はHLS、.mpdはDASH)を読み取り、ビデオファイルを再生するという方法を取っている。(この単純な考え方を示した文書が、なかなか見つからず苦労した)
だから解決するアイデアは、ffmjpgという動画変換でよく使われるパッケージを利用して、udpストリームをDASHに変換する。それを見られるHTMLファイルを作ればいいということになる。
WebサーバーはRaspiなので軽量なLighttpdにした。
1. Goproのプレビューストリームを開始する。
以下がGoproへコマンドを出すプログラム。開始前にちゃんとGoproのWiFiアクセスポイントに接続しておく必要がある。
import sys
import json
import requests
GOPRO_BASE_URL = "http://10.5.5.9:8080"
cmd = GOPRO_BASE_URL + "/gopro/camera/stream/stop"
response = requests.get(cmd,timeout=10)
response.raise_for_status()
print( cmd + " is OK")
cmd = GOPRO_BASE_URL + "/gopro/camera/stream/start?port=8556"
response = requests.get(cmd, timeout=10)
response.raise_for_status()
print(cmd + " is OK")
# GoPro default video stream port is; 8556
2. ffmpegでGoproのUDPストリームをDASHに変換
ffmpegをあらかじめaptでインストール。パラメーターの中で-iで入力udpを指定している。-f で出力フォーマットとマニフェストファイル名を指定している。このファイルは当然、今、ffmpegを動作させている環境にできる。htmlファイルはそこを参照できなければならない。
ffmpeg -i udp:10.5.5.9:8556 \
-c:v libx264 -b:v 1000k -g 48 -keyint_min 48 \
-sc_threshold 0 -an \
-f dash stream.mpd
3. Lighttpdの設定
DASHファイルをビデオとして認識させる。
mimetype.assign = ( ".mpd" => "application/dash+xml", ".m4s" => "video/iso.segment" )
シンボリックリンクをOKにする。
server.follow-symlink = "enable"
これくらいでいいようだ。
4. html
htmlファイルはlighttpdの場合は、/var/www/htmlにできるが、所有者はrootである。それゆえシンボリックリンクを自分のユーザーフォルダーを指すようにした。パスはすべてアクセス可能でなければならない。そうでないとwebサーバーは403 forbiddenを返す。
当たり前なのだが、解説されていない重要項目は黄色でマーカーをつけたファイルが目的のマニフェストファイルである。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Raspberry Pi DASH Streaming</title>
<script src="https://cdn.dashjs.org/latest/dash.all.min.js"></script>
</head>
<body>
<h1>DASH Video Streaming</h1>
<video id="video" controls autoplay style="width: 100%; max-width: 600px;"></video>
<script>
const video = document.getElementById('video');
if ('MediaSource' in window) {
const url = 'http://192.168.100.1/video/stream.mpd';
const player = dashjs.MediaPlayer().create();
player.initialize(video, url, true);
} else {
alert('Your browser does not support DASH.');
}
</script>
</body>
</html>
この例は私が探した限り、ネットで関係記事を見つけられなかった。
今日はここまで。