Posted by & filed under debian, iphone, Linux.

寝かしつけた息子を寝室に置いてテレビを観たいという嫁のリクエストを叶えるべく、ありもののwebcamと古いラップトップでwebcamの配信システムを構築した。およそ30秒ほど過去の息子の動静がiPadから確認できる。(むっちゃずれてるけど)音声も付いているので、起きたかどうかも音で確認できる。

仕様

  • HLSストリーミングの仕組みを利用し、shmに分割されたビデオtsを吐き出し直接nginxで公開する
  • HLS対応の出力はffmpegに実装されているものを使う
  • 音声つきビデオとする。ビデオが記録された時刻を画面左上に表示する

以下のサンプルの場合、iPadなどから http://yourhost/live/home/index.html にアクセスし、ビデオをタップすることでストリーミングが見られる。

構築にあたり気をつけた点

iPad対応にするため、ビデオのキーフレームをドキュメントにある90に指定(たぶん30とかでも良いのだろうが、チャートに従った)。
分割のタイミングとキーフレームが挿入されるタイミングを合わせた(試行錯誤の中でやった工夫なので、実際に必要かどうかは不明)。
ffmpegは使い終ったtsの削除をしてくれない。
音声がずれたりプチプチノイズが入る。サンプリングレートの指定をやめたことでノイズは消えたが、ズレはそのままとなっている。
apacheでなくnginxを使ったのは、最初rtmp方面から攻めたことによる名残である。rtmpの試行ではnginx-rtmp-moduleを使った。レイテンシが1分以上になる上にvlc以外で再生できないようなザンネンなストリームしか吐かせることができなかった。

用意するもの

もともとラップトップに入っていた debian gnu/linux を利用した。ffmpegはdebian-multimedia版のnonfreeライブラリを含むものを使用している。

必須

いずれもaptで導入。
nginx
ffmpeg
mplus fontdone
chrony -> ビデオにインポーズする時刻が狂うといろいろ都合が悪いため

あった方が良い

avahi -> ころころ変わるipなんか打ってられないという方に

デーモン化にはsystemdを利用した。

PCはdell latitude 4200 C2D。LogicoolのWebcam C525を利用。ラズパイで動いたらいいなー。

コード

code: /usr/local/bin/ffmpeg.sh

#!/usr/bin/env bash

BASE=/dev/shm/nginx-hls/home
mkdir -p $BASE
find $BASE -type f -delete

RES=640x360
#RES=960x544
#RES=1280x720

BRATE=600k
#BRATE=1200k
#BRATE=1800k
#BRATE=2500k

W=${RES%%x*}
H=${RES##*x}

cat > $BASE/index.html <<EOF
<html>
<head>
    <title>My son</title>
</head>
<body>
    <video src="http://yourhost/live/home/index.m3u8" height="$H" width="$W" >
    </video>
</body>
</html>
EOF

(sleep 12;
 while [ -e $BASE/index.m3u8 ]; do
   find $BASE -newer $BASE/index.m3u8 -prune -o -name '*.ts' -print | \
     grep -v -f $BASE/index.m3u8 | \
     xargs rm 2> /dev/null && true;
   sleep 6;
 done) &

trap "{ rm $BASE/index.m3u8; exit 0; }" TERM EXIT

ffmpeg \
 -y -threads 0 \
 -f v4l2 \
 -video_size $RES \
 -timestamps abs \
 -r 15 \
 -i /dev/video0 \
 -f alsa -thread_queue_size 1024 \
 -i "default:CARD=C525" \
 -ac 1 -strict -2 \
 -vcodec libx264 \
 -filter:v "drawtext=fontfile=/usr/share/fonts/truetype/mplus/mplus-2m-medium.ttf: text='%{localtime}': fontcolor=white@0.8: x=5: y=5" \
 -profile:v high -level 4.0 \
 -preset ultrafast \
 -pix_fmt yuv420p \
 -force_key_frames 'expr:gte(t,n_forced*6)' \
 -b:v $BRATE \
 -acodec libfaac \
 -b:a 40k \
 -filter:a "aresample=async=100, highpass=f=200, lowpass=f=3500" \
 -f segment -segment_time 6 \
 -segment_format mpegts \
 -segment_list $BASE/index.m3u8 \
 -segment_list_size 12 -segment_list_flags live \
 -segment_list_type m3u8 $BASE/%08d.ts

code: /etc/systemd/service/webcam.service

[Unit]
Description=Webcam HLS service
After=network.target auditd.service

[Service]
ExecStart=/usr/local/bin/ffmpeg.sh

[Install]
WantedBy=multi-user.target

* 以下登録のコマンド

# systemctl daemon-reload
# systemctl enable webcam

code: /etc/nginx/sites-available/default

server {
        ... snip ...
	location /live {
                types {
                    text/html html;
                    application/vnd.apple.mpegurl m3u8;
                    video/mp2t ts;
                }
                alias /dev/shm/nginx-hls;
                add_header Cache-Control no-cache;
	}
        ... snip ...
}

参考文献

iOS対応VIDEOの情報
https://developer.apple.com/library/ios/documentation/…/TP40008332-CH102-SW21

ffmpegで時刻のインポーズ
http://einar.slaskete.net/2011/09/05/adding-time-stamp-overlay-to-video-stream-using-ffmpeg/

grepのパターンをファイルから読む(ts削除のロジック)
http://unix.stackexchange.com/questions/83260/reading-grep-patterns-from-a-file

ALSA使うと [alsa @ 0x1d83640] ALSA buffer xrun. が出る不具合
http://stackoverflow.com/questions/28359855/alsa-buffer-xrun-induced-by-low-quality-source-in-ffmpeg-capture

ビットレート設定など
https://ffmpeg.org/ffmpeg.html

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です