The authoritative field reference for a phrame-webrtc-session instance. See
phrame-webrtc-session for what the service does and
why it is shaped the way it is.
The four required sections are stream (which Phrame bus stream to serve),
whep (where to listen), auth (the public key and audience used to verify a
viewer’s token), and video (how to encode). Everything else has a default.
| Field | Type | Required | Default | Description |
|---|
version | string | no | — | |
log_level | string | no | — | |
stream | object | yes | — | |
whep | object | yes | — | |
auth | object | yes | — | |
ice | object | no | — | |
video | object | yes | — | |
audio | object | no | — | OPTIONAL. Omit entirely for a video-only source: no program-audio egress thread is spawned. Present => audio egress reads vdi://<stream.id>:<audio_suffix>. Spawning it for a stream nothing writes costs 100 x 500ms of failed VDI opens per session (4 log lines each), which is why this is opt-in. |
session | object | no | — | |
enable_test_controls | boolean | no | false | Expose GET/POST /control/bitrate, which can pin the encoder bitrate and suppress BWE. For measurement runs only; default false. Still JWT-gated when enabled -- this controls exposure, not authorisation. |
topology | object | no | — | Maps a composited frame's input id to the TAMS flow behind it, so the per-frame identity published on the nle-frame-id data channel can name a flow rather than a bare index. Key is the PRODUCING STAGE'S INPUT-ARRAY INDEX (phrame_frame_identity.hpp: 'id is the index in inputs, INCLUDING skipped null slots'), NOT the compositor config's stream-id param -- the two coincide in comp-mv-2048.json and must not be conflated. Omit for a single-input stream: the identity list is still published with ids and media positions, only 'flow' is left empty. |
Definitions
stream
| Field | Type | Required | Default | Description |
|---|
id | string | yes | — | |
video_suffix | string | no | — | |
audio_suffix | string | no | — | |
talkback_suffix | string | no | — | |
domain | string | no | — | |
whep
| Field | Type | Required | Default | Description |
|---|
bind_addr | string | no | — | |
port | integer | yes | — | |
auth
| Field | Type | Required | Default | Description |
|---|
public_key_path | string | yes | — | |
audience | string | yes | — | |
algorithm | enum: ES256 · RS256 | no | — | |
ice
| Field | Type | Required | Default | Description |
|---|
host_candidate_ip | string | no | — | |
stun_url | string | no | — | |
udp_port_min | integer | no | — | |
udp_port_max | integer | no | — | |
bind_addr | string | no | — | Local address to bind the ICE UDP socket to (default: host_candidate_ip). Use 0.0.0.0 behind NAT/Docker. |
ice_lite | boolean | no | — | Run ICE in lite mode (respond only, never initiate checks). Needed behind symmetric NAT. |
video
| Field | Type | Required | Default | Description |
|---|
bitrate | integer | yes | — | |
preset | string | no | — | |
gop | integer | no | — | |
fps | integer | yes | — | |
h264_level_idc | integer | no | — | H.264 level_idc to advertise in profile-level-id, as the level x10 (31 = Level 3.1, 42 = Level 4.2). Must not be below what the output geometry requires or hardware decoders reject the stream and the client silently falls back to software decode. Default 42. |
vbv_buffer_frames | number | no | — | VBV buffer size in FRAMES of budget. Absent => ABR (average bitrate only, peaks unconstrained) which is the historical behaviour. Set 1.0-2.0 to cap the instantaneous rate: bitrate alone constrains only the average, so a keyframe takes 5-15x the per-frame budget and the paced sender then meters it out while later frames queue. |
constant_bitrate | boolean | no | — | With vbv_buffer_frames set, also hold the average at the target (nal-hrd=cbr) rather than only capping the peak. Both cap the peak identically; true always spends the full bitrate, false lets the average float down on easy content. Default false. |
intra_refresh | boolean | no | false | Replace the periodic IDR with a rolling intra refresh. Removes the visible quality pulse a tightly-constrained keyframe causes under a small VBV. Trade-off: no IDR to resynchronise on after loss. |
audio
OPTIONAL. Omit entirely for a video-only source: no program-audio egress thread is spawned. Present => audio egress reads vdi://<stream.id>:<audio_suffix>. Spawning it for a stream nothing writes costs 100 x 500ms of failed VDI opens per session (4 log lines each), which is why this is opt-in.
| Field | Type | Required | Default | Description |
|---|
bitrate | integer | yes | — | |
session
| Field | Type | Required | Default | Description |
|---|
on_second_connection | enum: reject-except-same-sub · always-reject · always-preempt | no | — | |