Python で WebCodecs API を利用できる webcodecs-py を公開しました
ブラウザでは音声や映像のコーデックを利用できる WebCodecs API というのがあります。ただ、当たり前ですが、ブラウザでしか利用できません。
これを Python で使いたい!って思っていたので、 Python で利用できるライブラリを公開しました。
方針
- scikit-build-core と nanobind を利用して完全に時前ビルドにする
- CMake を利用してマルチプラットフォームにする
uv add webcodecs-pyで利用できるようにする- WebCodecs API にできるだけ準拠する
- ハードウェアアクセラレーターに対応する
numpy.ndarray前提にする
結果
ほぼほぼ WebCodecs API 準拠で使えるようになりました。違いはコールバック指定を引数にしたくらいです。
import numpy as np
from webcodecs import (
LatencyMode,
VideoEncoder,
VideoEncoderConfig,
VideoFrame,
VideoFrameBufferInit,
VideoPixelFormat,
)
width, height = 320, 240
# エンコーダを作成
encoded_chunks = []
def on_output(chunk):
encoded_chunks.append(chunk)
def on_error(error):
raise RuntimeError(f"エンコーダエラー: {error}")
encoder = VideoEncoder(on_output, on_error)
encoder_config: VideoEncoderConfig = {
"codec": "av01.0.04M.08",
"width": width,
"height": height,
"bitrate": 500_000,
"framerate": 30.0,
"latency_mode": LatencyMode.REALTIME,
}
encoder.configure(encoder_config)
# I420 フォーマットのテストフレームを作成
data_size = width * height * 3 // 2
frame_data = np.zeros(data_size, dtype=np.uint8)
init: VideoFrameBufferInit = {
"format": VideoPixelFormat.I420,
"coded_width": width,
"coded_height": height,
"timestamp": 0,
}
frame = VideoFrame(frame_data, init)
# エンコード
encoder.encode(frame, {"keyFrame": True})
encoder.flush()
print(f"エンコード完了: {len(encoded_chunks)} チャンク, {encoded_chunks[0].byte_length} bytes")
frame.close()
encoder.close()AV1 をエンコードする仕組み
対応
- 多くの WebCodec API に対応
- 対応内容はこちら
- Opus / FLAC / AAC のエンコードとデコード
- AAC は Apple Audio Toolbox で実現
- AV1 / H.264 / H.265 のエンコードとデコード
- H.264 / H.265 は Apple Video Toolbox で実現
- AV1 はエンコードは aom でデコードは dav1d
- libyuv を利用した
VideoPixelFormat変換対応
何ができるの?
opencv-python 経由のカメラ映像を webcodecs-py で AV1 に変換して mp4-py を利用して MP4 に出力できます。
sounddevice 経由のマイク音声と opencv-python 経由のカメラ映像を webcodecs で Opus / AV1 に変換して libdatachannel-py 経由で WebRTC で配信したりすることができます。
mp4 ファイルの中身をデコードして変換する仕組みなども実装できます。
なんで Python ?
自分が慣れているのが第一ですが、LLM との相性がいいからです。2025 年時点では LLM やるなら Python ほぼ一択です。LLM で音声や映像をとり扱う場合、気軽に利用できるエンコーダーやデコーダーが重要になると思っています。
また C/C++ ベースの Python ライブラリのノウハウは今後も生きると思っています。
MOQT も視野
Media over QUIC Transport (MOQT) では音声や映像を送受信するトンネル部分しか提供しないため、コーデック部分は自力になります。ブラウザでは WebCodecs API を使えばいいですが、別に MOQT はブラウザのためだけの仕組みではありません。
現在時雨堂では Google が公開している QUIC 実装 quiche の時前ビルドを提供しており、今後はこの quiche ベースの MOQT を Python 経由で利用できる moqt-py を開発していく予定です。
この時、 webcodecs-py があると、コーデック関連を webcodecs-py に丸投げできるようになります。
公開
- shiguredo/webcodecs-py https://github.com/shiguredo/webcodecs-py
- webcodecs-py · PyPI https://pypi.org/project/webcodecs-py/
blend2d-py + webcodecs-py + libdatachannel-py で WebRTC SFU Sora 経由で配信してブラウザで視聴するデモ映像
想像以上に便利
blend2d-py で 2D アニメーションを作成し、それを webcodecs-py で H.265 (Apple Video Toolbox) で変換し、libdatachannel-py で WebRTC (WHIP) にして、WebRTC SFU Sora へ配信して、ブラウザ (Chrome) で視聴してみるデモ映像です。
雑感
開発期間は 3 ヶ月くらいです。ちまちまと暇を見つけて開発をしていました。3-4 回作り直していますが、かなり良いモノができたと思います。
今後は C++ 実装を整理して性能を出せるようにしたり、Python 3.13 から入った free threading に対応したり、コーデックを増やしたり、WebCodecs API に追従したりしてきたいと思っています。
とにかく使いやすく、性能がでて、落ちない Python ライブラリを目指します。