Jetson nano 2GB: USBカメラとPython FlaskでWeb動画ストリーミング

この記事はMDCアドベントカレンダー22日目の記事となる。

はじめに

機能概要

  • Webブラウザ経由でUSBカメラでキャプチャした動画(連続画像)を表示
  • 音声なし、動画の同時表示クライアント数は1つ

実行時のイメージ

紹介するソースコードの実行時のイメージは以下の通り。自身が想定した以上にヌルヌル動くので驚きだった。

USBカメラのキャプチャ内容をWebブラウザでストリーミング配信中

実行環境

本体(+ソフトウェアのバージョン)と付属部品を紹介する。

Jetson nano 2GB 本体

NVIDIA Jetson Nano 2GB 開発者キット JETSON NANO 2GB DEV KIT

初期設定時はモニタ・キーボード・マウス等ケーブルに囚われるイメージだが、VNC, ssh周りの設定が完了すれば2枚目の画像の通り多少はスッキリする。

初回起動・初期設定時
リモート開発環境の設定後

OSバージョン

Python、パッケージバージョン

主に使用するのはOpenCV、Flask、uWSGIとなる。

USBカメラ

最近発売されて価格と性能が釣り合っているロジクールC505を使用。赤ちゃんモニター用途だとより広角が欲しくなるかもだが、トライアルであれば十分な仕様。

ロジクール ウェブカメラ C505 HD 720P 自動光補正 ロングレンジマイク 2mの長いUSB接続ケーブル プラグアンドプレイ WEBカメラ ZoomやSkype等主要なビデオ通話アプリに対応 国内正規品 2年間メーカー保証

その他部品

microSDカードと電源ケーブル。欲を言えばケースも欲しかったが、2020年12月時点2GBモデルに対応する適当なケースが無く裸で使用している。

ソースコード

構成としてはFlask Webアプリ内でUSBカメラのキャプチャ画像を60fpsで出力する構成となる。

ファイル・フォルダ構成

実際には下記以外に開発環境であるVS code用の設定ファイル、Web公開の為のBasic認証用のNginxコンテナ周りの設定ファイルやDockerfile、docker-compose.ymlファイル等があるが、表題とズレる為割愛する。

app.py – Flaskアプリ本体

Interface 2021年1月号にbottleフレームワーク(FW)版の記載があるが、私が得意なFWはDjangoかFlaskの為、メインの処理部分を参考にしつつFlask-nizeしたもの。

ページ構成としてはルートディレクトリ’/’にアクセス時に呼び出されるindex.htmlテンプレート内のimgソースとしてvideo_recvメソッドが呼び出される。当該ページ(画像)はサーバのプッシュ通信で描画内容を更新させる為mimetype=’multipart/x-mixed-replace;boundary=frame’指定とし、__main()処理内のyield句で生成されるjpg画像が60fpsで切り替わる流れ。

index.html – Flask アプリのテンプレート

uwsgi.ini – Flask用APサーバー

開発環境でのテスト実行であればif name == ‘main‘:句内を直接実行で構わないが、本番運用時は以下のWARNINGの通り推奨されない。

Development Server — Flask Documentation (2.0.x)

uwsgi.ini記述は以下の通り。

実行方法

コマンド末尾に&を付与することでバックグラウンドでの実行が可能。尚、実行時のリソース使用状況は以下の通り。これまで動画像処理の経験があまりなく、必要リソースの肌感覚が掴めなかった為参考となった。配信のマルチスレッド化とアクセス数の増加時にどのように推移するかは気になる点である。

作成動機・背景

これまでシングルボードコンピュータを扱ったことがなく、書籍やWeb上の活用事例を見ながら漠然とした興味に留まっていたがJetson nano 2GBのお手頃価格が背中を押した感じ。

我が家はFamily budgetのみの為、妻とJetson nano 2GBの活用方法を相談している中で、表題のアプリはコロナ禍で英露から来日出来ない妻の両親が「何時でもお孫さんと一緒だよ」と感じられるツールにもなるとのことで、了解してもらった。

ただ、実際に設置してみると現時点は我々夫婦が専らのユーザーとなり生後4ヶ月の息子の寝返りチャレンジをチラ見する事となった。。(今の所寝返るが腕抜きが出来ず最後に泣いて両親駆けつけレスキュー)