USB接続のカメラを使ってffmpegでタイムラプス録画

カメラはいろいろ買ったが、結局 BUFFALO BSW20KM11BK を使ってる。

画質はいまいちだけど、画角が広い。そして画角が広いのに湾曲が少なくて見やすい。
夜間は真っ暗で見えなくなるので、この赤外線ライトを併用。一応センサーで暗くなったときだけ点灯する仕組みになっているが、けっこう発熱があって気になる。狭い室内で使うのに48個もいらんだろうという気もするけど、ほかの製品が見つからなかったので仕方ない。
カメラは分解して赤外線フィルターをはずした。これで暗闇でも赤外線ので映るようになる。画質は悪いけど。


録画のソフトは iSpy というソフトを使っていた。
これはすごく多機能だけど、実際のところタイムラプス録画の機能しか使ってなかった。
タイムラプスでは1秒に1フレーム撮影し、60fpsの動画として書き出し、1時間を1分でみられるように設定していたのだが、撮影間隔が秒単位でしか設定できないのがいまいちだった。できれば1秒に2フレーム撮影したい。


調べてみるとffmpegを使えば、このへんも柔軟にできそうだったので試してみた。
まず接続されているカメラの名前を調べる。

ffmpeg -f dshow -list_devices true -i dummy
[dshow @ 005936a0] DirectShow video devices (some may be both video and audio devices)
[dshow @ 005936a0]  "USB_Camera"
[dshow @ 005936a0]     Alternative name "@device_pnp_\\?\usb#vid_0458&pid_708c&mi_00#6&29a4ead7&0&0000#{65e8773d-8f56-11
d0-a3b9-00a0c9223196}\global"
[dshow @ 005936a0] DirectShow audio devices
[dshow @ 005936a0]  "繝槭う繧ッ (USB2.0 MIC)"
[dshow @ 005936a0]     Alternative name "@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\wave_{C5E9D1FA-0676-44FA-BC07
-D2D860F8A479}"

"USB_Camera" が見つかった。今度はこのカメラがサポートしているフォーマットを確認する。

