USB カメラの映像を取得する uvc-py を公開した
Python でカメラから映像を取得するのは OpenCV が一般的ですが、もう少し低機能のライブラリが欲しくなったので USB カメラからの映像に特化した uvc-py というライブラリを公開しました。
UVC
UVC (USB Video Class) といいつつ、実際は UVC を OS がうまいことやってくれているので、クロスプラットフォーム映像取得ライブライブラリみたいなものです。
MJPEG に対応したかったのですが、依存ライブラリを増やしたくなかったのと、多くのカメラは NV12 や YUY2 に対応しているので、まぁ最低限はこれでいいかという結論になりました。
特に macOS の場合はカメラ映像を取得する場合は MJPEG では取得できません。MJPEG をデコードして NV12 か YUY2 にして映像を渡してきます。
結果的に NV12 か YUY2 を numpy.ndarray で返してくれるというシンプルなライブラリに落ち着きました。
Capsules
これは今まで知らなかったのですが、Python には Capsules というライブラリがデフォルトで搭載されています。これはライブラリ間でポインタを渡せるようになるという謎の仕組みです。
つまりコピーが発生しません。これにより uvc-py と以前作った生データ再生ライブラリ raw-player で映像フレームのポインタ (CVPixelBuffer) が渡せるようになりました。
まさか Python でそんなことができるとは思っていなかったのでびっくりです。
Python シリーズ
ここ数ヶ月は Python ライブラリをコツコツ作ってきました。これは WebRTC や MOQT などのリアルタイムな音声や映像、データを扱う際に Python から気軽に利用できるようにしたいと言うのが目的です。また Pyhton 3.13 から入り Python 3.14 で正式版となった Free Threading (no-GIL) へ対応しているライブラリが少ないため、であれば必要なのは全部作ってしまおうということで作りました。
全て nanobind と scikit-build-core を利用した C/C++ で作っています。
blend2d-py
もともと libdatachannel-py や自社製品の Python SDK を利用する際にダミー映像を作るのが OpenCV などだと遅くて困って居たのがきっかけで開発しました。特に CI (GitHub Acitons) での利用を想定し GPU に依存せず CPU パワーで高速に 2D アニメーションが生成できるライブラリとして開発しました。
実際製品の E2E テストで大活躍しています。映像の内容により圧縮率が変わったりするのでダミー映像を自由に作れるのは本当に大事です。
libwebm-py
WebM ファイルを操作するのって思った以上にライブラリが無いので、公式の libwebm をラップしたライブラリです。ビルドも簡単ですし、シンプルな構成ということもあり、nanobind や CMakeList.txt のテストに使ったりしています。
libdatachannel-py
もともとは独自ビルドで実現していた libdatachannel の Python バインディングですが、勉強がてら nanobind と scikit-build-core に切り替えました。libwebrtc では扱いにくいような少し変わったことをやるときに重宝しています。
mp4-py
mp4-rust という Rust で書いてあるライブラリの C API を nanobind 経由で利用できるようにしています。Python で気軽に MP4 を保存するというライブラリが欲しくて実現しました。もともとは ctypes で書いていたのを nanobind にして Windows 対応をしたりしています。
ちなみに pytest と Hypothesis という Property-Based Testing ライブラリを利用したりしています。
webcodecs-py
Python で音声や映像圧縮コーデックを WebCodecs API ほぼ準拠で利用でいるようにするライブラリです。WebCodecs API だけ覚えておけば良いので扱いやすいようにしています。
raw-player
Python で音声や映像を生データ、つまり PCM だったり NV12 だったりを再生するプレイヤーがなかったので、 SDL (Simple DirectMedia Layer) を利用しているので GPU もしっかり利用できるようにしているので 1080p 120fps でもサクサク再生できるライブラリです。
portaudio-py
もともと sounddevice という PortAudio のライブラリを使う予定だったのですが、よく考えたら Free Threading に対応していないことを気づき、最低限の機能を自前で実装したライブラリです。
Free Threading 対応
世の中のライブラリって no-GIL である Free Threading 対応していないので、Free Threading 対応ライブラリを作っても恩恵を受けにくいという問題があり、自分が使いたいライブラリを一通り Free Threading で作るということをしていました。
また、全てのデータを numpy.ndarray ベースにしたりと、完全にやりたい放題で実装しました。
雑感
Python + C/C++ は自分が Python を覚え始めた時からやりたかったのですが、当時は nanobind とかビルド周りの知識もなかったので、CMake とかも全然知りませんでした。
時が経ち、なぜか Python がメジャー言語になり nanobind やら scikit-build-core やら、PyPI 経由で cmake が入ったりとか、本当に便利な時代になりました。
今後は Python + nanobind + Free Threading である程度性能がでるライブラリを作っていければと思います。