だいぶ前の記事で、リモートのラズパイからカメラ画像を動画としてUDP配信による簡単な監視カメラ化する方法について取り上げていました。

合同会社タコスキングダム|蛸壺の技術ブログ
ffmpegでラズパイゼロからカメラ画像をUDP配信する方法

簡単にできる自分専用動画配信サービスをffmpegでどう実現するかを解説



その際ポイントとなったのが
「ffmpeg」「ffplayer」「v4l2」 のセットアップやコマンドの使い方、ネットワークの設定だったり、少々面倒に感じるポイントがいくつかありました。
今回はもっと簡単にターミナル上に動画を表示させるためのやり方を
「libsixel」 で考えていこうと思います。
なおこの記事の内容では「libsixel」のインストール方法と使用法を解説していませんので、以下の記事を参考にしてください。

参考|【シェルコマンド】WezTermとlibsixelを使ってDebian&MacOSのターミナルで画像をそのまま表示してみる

「FFmpeg-SIXEL」はすでに非推奨の状態



※この節の内容は主題とは直接関係ないので、興味がない場合次節からお読みください。
かつてはターミナルからCUIに直接動画を流すことのできた
「FFmpeg-SIXEL」 ですが、10年弱もメンテナンスされていないため、必須の依存ライブラリのいくつかが現在のラズパイOSで利用不可能となっています。
「FFmpeg-SIXEL」のコンセプトとしては、動画フォーマットに
sixel を組み込んだffmpegであり、

            $ ffmpeg -i 'https://www.youtube.com/watch?v=LLzGBpNlX-c' -f sixel -pix_fmt rgb24 -s 480x270 -
#...ターミナルに直接動画を再生する

        

ようなニッチで面白い仕様のプログラムでした。
なお、通常版のffmpegではストリーミングを直接sixelのフォーマットに変換することができません。
結局は手元のラズパイでビルドインストールできませんでしたが、無駄に時間も取られてしまったため、どこらへんで躓いたのかを記録として残しておきます。

aptからffmpegをアンインストール



一旦、通常版のffmpegを設定ファイル+依存関係にあるパッケージもごっそり削除してみます。

            $ sudo apt --purge remove ffmpeg

        

FFmpeg-SIXELをインストール



ではsixelで動画再生できるようにされた
FFmpeg-SIXEL をソースコードビルドしていきます。

参考|インストール手順

以下は公式通りにコマンドを順に叩きます。

            $ git clone https://github.com/saitoha/FFmpeg-SIXEL
$ cd FFmpeg-SIXEL
$ ./configure --enable-libquvi --enable-libsixel
$ make install
$ ffmpeg -i 'https://www.youtube.com/watch?v=ixaMZPPmVG0' -f sixel -pix_fmt rgb24 -s 480x270 -

        

すると
configure の段階で、どうも libquvi がないらしいエラーが発生します。

            $ ./configure --enable-libquvi --enable-libsixel
ERROR: libquvi not found using pkg-config

If you think configure made a mistake, make sure you are using the latest
version from Git.  If the latest version fails, report the problem to the
ffmpeg-user@ffmpeg.org mailing list or IRC #ffmpeg on irc.freenode.net.
Include the log file "config.log" produced by configure as this will help
solve the problem.

        

そこで、
pkg-config から libquvi を有効する必要がありそうです。
内部の
libquvi を捜索しましょう。

            $ pkg-config --exists --print-errors libquvi
