This release is a pre-release and may not be stable for production use.
cymedia
Low-latency, group-aligned media processing graphs on FFmpeg's libraries, for Python.
A graph decodes a source once and feeds any number of branches. Each branch is a libavfilter chain ending in an encoder, and its output goes to a sink. Source group numbers, object numbers and timestamps pass through unchanged, and every branch starts a keyframe at each source group start, so equally numbered groups line up across all outputs. The first graph is an ABR ladder.
Status: alpha. The NVIDIA path (NVDEC, scale_cuda, NVENC) and a software path (libopenh264,
else libx264) work, on Linux and macOS with Python 3.12 and 3.13. The API can change before 1.0.
Install
cymedia builds against the system's FFmpeg, 6.1 or later. It needs FFmpeg's development files,
pkg-config and a C compiler:
sudo apt-get install pkg-config libavcodec-dev libavfilter-dev libavutil-dev # Ubuntu 24.04
brew install ffmpeg pkg-config # macOS
pip install cymedia
Prebuilt wheels with an LGPL FFmpeg are planned.
Example
from cymedia import Rung, ladder
rungs = [Rung(1280, 720, 3_750_000), Rung(640, 360, 900_000)]
with ladder(rungs, profile="nvenc", fps=(60, 1)) as g:
g.push(frame, group, obj, pts_us, key) # one H.264 access unit
for out in g.read(timeout=0.1):
... # out.branch, out.group, out.object, out.pts_us, out.key, out.group_start, out.data
- Input is one H.264 access unit per
push(): Annex B, or 4-byte length prefixes with the avcC passed asextradata=.keymarks a group's first frame.push()returns False when the frame was dropped. - Output is Annex B, one
Outputper encoded frame, carrying its source frame's group, object and timestamp.g.fileno()is readable while outputs are queued, for an event loop:loop.add_reader(g.fileno(), lambda: handle(g.read(0))). flush(timeout)ends input and waits for every branch's last frame;stats()anddelays(branch)report counters and recent push-to-output delays.
Profiles
| Profile | Decode | Scale | Encode |
|---|---|---|---|
nvenc |
NVDEC | scale_cuda |
h264_nvenc: p1, ultra low latency, CBR, no B-frames; filler NAL units stripped |
cpu |
software | scale |
libopenh264, else libx264 (veryfast, zerolatency) |
Any other graph is a list of branches:
from cymedia import Branch, Graph
g = Graph([Branch("scale=640:360,format=yuv420p", "libx264", {"preset": "veryfast"})],
decoder="h264", fps=(30, 1))
How it runs
- One decode thread decodes each source frame once, then runs every branch's filter chain.
- Each branch encodes on its own thread. Python's GIL is released throughout.
- In realtime mode (the default) a full queue drops instead of blocking. Input resumes at the next
group start; a branch that falls behind abandons the rest of that group, so a group is cut
short and never has a hole in it. While a branch's encoder first opens, frames wait rather
than drop. With
realtime=False, queues block instead. - Outputs go to a sink with a C ABI (
cymedia_sink.h). The default sink queues them forGraph.read(); a native consumer passes its own sink as acymedia.sinkcapsule and keeps frames out of Python entirely.
Measured delay
An RTX 4070, a 2160p60 H.264 source to six NVENC rungs (1440p to 180p), from push() to the
encoded output, the 4K decode included (about 4.4 ms of it):
| Run | GPU power state | p50 | p99 |
|---|---|---|---|
| 60 fps | P2, then P3 | 8.5–9.3 ms | 14.6–15.3 ms |
| 60 fps, clocks held up | P2 | 7.4–8.0 ms | 15.5–17.1 ms |
| 30 fps | P5 | 14.7–16.1 ms | 29.7–30.7 ms |
| 30 fps, clocks held up | P2/P3 | 8.5–9.0 ms | 16.0–16.9 ms |
Under a light load a GeForce card drops to a low power state and the delay doubles; no frames are
held. bench/ladder_delay.py measures it on your hardware.
Used by
aiomoqt's abr_ingest sits in front of a MoQ relay and
publishes a broadcast plus a cymedia ladder under one catalog.
Develop
python -m venv .venv && .venv/bin/pip install "Cython>=3.0.10" "setuptools>=77" pytest
.venv/bin/pip install --no-build-isolation -e .
.venv/bin/python -m pytest -q
GPU tests skip unless CUDA, h264_nvenc and scale_cuda are available. The delay bench:
.venv/bin/python bench/ladder_delay.py clip.mkv --profile nvenc --seconds 90
Contributor rules are in AGENTS.md.
License
MIT. cymedia links FFmpeg dynamically. A build for distribution must link an LGPL-only FFmpeg
(no --enable-gpl, no --enable-nonfree; scale_cuda built with --enable-cuda-llvm) and
publish that FFmpeg's source and configure line. Distribution packages often ship GPL builds,
which are fine for development but not for redistributed wheels. cymedia.ffmpeg_info() reports
the license of the FFmpeg in use.
Metadata
Release files for cymedia 0.1.0a1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| cymedia-0.1.0a1.tar.gz | 25.4 kB | With provenance | Details for cymedia-0.1.0a1.tar.gz |
Release files / cymedia-0.1.0a1.tar.gz
| Download URL | cymedia-0.1.0a1.tar.gz |
|---|---|
| Size | 25.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a9fe9207c0774a96ba285f601408edf179d00b0606903245a4b0c9962a3dd89b
|
|
BLAKE2b-256 checksum How to use checksums |
033404e039f92b6ca1cb56d9d4b053a45065797de3cb6d7b3e58bcb48443f17e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.12.8
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 8, 2026.
Transparency logSecurity for cymedia 0.1.0a1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
1 file in this release has been uploaded with provenance metadata.
Attestation for cymedia-0.1.0a1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 8, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.