# DRM-Decryption Capture Widevine live sessions from Android streaming apps and restream them. Everything is one Go binary — `drm` — with every app module compiled in. Each streaming app (RTE, TG4, …) is a Go package under `apps/modules/`; its secrets and IDs live in a local, gitignored values file that you fill in yourself. - **[docs/](docs/)** — architecture, module authoring, per-provider setup - **[docs/quickstart.md](docs/quickstart.md)** — the longer version of what follows --- ## Quick start ### 1. Prerequisites | Need | Why | |---|---| | **Go 1.25+** | builds everything | | **Python 3.10+** | `apps/wvkey/wvkey.py` talks to the Widevine CDM | | **adb** (platform-tools) on `PATH` | only for phone capture | | A `.wvd` Widevine device file | only for fetching keys | Phone capture additionally needs a rooted Android device (Magisk) so the MITM CA can be injected into the system trust store. Catalog lookups need no phone. ### 2. Clone and build ```bash git clone https://git.nulldrm.com/nulldrm/Null-DRM-Official.git cd Null-DRM-Official # Linux / macOS go -C apps/cli build -o ../../bin/drm . # Windows go -C apps/cli build -o ../../bin/drm.exe . ``` Check it: ```bash ./bin/drm help ./bin/drm modules # which app modules this build contains ``` `drm modules` works immediately, but channel lists stay empty until you add values — that is the next step. ### 3. Python CDM helper ```bash python -m venv .venv .venv/bin/pip install -r apps/wvkey/requirements.txt # Windows: .venv\Scripts\pip ``` Put your Widevine device file in `data/` (gitignored), e.g. `data/device.wvd`. ### 4. Fill in a module's values Compiled-in module code carries **no** account IDs, policy keys, video IDs, license URLs or key IDs. Those go in a gitignored file per module, which you create: ```text apps/modules/tg4/module.yaml apps/modules/rte/module.yaml ``` Where each value comes from: - **[docs/providers/tg4.md](docs/providers/tg4.md)** — Brightcove account ID, policy key, video IDs - **[docs/providers/rte.md](docs/providers/rte.md)** — license URL, origin hosts, channel KIDs - **[docs/capture.md](docs/capture.md)** — how to discover all of it for a *new* app Any value can be passed per-run instead of stored: ```bash ./bin/drm catalog --app tg4 --channel ioi --tg4.policy-key 'BCpkAD...' TG4_POLICY_KEY='BCpkAD...' ./bin/drm catalog --app tg4 --channel ioi ``` ### 5. Run something ```bash # keys from a public catalog — no phone needed ./bin/drm catalog --app tg4 --channel ioi --keys --wvd data/device.wvd # phone capture: launch the app, drive it to a channel, grab license + keys ./bin/drm proxy build # once: cross-compile the on-device MITM ./bin/drm capture --app rte --channel rteone --auto-play --wvd data/device.wvd # control plane + dashboard on http://127.0.0.1:8083 ./bin/drm serve --bind 127.0.0.1:8083 --data .cache/streamd --token SECRET # always-on refresher: watches streamd, re-captures dead channels STREAMD_TOKEN=SECRET ./bin/drm agent run --config apps/agent/agent.yaml ``` Results land in `outputs///`, with `latest/` kept as a copy. --- ## Subcommands | Command | What it does | |---|---| | `drm modules` | list compiled-in app modules, their channels and config source | | `drm capture` | one-shot phone MITM capture → `outputs///` | | `drm catalog` | resolve a channel from its public catalog, no phone | | `drm serve` | streamd: REST API + dashboard + media supervisor | | `drm agent` | `run` / `status` / `devices` / `enqueue` / `cancel` | | `drm proxy` | `build` / `push` / `install-ca` / `start` / `stop` / `discover` / `pull` | Run any of them with `--help`. ## Layout ```text apps/cli/ the binary -> bin/drm apps/modules/ app modules: Go (tracked) + module.yaml (gitignored) apps/pkg/ shared, provider-neutral libraries apps/capture/ phone capture command apps/agent/ always-on key refresher apps/streamd/ control plane: API, SQLite, dashboard, supervisor apps/proxy/ MITM host CLI + on-device proxy source apps/wvkey/ wvkey.py — CDM only docs/ architecture, authoring, provider setup data/ secrets: .wvd, CA (gitignored) outputs/ capture sessions (gitignored) bin/ built binaries (gitignored) www/ static site ``` ## Tests ```bash go -C apps/pkg test ./... go -C apps/modules test ./... go -C apps/streamd test ./... ``` Tests that hit a live origin are behind a build tag, so they stay out of the normal run: ```bash go -C apps/modules test -tags live ./rte/ -v ``` ## Scope For use only on services you are authorised to access, with content you have the right to decrypt. [docs/architecture.md](docs/architecture.md) describes what the system does and where it stops.