We will not respond to PRs or issues that have not been discussed on Discord. Also, Discord is only available in Japanese.
Please read https://github.com/shiguredo/oss/blob/master/README.en.md before use.
利用前に https://github.com/shiguredo/oss をお読みください。
webcodecs-py は WebCodecs API API を Python で利用できるようにするライブラリです。
- WebCodecs API の Python バインディング
- Opus、FLAC、AAC、AV1、H.264、H.265 コーデックをサポート
- AAC は macOS の AudioToolbox を利用
- H.264 と H.265 は macOS の VideoToolbox を利用
- クロスプラットフォーム対応
- macOS
- Ubuntu
- Windows
開発状況は webcodecs-py 対応状況 をご確認ください。
- ImageDecoder: 画像デコード機能は実装対象外
- Pillow や OpenCV を使用してください
- CanvasImageSource: VideoFrame の CanvasImageSource コンストラクタはブラウザ固有機能のため実装対象外
import numpy as np
from webcodecs import (
AudioData,
AudioDataInit,
AudioEncoder,
AudioEncoderConfig,
AudioSampleFormat,
)
sample_rate = 48000
frame_size = 960 # 20ms @ 48kHz
# エンコーダを作成
encoded_chunks = []
def on_output(chunk):
encoded_chunks.append(chunk)
def on_error(error):
raise RuntimeError(f"エンコーダエラー: {error}")
encoder = AudioEncoder(on_output, on_error)
encoder_config: AudioEncoderConfig = {
"codec": "opus",
"sample_rate": sample_rate,
"number_of_channels": 1,
"bitrate": 64000,
}
encoder.configure(encoder_config)
# サイン波を生成してエンコード
t = np.linspace(0, frame_size / sample_rate, frame_size, dtype=np.float32)
audio_samples = (np.sin(2 * np.pi * 440 * t) * 0.5).reshape(frame_size, 1)
init: AudioDataInit = {
"format": AudioSampleFormat.F32,
"sample_rate": sample_rate,
"number_of_frames": frame_size,
"number_of_channels": 1,
"timestamp": 0,
"data": audio_samples,
}
# with 文で AudioData を使用(自動的に close される)
with AudioData(init) as audio_data:
encoder.encode(audio_data)
encoder.flush()
print(f"エンコード完了: {len(encoded_chunks)} チャンク")
encoder.close()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,
}
# with 文で VideoFrame を使用(自動的に close される)
with VideoFrame(frame_data, init) as frame:
encoder.encode(frame, {"keyFrame": True})
encoder.flush()
print(f"エンコード完了: {len(encoded_chunks)} チャンク, {encoded_chunks[0].byte_length} bytes")
encoder.close()uv add webcodecs-py
- Opus
- FLAC
- AAC
- AV1
- H.264 (AVC)
- H.265 (HEVC)
- 3.14
- 3.13
- 3.12
- macOS 26 arm64
- macOS 15 arm64
- Ubuntu 24.04 LTS x86_64
- Ubuntu 24.04 LTS arm64
- Ubuntu 22.04 LTS x86_64
- Ubuntu 22.04 LTS arm64
- Windows 11 x86_64
- Windows Server 2025 x86_64
make developuv sync
make testuv sync --group example
make develop
uv run python examples/blend2d_to_mp4.pyApache License 2.0
Copyright 2025-2025, Shiguredo Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.