This document defines the portable configuration boundary for Camera Feed Lab. The runtime implements it with the focused Go control process approved by EXC-006.
| Purpose | Container path | Mutability |
|---|---|---|
| Stream manifest | /config/camera-feed-lab.json |
Read-only |
| Media root | /media |
Read-only |
| Generated runtime configuration | /tmp |
Ephemeral |
Host paths are selected only by Compose overrides. A manifest contains paths
relative to /media; it cannot contain host paths, URLs, absolute paths, or
parent-directory traversal.
The canonical schema is
config/camera-feed-lab.schema.json. A representative
manifest is
config/camera-feed-lab.example.json.
The runnable contract-only synthetic example is
config/camera-feed-lab.synthetic-example.json.
schema_versionis required and currently must be2.deployment.environmentis required and must bedefault,development, orproduction. Health reports this authoritative value for deploy safety.- Unknown fields are rejected at every object boundary.
- JSON field names are case-sensitive and must match the canonical schema.
- Every stream has a stable identifier, one MediaMTX producer path, and up to 128 optional reader aliases. Paths omit the leading slash.
- Stream identifiers, producer paths, and alias paths must be unique across the complete manifest.
- A manifest contains at most 64 streams. The default 4096-PID container budget retains headroom above the bounded-thread compatibility profile. A measured 64-stream profile (720x576 H264 at 12 fps and 1200 kbps per stream) peaked at 2169 tasks (53% of the limit) and 2.28 GiB under an 8 GiB test fence. Private deployments must independently measure their selected source/output mix before sustained use.
alwaysstreams publish at service startup.on_demandstreams publish only while MediaMTX has a reader.- Reader aliases are direct on-demand publisher paths. Each alias starts a separate shell-free FFmpeg packet-copy publisher from the same rooted, read-only source definition; it does not add another encoder. This avoids an in-process RTSP proxy hop, keeps every consumer on its configured path, and prevents an internal producer path from leaking through a redirect response.
- File sources are paced in real time. They may loop, but they cannot select a
network input. The optional
replay.mode: wall_clock_dayseeks a looped, full-day recording to the current seconds-of-day at publisher start. Its requiredutc_offset_secondsvalue is deployment-private; publisher restarts recompute the seek. Omittingreplaypreserves continuous playback from the file start, which is suitable for deliberately time-inaccurate stress loops. Only direct MPEG-PS, MPEG-TS, MP4/MOV, and MXF containers are accepted; playlist and manifest formats are rejected. The publisher forces the corresponding demuxer and disables external MOV data references. - Synthetic sources generate deterministic video and may add a deterministic tone.
- File video may be copied or transcoded to H.264/HEVC. Synthetic video must be transcoded. Audio may be dropped, copied, or transcoded to AAC.
- Publisher transport is a fixed implementation invariant: every FFmpeg publisher writes to MediaMTX over RTSP/TCP. It is not a manifest option.
- Reader transport in the hardened bridged container contract is RTSP/TCP. UDP and multicast require a host-network deployment and are not advertised by the portable Compose profile.
- MediaMTX accepts publishers and API requests only from loopback hooks, rejects publisher replacement, and keeps anonymous reader access.
- FFmpeg invocations are constructed as argument arrays. Manifest text is never evaluated by a shell.
JSON Schema establishes the document shape. The implementation must also
perform semantic validation that JSON Schema cannot express portably: duplicate
ID/path detection, resolved-path confinement under /media, required-file
existence/readability, source/output compatibility, and safe numeric
relationships, and producer/alias path collisions. Any failure is fatal and
identifies the stream and field.
The public default
config/camera-feed-lab.compatibility.json
preserves the consumer-visible Stage 1 surface with synthetic, site-neutral
sources. It also exposes the generic read-only alias examples/channel_01 for
real-container verification of the proxy contract:
| Paths | Count | Activation | Output profile |
|---|---|---|---|
unicast/c1/s1/live through unicast/c16/s1/live |
16 | Always | H.264, 720x576, 12 fps |
stress/4k264/c1 through stress/4k264/c8 |
8 | On demand | H.264, 3840x2160, 30 fps |
stress/4k265/c1 through stress/4k265/c8 |
8 | On demand | HEVC, 3840x2160, 30 fps |
stress/1080p60/c1 through stress/1080p60/c8 |
8 | On demand | H.264, 1920x1080, 60 fps |
test/tone |
1 | On demand | H.264, 1280x720, 25 fps, AAC tone |
This table is a compatibility contract, not a host deployment configuration. It contains no credentials, media, private paths, machine addresses, or site mapping.