FreeBSDとffmpegでライブカメラ

ffmpeg+ffserverを使ってFreeBSDでストリーミングサーバを作ってみました. USBカメラからの入力をエンコードしつつ,asf形式で流しています.

ffmpegは エンコーダ(ffmpeg)とストリーミングサーバ(ffserver)がセットになっています. Linux用のソフトみたいですが,FreeBSDのPortsにも入っているので導入は簡単です. エンコード形式には,asfの他にMPEGやRealMediaにも対応しているようです.

環境

インストール

Ports/Package から multimedia/ffmpeg をインストールするだけです. 現在の最新版はversion 0.4.9で,サポートされているエンコード形式が増えたようです.

エンコード

まずは,映像をエンコードできることから確認します. video4linuxのディバイスからならば,直接読み込めますが, 名前から想像できる通りFreeBSDでは使えません. そこで,標準入力から読み込むことにします. そのため,標準出力に連続した画像データをひたすら(ヘッダも何も付けないで)出力する プログラムが必要になります.

./ff_camera -t ov511 -r 8 -s 320x240 | ffmpeg -t 10 -r 8 -s 320x240 -f rawvideo -pix_fmt rgb24 -i pipe: test.mpg

ff_cameraはUSBカメラからの動画を指定されたフレームレートで取り込み, 24ビットRGB形式でひたすら標準出力に吐き出すプログラムです. 上の例では,10秒間,8fpsで,320x240のサイズでエンコードして保存します. 出力フォーマットは,指定しなければ拡張子から予測してくれるようです.

他にも,動画ファイルを入力にして再エンコードしたり, 複数の静止画を動画にしたりもできるようです.

ffmpegのオプション

良く使うオプションです.

ストリーミング

ffserver.conf

ffserverの設定はffserver.confで行います. Portsから入れた場合は,/usr/local/etc/ffserver.confにあります. ffserver.conf.sampleという名前でサンプルがあると思うのでそれを参考に書いていきます.

Port 8090
BindAddress 0.0.0.0
MaxClients 100
CustomLog -

# Camera-1

<Feed feed1.ffm>
File /tmp/ram/feed1.ffm
FileMaxSize 200K
ACL allow 127.0.0.1
</Feed>

<Stream cam01.asf>
Feed feed1.ffm
Format asf
VideoBitRate 200
VideoFrameRate 8
VideoSize 320x240
VideoGopSize 20
NoAudio
StartSendOnKey
</Stream>

<Stream cam01.jpg>
Feed feed1.ffm
Format jpeg
VideoFrameRate 2
VideoIntraOnly
VideoSize 320x240
NoAudio
</Stream>


# Camera-2

<Feed feed2.ffm>
File /tmp/ram/feed2.ffm
FileMaxSize 200K
ACL allow 127.0.0.1
</Feed>

<Stream cam02.asf>
Feed feed2.ffm
Format asf
VideoBitRate 128
VideoFrameRate 3
VideoSize 320x240
VideoGopSize 20
NoAudio
StartSendOnKey
</Stream>

<Stream cam02.jpg>
Feed feed2.ffm
Format jpeg
VideoFrameRate 1
VideoIntraOnly
VideoSize 320x240
NoAudio
</Stream>


<Stream stat.html>
Format status
ACL allow localhost
</Stream>

<Redirect index.html>
URL http://kstm.org/
</Redirect>

データの受け渡し

上の設定で,http://kstm.org:8090/feed1.ffm にデータの受け渡し用のインターフェイスが 用意されたので,ffmpegからURLを指定して,ffserverにデータを渡します. /tmp/ramはmdディバイスのRAMドライブにしてみました.

./ff_camera -t ov511 -r 8 -s 320x240 | ffmpeg -r 8 -s 320x240 -f rawvideo -pix_fmt rgb24 -i pipe: http://kstm.org:8090/feed1.ffm

asxファイル

これで,「http://kstm.org:8090/cam01.asf」などでエンコードされたデータに アクセスできるようになりましたが,これだとブラウザからアクセスしても, ダウンロードしようとするだけなので,以下のような内容のasxファイルを書く必要があります.

<ASX version = "3.0">
  <Entry>
    <Ref href="http://www.kstm.org:8090/cam01.asf" />
  </Entry>
</ASX>

これをcam01.asxなどの名前で保存して,メディアプレーヤで開けばストリーミングで 再生されるはずです. Apacheデフォルトのmime.typesには,asxは登録されていないので, asf,asx の Content-type を video/x-ms-asf にしておく必要があります. 設定しないと,ブラウザによってはファイルの内容を表示してしまうことがあります.

遅延

VideoGopSizeで指定したフレームだけまとめてエンコードするので, VideoGopSize/VideoFrameRate秒の時間の遅延が発生します. ただし,VideoGopSizeを小さくしすぎると,画質が悪くなります. それよりも大きな原因は,クライアントのバッファリングなので, プレーヤで設定を変えれば多少よくなると思います. まぁ,手元にカメラが無い限り数秒の遅延には気付かないと思いますが…….

CPUの占有

アクセスが無いときも,処理はしているようでCPUを4〜5%くらい占有しているのが気になります.

ツール

とりあえず,ソースを公開.殆ど寄せ集めです. Sonixのカメラは,takaM氏が 公開しているソースを使いました. CV511はvidを基にしています(かなり弄ってるので怪しいかもしれません).

使い方

汚いですが,ソースを読んでください. 最低限の機能しかないので,いじれる人は好きなようにいじって使ってください. wcamは指定したポートで待ち受けて,ブラウザからアクセスされるとjpegデータを 送りつけるプログラムです.毎分,指定したファイルに出力することも出来ます. ff_cameraは,RGBの無圧縮データを標準出力にはき続けるプログラムです. ffmpegの入力データとして使ってください.

文書の履歴

ksk@kstm