Skip to main content

pycenc

Pure-Python CENC (Common Encryption) decryptor for fragmented MP4.

pycenc decrypts cenc-encrypted DASH/fragmented MP4 files (the scheme used by Widevine, PlayReady, and ClearKey) using a content key you already have. It is a pure-Python alternative to Bento4's mp4decrypt — no compiled dependencies, just the cryptography library.

What this is: an implementation of ISO/IEC 23001-7 (CENC) — a published standard for common encryption of fragmented MP4. It performs standard AES-128-CTR decryption given a content key.

What this is not: it does not obtain keys. There is no CDM, no key exchange, no license server, no network access. You supply the key; the library does the crypto. (Obtaining keys from a DRM system is a separate concern this library does not address.)

Install

pip install pycenc
# or, from source:
uv tool install .   # or: pip install .

CLI

# file -> file (mp4decrypt-style)
pycenc --key KID:KEY input.m4s output.mp4

# streaming: stdin -> stdout (for live pipelines)
producer | pycenc --stream --key KID:KEY | consumer
# equivalent:
pycenc --key KID:KEY - -

Because decryption is a streaming transform with bounded memory, pycenc fits directly into a pipeline: yt-dlp | pycenc --stream | ffmpeg | vlc. The output begins before the input is fully downloaded.

Library

from pycenc import decrypt_bytes, decrypt_file, decrypt_stream

# in-memory (whole file)
with open("encrypted.m4s", "rb") as f:
    data = f.read()
clear = decrypt_bytes(key_bytes, data)          # -> bytes

# file-based
with open("encrypted.m4s", "rb") as fi, open("decrypted.mp4", "wb") as fo:
    decrypt_file(key_bytes, fi, fo)

# streaming (bounded memory; stdin/stdout, pipes, live pipelines)
decrypt_stream(key_bytes, input_stream, output_stream)

key_bytes is a 16-byte AES-128 content key.

How it works

  1. Walks the ISO BMFF box tree (moov/trak/moof/traf/mdat) without external parsers.
  2. For each fragment, reads the senc box (per-sample IVs + subsample split) and the trun box (sample sizes), then decrypts each sample's encrypted bytes with AES-128-CTR.
  3. Auto-detects the IV size (8 or 16 bytes) and whether subsample encryption is used — some files in the wild carry non-compliant senc flags or tenc reporting per_sample_iv_size=0, so detection validates each interpretation against the box length rather than trusting the flags.
  4. Produces a clean, muxable MP4: strips the CENC boxes (sinf/senc/saiz/saio/pssh), restores sample-entry types (encv→avc1, enca→mp4a), recomputes box sizes, and fixes trun.data_offset. The output opens directly in ffmpeg and standard players.

Supported

Scheme Status
cenc (AES-CTR, full-sample & subsample) ✅
cbcs (pattern, AES-CBC) planned
cens (partial, AES-CTR) planned
Feature Status
Single content key per file ✅
Multi-key (per-track KID matching) planned

Limitations

  • Single content key per file (the common case). Multi-key support is planned.
  • cenc scheme only for now; cbcs/cens are on the roadmap.
  • decrypt_bytes loads the whole file into memory; use decrypt_stream (or decrypt_file, which streams internally) for pipes and large files.

License

MIT — see LICENSE.

Release files for pycenc 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pycenc 0.2.0
File Size Uploaded
pycenc-0.2.0.tar.gz 10.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pycenc 0.2.0
File Interpreter ABI Platform
pycenc-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 24.1 kB

Release files / pycenc-0.2.0.tar.gz

Download URL pycenc-0.2.0.tar.gz
Size 10.8 kB
Tags Source
SHA-256 checksum
How to use checksums
4c8a4212a36a12663a34595f2b3b7f2cdac7e9ba472b885d9e136c2ea90605fa
BLAKE2b-256 checksum
How to use checksums
ea85c8a332441c6b641a7a0e31dfa808e967c74af85ee0b5a5a22b6fb6926de9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.0 {"installer":{"name":"uv","version":"0.12.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"22.04","id":"jammy","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / pycenc-0.2.0-py3-none-any.whl

Download URL pycenc-0.2.0-py3-none-any.whl
Size 13.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
22d6ca9cf9d0269188f428dfd093bc90e2b3f628e1bd35a021734635913b7d50
BLAKE2b-256 checksum
How to use checksums
b22d9f4e7520443b3c079d2b2da9a5b27917aa0d1fe170422130a1f85f513467
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.0 {"installer":{"name":"uv","version":"0.12.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"22.04","id":"jammy","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page