ffmpeg -f dshow -list_options true -i video="USB_Camera"
[dshow @ 057f36a0] DirectShow video device options (from video devices)
[dshow @ 057f36a0]  Pin "繧ュ繝」繝励メ繝」" (alternative pin name "0")
[dshow @ 057f36a0]   pixel_format=yuyv422  min s=640x480 fps=30 max s=640x480 fps=30
[dshow @ 057f36a0]   pixel_format=yuyv422  min s=640x480 fps=30 max s=640x480 fps=30
[dshow @ 057f36a0]   pixel_format=yuyv422  min s=160x120 fps=30 max s=160x120 fps=30
[dshow @ 057f36a0]   pixel_format=yuyv422  min s=160x120 fps=30 max s=160x120 fps=30
[dshow @ 057f36a0]   pixel_format=yuyv422  min s=176x144 fps=30 max s=176x144 fps=30
[dshow @ 057f36a0]   pixel_format=yuyv422  min s=176x144 fps=30 max s=176x144 fps=30
[dshow @ 057f36a0]   pixel_format=yuyv422  min s=320x240 fps=30 max s=320x240 fps=30
[dshow @ 057f36a0]   pixel_format=yuyv422  min s=320x240 fps=30 max s=320x240 fps=30
[dshow @ 057f36a0]   pixel_format=yuyv422  min s=352x288 fps=30 max s=352x288 fps=30
[dshow @ 057f36a0]   pixel_format=yuyv422  min s=352x288 fps=30 max s=352x288 fps=30
[dshow @ 057f36a0]   pixel_format=yuyv422  min s=800x600 fps=10 max s=800x600 fps=10
[dshow @ 057f36a0]   pixel_format=yuyv422  min s=800x600 fps=10 max s=800x600 fps=10
[dshow @ 057f36a0]   pixel_format=yuyv422  min s=1280x720 fps=8 max s=1280x720 fps=8
[dshow @ 057f36a0]   pixel_format=yuyv422  min s=1280x720 fps=8 max s=1280x720 fps=8
[dshow @ 057f36a0]   pixel_format=yuyv422  min s=1920x1080 fps=5 max s=1920x1080 fps=5
[dshow @ 057f36a0]   pixel_format=yuyv422  min s=1920x1080 fps=5 max s=1920x1080 fps=5
[dshow @ 057f36a0]   vcodec=mjpeg  min s=640x480 fps=30 max s=640x480 fps=30
[dshow @ 057f36a0]   vcodec=mjpeg  min s=640x480 fps=30 max s=640x480 fps=30
[dshow @ 057f36a0]   vcodec=mjpeg  min s=160x120 fps=30 max s=160x120 fps=30
[dshow @ 057f36a0]   vcodec=mjpeg  min s=160x120 fps=30 max s=160x120 fps=30
[dshow @ 057f36a0]   vcodec=mjpeg  min s=176x144 fps=30 max s=176x144 fps=30
[dshow @ 057f36a0]   vcodec=mjpeg  min s=176x144 fps=30 max s=176x144 fps=30
[dshow @ 057f36a0]   vcodec=mjpeg  min s=320x240 fps=30 max s=320x240 fps=30
[dshow @ 057f36a0]   vcodec=mjpeg  min s=320x240 fps=30 max s=320x240 fps=30
[dshow @ 057f36a0]   vcodec=mjpeg  min s=352x288 fps=30 max s=352x288 fps=30
[dshow @ 057f36a0]   vcodec=mjpeg  min s=352x288 fps=30 max s=352x288 fps=30
[dshow @ 057f36a0]   vcodec=mjpeg  min s=800x600 fps=30 max s=800x600 fps=30
[dshow @ 057f36a0]   vcodec=mjpeg  min s=800x600 fps=30 max s=800x600 fps=30
[dshow @ 057f36a0]   vcodec=mjpeg  min s=1280x720 fps=30 max s=1280x720 fps=30
[dshow @ 057f36a0]   vcodec=mjpeg  min s=1280x720 fps=30 max s=1280x720 fps=30
[dshow @ 057f36a0]   vcodec=mjpeg  min s=1920x1080 fps=30 max s=1920x1080 fps=30
[dshow @ 057f36a0]   vcodec=mjpeg  min s=1920x1080 fps=30 max s=1920x1080 fps=30
video=USB_Camera: Immediate exit requested

カメラはここに表示されたフォーマットでしか取り込めないので、-vcodec、-pixel_format、-video_size、-framerate オプションで指定する必要がある。
試行錯誤してできあがったコマンドラインは以下の通り。

ffmpeg -hide_banner -t 録画する秒数 -f dshow
    -pixel_format yuyv422 -video_size 1280x720 -framerate 8
    -i video="USB_Camera"'
    -r 60 -c:v libx264 -pix_fmt yuv420p -preset slow -crf 24
    -filter:v setpts=0.0333*PTS,hqdn3d=15:15:20:20,drawtext="fontfile=ariblk.ttf:fontcolor=white:shadowcolor=black:shadowx=2:shadowy=2:fontsize=50:x=(w-text_w)/2:y=8:text=%{localtime}"
    出力ファイル名

これで1秒に2フレーム撮影して60fpsで書き出せた。(と思う)
ざっくり言うと、1〜3行までが入力の設定、3〜4行が出力の設定。hqdn3dというのがノイズ除去の設定。監視カメラは位置が固定されているので、ノイズ除去すればするほどファイルサイズが縮む。-crf 24 と画質は低めにしてるけど「ネコがどう移動しているか確認する」という目的にはじゅうぶん。
iSpy を使っていたときに比べて、時間当たりのフレーム数は倍になったのにファイルサイズは半分以下になった。これでリモートからの確認もしやすくなりそう。