Package libquvi was not found in the pkg-config search path.
Perhaps you should add the directory containing `libquvi.pc'
to the PKG_CONFIG_PATH environment variable
No package 'libquvi' found

        

仕方ないので
libquvi をパッケージインストールしようとすると....、

            $ sudo apt install libquvi
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
E: Unable to locate package libquvi

        

なるほど、パッケージからは利用できそうにないようです。
そこで
libquvi もソースコードインストールを試みます。

            $ git clone https://github.com/mogaal/libquvi.git
$ cd libquvi
$ ./configure && make

configure: error: a2x is required to create man pages when building from git

        

うーん、今度は
a2x が無い。
Debianだと
a2xasciidoc-base の一部らしいので、以下を叩きます。

            $ sudo apt install asciidoc-base

        

これで再度
libquvi をビルドしてみます。

            $ ./configure && make

configure: error: Package requirements (lua-5.1 >= 5.1) were not met:

No package 'lua-5.1' found

        

更に更に、
lua-5.1 も要求されます...こうなったらとことん不足の依存性入れてあげます。


            $ sudo apt install liblua5.1-0-dev liblua50-dev liblualib50-dev

        

で、再度ビルド...、

            No package 'libproxy-1.0' found

        

というのが出ました。
ただ、
libproxy-1.0 のライブラリ依存性かなり古すぎて、最近のDebianでのソースコードビルドが不可能のようです。
これ以上はダメそうなので、
FFmpeg-SIXEL のインストールはここでゲームオーバーとします。


コマ撮りしたjpeg画像をimg2sixelコマンドの表示から逐次更新させる



前節の内容からffmpegから出力する動画フォーマットをsixel形式に対応させることが無理そうということが分かりました。
ただし同じ逆転の発想で、動画を細切りにして連続するJPEG/PNG画像へ変換することができれば、その変換した静止画像を利用して
img2sixel コマンドでターミナルに表示&更新してあげると同じことができそうです。
例えば以下のブログでは、YoutubeLiveから一定間隔で取得した映像をpng画像化し、
img2sixel コマンドにパイプさせてターミナルへ表示させています。

参考|tmux Sixel でリモート画像を表示して遊ぶ

同じような理屈で、ffmpegコマンドが使える場合、画像からコマ撮りさせることが簡単で、そこに
img2sixel コマンドから一定間隔で撮りためた画像を表示させてみましょう。

            $ while true;\
    do ffmpeg -f v4l2 -i /dev/video0 -loglevel -8 \
        -vframes 1 -c:v png -f image2 - | img2sixel; sleep 0.2; \
    done

        

実際にはこれで動くはずなのですが、カメラモジュールV1/V2などの
「レガシーカメラ」 を使うと以下のようなエラーが発生します。

            #...
[video4linux2,v4l2 @ 0x15be900] ioctl(VIDIOC_G_PARM): Inappropriate ioctl for device
[video4linux2,v4l2 @ 0x15be900] Time per frame unknown
[video4linux2,v4l2 @ 0x15be900] ioctl(VIDIOC_STREAMON): Invalid argument
/dev/video0: Invalid argument

        

これはffmpegが内部で利用しているv4l2(video for linux2)がカーネルレベルで
「レガシーカメラは使えないよ」 とエラーを出していることに起因します。
つまり最近のラズパイOSを使う限りでは、カメラモジュールV3相当を装備するか、ffmpeg/v4l2を使うのを諦めるかの選択になります。


レガシーのラズパイカメラでもコマ撮り写真を撮影する方法



ラズパイカメラの連写には、現行のOS標準で利用することのできる
libcamera-vid コマンドが便利です。

libcamera-vid コマンドはラズパイのカメラデバイスから動画を作成するためのものです。
デフォルトでは動画のエンコーディング形式がハードウェアH264ですが、
--codec オプションから MotionJPEG を使うことも可能です。

            $ libcamera-vid -t 10000 --codec mjpeg -o test.mjpeg

        

ただし今回の目的でいうと、MotionJPEGそのものを動画として利用するのではなく、連番のJPEG画像として保存することが好ましいです。
これを可能にするのが、
--segment オプションです。

--segment オプションに連写間隔時間(ミリ秒)を指定することで、おおよそ指定の間隔ごとに写真を撮り、連続するJPEG画像として撮りためることができます。
以下の例であれば、1ミリ秒間隔で10秒(=10000ミリ秒)間JPEG画像を連続で取り続けます。

            $ libcamera-vid -t 10000 --codec mjpeg --segment 1 -o test%05d.jpeg

        

ハードウェアのスペックやカメラの取り込み解像度にもよりますが、手元のラズパイ4で480x320サイズの画像が310枚連写されています。
おおよその概算ですがこの設定だと、写真1コマあたり31ミリ秒強の時間を消費している計算になり、結構高速な撮影になっているように思います。


SSH接続したラズパイでコマ撮りした画像をターミナル上に動画として表示する



先程の内容までで、基礎となるテクニックとポイントを掻い摘んで解説していきました。
ということで、ようやく本題の
WezTerm 越しにSSH接続したラズパイから直接ターミナル上に動画として表示させてみましょう。
なお、
Sixelプロトコル が扱えるターミナルソフトであれば WezTerm でなくても同じことができます。
なお、
WezTerm の画面分割は以下の記事の内容を参考にしてください。

参考|【シェルコマンド】WezTermの画面操作


では、
WezTerm からラズパイにSSH接続し、適当なディレクトリで以下のコマンドからコマ撮りを開始します。

            $ libcamera-vid -t 0 --codec mjpeg --segment 100 -o test.jpeg

        

そして別窓で、SSH接続し、コマ撮り中のJPEG画像のあるフォルダ内で、以下のコマンドを実行します。

            $ while true; \
    do img2sixel test.jpeg 2>/dev/null; sleep 0.1; \
    done

        

するとなんということでしょう。
1秒くらいの遅延は感じるものの、即席の監視カメラとして動かすことができています。
1000x461
合同会社タコスキングダム|蛸壺の技術ブログ


実際の監視カメラとしての実用性は乏しいですが、製品開発段階のカメラの動作チェックや、動画の品質チェックなどで利用できそうなテクニックになるでしょう。

GUIなしの無印ラズパイゼロでもlibsixelは動く

WezTermlibsixel の組み合わせの良いところは、SSH接続できるだけでカメラ側のハードウェアの性能にほぼ関係なく動作してくれる点にあります。
今となってはだいぶスペックも見劣りしてきたクラシックなラズパイゼロでも
libsixel が導入可能です。

            $ sudo apt install libsixel*

        

現行のカメラモジュールのユーティリティである
libcamera-vid コマンドのご先祖にあたる 「raspivid」コマンド の時代にはmotionJPEGフォーマットからJPEGを一枚づつコマ撮りするオプションは無いため、 「raspistill」-tl(--timelapse) オプションで代替します。

-tl オプションを使うとミリ秒で指定した間隔でコマ撮り(連続撮影)モードを使うと良いでしょう。
ということで、古いOSで動いているラズパイでは以下のようにコマ撮りできます。

            $ raspistill -t 0 -w 480 -h 320 -tl 100 -o test.jpeg

        

まとめ



今回はSSH接続を介したラズパイからのカメラ撮影写真を動画風にsixelプロトコルを使ってCUI表示させるテクニックについて解説していきました。
個人的にはトイカメラに高い性能などを要求してはいないのですが、ラズパイカメラモジュールV3などは最近の相場で5,000円を越えてくる高価な製品になってきているため、辛うじてレガシーカメラもまだ利用できるのは少し安心します。
そのうちレガシーカメラが完全に使えなくなる可能性もあるので、今後はできるだけV3モジュールを検討したほうが良いかも知れませんが...。