
この記事はNanoPi NEO用として書いているけどおそらくBanana Pi M2+, Beelink X2, NanoPi M1+, NanoPi NEO Air, NanoPi M1, Orange Pi+ 2, Orange Pi PC+, Orange Pi+ 2e, Orange Pi Lite, Orange Pi 2, Orange Pi One, Orange Pi PC, Orange Pi+ あたりのH3搭載ボードなら同様にできる筈。
NanoPi NEOでウェブカメラを書いてから、あれもこれもやりたいということで忙しくてだいぶ間が空いてしまったが、再びウェブカメラ。
前回は動画の速度と画質を無理くり我慢してなんとか実用ぎりぎり(アウト?)な感じだったので今回はより実用的なものにしたい。
NanoPi NEOで動画がめっちゃ遅いのは動画の支援機能が働いてないから。この手のシングルボードコンピュータはPCと比べるとCPUが圧倒的に遅いので支援無しでHDサイズの動画というのは苦しい。でも、動画支援機能は技術力のあるプログラマでないとなかなか使えないというのが辛いところ。
と、思っていたが、ググるとAllwinnerのSoCなボード用に動画支援機能を追加した改変版FFMpegが出ていた。しかも2年ほど前に・・
今回はこの2つを合わせて使用する。上のリンクがffmpegのソースそのものだけど2年ほど前のものということで、出来上がるFFMpegのバージョンもgit-2015-01-22-f86a076というちょっと古そうなものになる。2つめのリンクはそのH3用パッチ。
この記事ではarmbianのDebian Jessie レガシーカーネル版を使用している。一応、新しいMainline系でも試したが残念ながら支援機能は使えなかった。
$ uname -a Linux nanopineo 3.4.113-sun8i #2 SMP PREEMPT Sat Apr 1 23:02:38 JST 2017 armv7l GNU/Linux
事前準備
必要になるであろうパッケージをインストールする。
# apt-get install libtool pkg-config autogen gettext # apt-get install libx264-dev libv4l-dev libpulse-dev libmp3lame-dev libjson-c-dev libjpeg-dev libflac-dev libogg-dev libvdpau-dev # apt-get install v4l-utils
1行目はアプリケーションをビルドするようなことがあるときに入れておきたいもの。
2行目はffmpegのビルドに必要なパッケージ。今回の記事のconfigureオプションなら上のもので足りる筈だが、他のオプションも追加するなら別途追加が必要になるパッケージがあるかと。
3行目はffmpegのビルドには関係ないが、USBウェブカメラの画質を制御したい場合は入れると良い。(この記事最後の方)
作り方
https://github.com/stulluk/FFmpeg-Cedrus からソースを取得
$ cd ~ $ git clone https://github.com/stulluk/FFmpeg-Cedrus.git
https://github.com/uboborov/ffmpeg_h264_H3 からソースを取得
$ git clone https://github.com/uboborov/ffmpeg_h264_H3.git
以下、ビルド手順
$ cd ~/FFmpeg-Cedrus/libavcodec $ mv cedrus264.c cedrus264.c.ORG $ cp ~/ffmpeg_h264_H3/cedrus264.c ./ $ cd ./arm $ mv sunxi sunxi.ORG $ cp -R ~/ffmpeg_h264_H3/sunxi ./ $ cd ../../ $ ./configure --prefix=/usr --enable-nonfree --enable-gpl --enable-version3 --enable-vdpau --enable-libx264 --enable-libmp3lame --enable-libpulse --enable-libv4l2 $ make -j4 # make install
configureからmake installまでNanoPi NEOでやるとかなりの時間がかかる。
で、今回作ったffmpegが普通のと違うのは通常のH.264用のエンコーダー libx264の他にcedrus264というのが追加されていること。これを使うとかなり速い。
使用してみる
$ ffmpeg -t 60 -f v4l2 -s 1280x720 -i /dev/video0 -pix_fmt nv12 -vcodec libx264 -r 30 ./test.mp4 Input #0, video4linux2,v4l2, from '/dev/video0': Duration: N/A, start: 17743.887218, bitrate: 73728 kb/s Stream #0:0: Video: rawvideo (YUY2 / 0x32595559), yuyv422, 1280x720, 73728 kb/s, 5 fps, 5 tbr, 1000k tbn, 1000k tbc [libx264 @ 0x218c510] using cpu capabilities: ARMv6 NEON [libx264 @ 0x218c510] profile High, level 3.1 [libx264 @ 0x218c510] 264 - core 142 r2431 a5831aa - H.264/MPEG-4 AVC codec - Copyleft 2003-2014 - http://www.videolan.org/x264.html - options: cabac=1 ref=3 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=7 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=6 lookahead_threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=40 rc=crf mbtree=1 crf=23.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00 Output #0, mp4, to './test.mp4': Metadata: encoder : Lavf56.2.100 Stream #0:0: Video: h264 (libx264) ([33][0][0][0] / 0x0021), nv12, 1280x720, q=-1--1, 30 fps, 15360 tbn, 30 tbc Metadata: encoder : Lavc56.0.101 libx264 Stream mapping: Stream #0:0 -> #0:0 (rawvideo (native) -> h264 (libx264)) Press [q] to stop, [?] for help frame= 1785 fps= 17 q=-1.0 Lsize= 405kB time=00:00:59.43 bitrate= 55.9kbits/s dup=1672 drop=0 video:384kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 5.659878%
60秒間(-t 60)USBカメラで取得した動画を1280x720の解像度でlibx264を使用してファイルに出力。この時、入力側ではなく出力側のフレームレートを30 (-r 30)に指定。もちろん指定したからといって性能が低ければその値で処理できるわけではない。
そして、表示上は59秒43ぶんを処理したことになっているが、実際にはこの処理は1分46秒かかっている。つまり1785フレームを106秒なので17fps。(1分46秒は上の表示にはなく別途計測したもの)
$ ffmpeg -t 60 -f v4l2 -s 1280x720 -i /dev/video0 -pix_fmt nv12 -vcodec cedrus264 -r 30 ./test.mp4 Input #0, video4linux2,v4l2, from '/dev/video0': Duration: N/A, start: 17418.199590, bitrate: 73728 kb/s Stream #0:0: Video: rawvideo (YUY2 / 0x32595559), yuyv422, 1280x720, 73728 kb/s, 5 fps, 5 tbr, 1000k tbn, 1000k tbc [VDPAU SUNXI] VE version 0x1680 opened. Output #0, mp4, to './test.mp4': Metadata: encoder : Lavf56.2.100 Stream #0:0: Video: h264 (cedrus264) ([33][0][0][0] / 0x0021), nv12, 1280x720, q=2-31, 200 kb/s, 30 fps, 15360 tbn, 30 tbc Metadata: encoder : Lavc56.0.101 cedrus264 Stream mapping: Stream #0:0 -> #0:0 (rawvideo (native) -> h264 (cedrus264)) Press [q] to stop, [?] for help frame= 1798 fps= 32 q=30.0 Lsize= 2175kB time=00:00:59.93 bitrate= 297.4kbits/s dup=1504 drop=0 video:2168kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.359510%
条件は前と同じで、vcodecにcedrus264を指定した。
表示上は59秒93となっているが実処理時間は1分1秒。ほぼ指定どおり。1798フレームを61秒なので29.5fpsとこちらも指定に近いものになっている。
ただし、被写体の変化が少ないものであればこのように順調だが被写体が動くとときどき詰まってその後ワープが発生したようになる。
でもかなり良い感じ。
ffmpegの細かいオプション指定は実際の画質を見てどこまで我慢できるかなのでこの記事ではこれ以上やらない。
ストリーミング
NanoPi NEOは基本的にはストレージはmicroSD。もちろんUSBでハードディスク等を繋ぐというのもアリだろうが、それだとNanoPi NEOのせっかくの小型さが台無し。
そこでNanoPi NEOを監視カメラにしようというのなら本体に動画を保存するのではなく、ネットワークで飛ばして他の端末で録画・再生するというのが良いと思う。要するにやりたいことは前回と同じくストリーミング。
前回はカメラからの動画の取得とストリーミングにVLCを使ったが、今回はここまでFFMpegでやってきたのでストリーミングもFFMpegで。単に出力先をファイルからネットワークに変更する程度なので実は簡単。
$ ffmpeg -f v4l2 -i /dev/video0 -vcodec cedrus264 -s 1280x720 -pix_fmt nv12 -b:v 4096k -f mpegts udp://192.168.0.200:10000
mpegts形式で192.168.0.200 ポート10000に向けてUDPで送信。192.168.0.200とポート10000は受信させたい端末・サーバのものであって、送信しようとしているNanoPi NEOのIPアドレスとポートではないので注意。
ストリーミングで受信する側の端末・サーバ側。例えばPCでVLCを使って観るなら「ネットワークストリームを開く」で「ネットワークURL」に以下を指定。udp://@:10000
このときNanoPi NEOのIPアドレスを指定するのではない点に注意。
動画再生が始まらない場合があるが、プレーヤー側を待ち受け状態(ネットワークURLを指定して実行)にしてからNanoPi側を動かす方が成功しやすいかも。
$ ffmpeg -framerate 15 -f v4l2 -s 1280x720 -i /dev/video0 -pix_fmt nv12 -vcodec cedrus264 -r 15 -f mpegts udp://192.168.0.10:10000 ffmpeg version git-2015-01-22-f86a076 Copyright (c) 2000-2014 the FFmpeg developers built on Apr 2 2017 13:29:23 with gcc 4.9.2 (Debian 4.9.2-10) configuration: --prefix=/usr --enable-nonfree --enable-gpl --enable-version3 --enable-vdpau --enable-libx264 --enable-libmp3lame --enable-libpulse --enable-libv4l2 libavutil 54. 6.100 / 54. 6.100 libavcodec 56. 0.101 / 56. 0.101 libavformat 56. 2.100 / 56. 2.100 libavdevice 56. 0.100 / 56. 0.100 libavfilter 5. 0.102 / 5. 0.102 libswscale 3. 0.100 / 3. 0.100 libswresample 1. 1.100 / 1. 1.100 libpostproc 53. 0.100 / 53. 0.100 [video4linux2,v4l2 @ 0x230a4b0] The driver changed the time per frame from 1/15 to 2/15 Input #0, video4linux2,v4l2, from '/dev/video0': Duration: N/A, start: 67485.253012, bitrate: 110592 kb/s Stream #0:0: Video: rawvideo (YUY2 / 0x32595559), yuyv422, 1280x720, 110592 kb/s, 7.50 fps, 7.50 tbr, 1000k tbn, 1000k tbc [VDPAU SUNXI] VE version 0x1680 opened. Output #0, mpegts, to 'udp://192.168.0.10:10000': Metadata: encoder : Lavf56.2.100 Stream #0:0: Video: h264 (cedrus264), nv12, 1280x720, q=2-31, 200 kb/s, 15 fps, 90k tbn, 15 tbc Metadata: encoder : Lavc56.0.101 cedrus264 Stream mapping: Stream #0:0 -> #0:0 (rawvideo (native) -> h264 (cedrus264)) Press [q] to stop, [?] for help frame= 932 fps= 15 q=30.0 Lsize= 60678kB time=00:01:02.13 bitrate=8000.2kbits/s dup=630 drop=0 video:56185kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 7.997251%
無理の無い現実的な値として入力側出力側共に15FPSを指定した。これだと被写体のワープや大きな遅延は発生しない感じ。指定した15FPSよりもコマ送り感があるけど監視カメラだからこんなもんでしょ。
ここまで音声無しでやってるけど音声乗せるのもFFmpegの設定しだい。
NanoPi NEO2でも試してみた。NanoPi NEO2のSoCのAllwinner H5ではGPU Mali450 MP4が利用できるということになっているけどarmbianではドライバが動かないしドライバがあっても使える自信がないので実質使えないものと思っている。
$ ffmpeg -f v4l2 -i /dev/video0 -vcodec libx264 -s 1280x720 -pix_fmt yuv420p -maxrate 400k -bufsize 1600k -preset ultrafast -f mpegts udp://192.168.0.10:10000
上の方とは条件を変えているが、NanoPi NEO2ではGPUの支援無しで17fps程度出ている。カクツキや動く被写体のワープもないので良い感じ。ただし、ときどき1〜2秒程度画面が灰色になることはある。
17fps出るなら監視カメラとしては十分すぎるのでNEO2はオススメかも。
カメラの画質変更
ffmpegの動画の画質の話ではなくカメラ側の画質の変更の話。昼の屋外などで動画が明るすぎる(白っぽい)ので暗めにしたいなど画質を変更したい場合。
まず、コントロールできる内容を表示してみる。
# v4l2-ctl -d /dev/video0 --list-ctrls error 22 getting ctrl Brightness error 22 getting ctrl Contrast error 22 getting ctrl Saturation error 22 getting ctrl White Balance Temperature, Auto error 22 getting ctrl Gain error 22 getting ctrl Power Line Frequency error 22 getting ctrl White Balance Temperature error 22 getting ctrl Sharpness error 22 getting ctrl Backlight Compensation exposure_auto (menu) : min=0 max=3 default=3 value=3 exposure_absolute (int) : min=1 max=10000 step=1 default=166 value=8 exposure_auto_priority (bool) : default=0 value=1 error 22 getting ctrl Brightness error 22 getting ctrl Contrast error 22 getting ctrl Saturation error 22 getting ctrl White Balance Temperature, Auto error 22 getting ctrl Gain error 22 getting ctrl Power Line Frequency error 22 getting ctrl White Balance Temperature error 22 getting ctrl Sharpness error 22 getting ctrl Backlight Compensation
今回使用したのが安物カメラだからか殆どの項目がエラーで触れない。コントロールできる項目は真ん中辺りの3つで「露光」関係だけ。現在は露光が自動になっいて、表示した時点のexposure_absolute値は8。(valueを見る)
以下のようにして指定したい値をセットする。
# v4l2-ctl -d /dev/video0 --set-ctrl=項目名=セットしたい値
デバイスが1つしかなければ -d /dev/video0 は入力しなくても大丈夫っぽい。
露光を自動からマニュアルに変える(下)。これをしないとその次の値の変更ができない。
# v4l2-ctl -d /dev/video0 --set-ctrl=exposure_auto=1
上の例では屋外の明るいところを撮っていて、露光(時間)の値が8だったのでこれより暗くするのはあまり選択範囲がない。とりあえず最低値の1を指定。 (数字を大きくしたら明るくなる=暗い所用、数字を小さくしたら暗くなる=明るい所用)
# v4l2-ctl -d /dev/video0 --set-ctrl=exposure_absolute=1
画面全体が白っぽいのは抑えられたので一応成功とはいえる。
でも、マニュアルにすると明るさが変わるところでは都度変更しなきゃならないので自動に戻しておいた方が良さそう。
# v4l2-ctl -d /dev/video0 --set-ctrl=exposure_absolute=8 # v4l2-ctl -d /dev/video0 --set-ctrl=exposure_auto=3
これまで「がとらぼ」のNanoPi NEOを何かに使う関係の記事はどれもこれも中途半端だったけど、ようやく「監視カメラ」として「使いものになる」と言えるものが出来た?
お値段的にはNanoPi NEO(無印)+ヒートシンク+送料、LOGICOOLウェブカメラC270(こちらはamazon送料無料)、合計約2,500〜3,000円。(電源とmicroSDカードは入ってない)
でネットワーク(ストリーミング)カメラとしては格安ということになる。
- NanoPi NEOでウェブカメラ (実用化編) ←いまここ
- NanoPi NEOでウェブカメラ この記事の前編
- ESP32-CAMで作る監視カメラ (RTSPストリーミング編)
- もしも、261円の怪しい中華Wi-Fiカメラを買ってみたら
- シングルボードコンピュータでAgent DVRを動かしてNVRサーバにする 後編
- シングルボードコンピュータでAgent DVRを動かしてNVRサーバにする 前編
- 中華の安物NVRボード用にケースを作ってみた
- 中華の安物NVRボードを設定してみた+謎通信の遮断
- 中華の安物NVRボードを買ってみた
- ESP32-CAMで作るリビングカメラ (工作編)
- ONVIF対応監視カメラをNVRサーバに登録して使用する
- 2つのLANをつなぐルーター作成
- Banggoodで1530円の1080P監視カメラを買ってみた
- アッチッチなNanoPi NEO3を冷やしたい パッド交換
- NanoPi NEO3冷却力強化後のUnixBench
- アッチッチなNanoPi NEO3を冷やしたい
- NTPサーバの時刻ソースに対するズレの調整
- NanoPi NEO3をv6プラスのルーターにする systemd-networkd + nftables
- NanoPi NEO3のUSB3.0ポートのネットワーク速度
- NanoPi NEO3でArmbian よきところでUnixBench
- NanoPi NEO3が届いた
- NanoPi NEOにRTCモジュールを付ける
- 新しい中華GPSモジュールとChronyで作るNTPサーバ (中編)
- 新しい中華GPSモジュールとChronyで作るNTPサーバ (前編)
- Prometheus2とGrafana6によるシステム監視 シングルボードコンピュータの温度表示
- NanoPi NEOでNTPサーバ再構築 (全まとめ)
- NanoPi NEO2をv6プラスのルーターにする 後編
- NanoPi NEO2をv6プラスのルーターにする 前編
- ELK Stackでシステム監視 FilebeatでNTP統計ログ取得 Logstashで加工
- NanoPi NEO2(arm64)用にFilebeatをビルド
- NanoPi NEO2を超コンパクトなアルミケースに入れる
- NanoPi NEO2用armbian 5.41 Debian 9 Stretch next 4.14.18