moq-transcode 0.0.10

Just-in-time live transcoding for hang broadcasts over Media over QUIC
Documentation

moq-transcode

Just-in-time live transcoding for hang broadcasts.

Consume a source broadcast, publish a derivative broadcast next to it: the derivative catalog advertises lower renditions (rungs) of the source video plus relative references back to the source renditions, so a player picks from the combined ladder and the transcoder never proxies what it doesn't re-encode.

Nothing is encoded until someone asks, Cloudflare-style just-in-time per rung:

  • Subscribe to a rung and the transcoder decodes the source live, resizing and re-encoding group for group until the last subscriber leaves. Every active rung of a source shares one subscription and one decoder, so decode cost scales with sources, not ladder depth.
  • Fetch a specific group and the transcoder fetches that same group from the source and transcodes just that group. Output groups mirror source group sequence numbers 1:1, so group N of every rung is the same content as source group N and rendition switches land cleanly.

The codec work is moq-video: hardware where available (NVDEC + NVENC on Linux, VideoToolbox on macOS, Media Foundation on Windows), openh264 as the H.264 software fallback. H.264, H.265, and 8-bit 4:2:0 AV1 source renditions are eligible when a matching decoder is available. On an NVIDIA GPU the pipeline is fully GPU-resident: NVDEC decodes and scales in hardware and NVENC encodes the CUDA frame in place, with no CPU copies. macOS also resizes on the GPU. Windows uses the Direct3D11 video processor by default; set Config::resize.acceleration to resize::Acceleration::Cpu to force a download and CPU resize.

Library

One entry point: run(source, output, config). The caller owns session setup and where the derivative is announced; the transcoder only fills the output broadcast.

let mut config = moq_transcode::Config::default();
// The derivative is announced at `<source>/transcode.hang`, so the source
// renditions are referenced one level up.
config.source = Some(moq_net::PathRelativeOwned::from("..".to_string()));

let output = origin.create_broadcast(
    format!("{path}/transcode.hang"),
    moq_net::broadcast::Route::new().with_announce(true),
)?;

moq_transcode::run(source, output, config).await?;

Only renditions strictly below the source survive the ladder: a 480p source is never transcoded up to 720p, and a same-height rung is only offered when it undercuts a known source bitrate.

Example

Publish something first (e.g. moq publish camera from moq-cli), then:

cargo run -p moq-transcode --example transcode -- \
    --url http://localhost:4443/anon --source my-broadcast

The derivative appears at my-broadcast/transcode.hang.