Skip to content

input-processor — Ingest

Every source is different; input-processor makes them all look the same. It takes files, streams, tuners, NDI, and MXL, decodes them into one raw-frame format, and puts them on the live bus — so everything downstream treats every source identically.

input-processor — ingest & normalise files RTSP · RTMPSRT · RTP DVB-T / T2 NDI existing MXL input-processordecode · normalisescale · reframeoverlay · proxy frame busVDI / MXL raw yuv422p16le one raw-frame contract → every source looks identical to everything downstream


The hardest part of live production is that inputs never agree — different codecs, frame rates, resolutions, colour formats, and transports. Traditionally that means a rack of format converters.

input-processor collapses that into software:

  • Bring in anything. Files, RTSP/RTMP/SRT/RTP, HTTP HLS/DASH, V4L2 cameras, DVB-T/T2 tuners, NDI, and existing MXL flows.
  • One contract downstream. Everything is normalised to a consistent raw-frame stream, so mixers and egress never care where a source came from.
  • Do more on the way in. Scale, reframe, convert frame rate, generate low-res proxy previews, produce compressed copies, and burn in timecode/overlays — in one pass.
  • Repeatable. Pipelines are JSON, version-controlled, and reconfigurable live over MQTT.

In one line: any input, normalised once, so the rest of the platform is gloriously simple.


You configure a run one of two ways:

MethodWhen
CLI flagsQuick one-offs: -i <source>, -f <format>, --pix_fmt, --re (realtime), --loop, -n <frames>.
JSON pipeline file (preferred)Repeatable, version-controlled runs; the only form that supports multiple inputs/outputs and parallel pipelines (--config pipeline.json).

A pipeline file has three required parts — inputs, outputs, and pipelines (which bind an input_id to an output_id):

  • Inputs pick a plugin (network for FFmpeg sources, mxl, or ndi), a source URI, and optional video/audio settings (pixel format, rescale, frame-rate conversion), plus pacing (realtime, loop, frame_limit) and dvb tuning.
  • Outputs target vdi, mxl, or null (testing), and choose which streams to publish: video, proxy, *_compressed, audio, etc., with optional compress and overlay burn settings.

The module ships runnable examples for the common paths — file-to-vdi.sh, srt-to-mxl.sh, rtsp-to-mxl.sh, ndi-to-mxl.sh, dvb-multi-service.sh, v4l2-camera.sh, playlist-two-clips.sh — with matching JSON in examples/.

Full field reference: input-processor config — every field, type, default, and description, generated from the JSON Schema.


  • Language: Rust. Default output pixel format yuv422p16le.
  • Plugin backends. Each transport is a native .so loaded via libloading (dlopen) and driven through the common C ABI (plugin_open(config_json)plugin_readplugin_close): libvdi.so, libplugin-mxl.so, libphramendi.so (NDI), the network plugin, and libplugin_null.so. See Frame bus & plugins.
  • Controller vs static mode. In controller mode the service subscribes to an MQTT config topic and runs a reconcile loop — comparing desired vs running pipelines and restarting only those whose spec materially changed — then publishes status on a state topic with a last-will message.
  • Performance. YUV conversion is parallelised with rayon (rayon_threads / RAYON_NUM_THREADS); optional NUMA-aware thread pinning.
  • Overlays. Timecode/text burn-in is rasterised with fontdue; timecode formats include hh:mm:ss:ff and TAI variants.

Key modules: main.rs (CLI + dual-broker MQTT), controller.rs (reconcile loop), pipeline_config.rs (schema + validation), vdi.rs, burn.rs, dvb.rs, numa.rs.


Part of the Phrame documentation system — one Markdown source, four audiences, a code-generated house-style diagram.