#479 (Enhanced RTMP, SCTE 104) and #483 (SRT, RIST) both extend joule-moq-ingest; both ingests are kept whole, on one set of types: - frame.rs: one Codec with both sides' codecs (HEVC, VVC, AAC, FLAC; ALL is nine), #479's WEBRTC constant and Option-returning to_str0m, #483's webrtc() and aac_header; one Header whose audio rate is #479's `rate` (#483 called it `samplerate`; its uses are renamed); unframe keeps #483's whole-ADTS check for AAC; the module text names both ingests' codecs. - package.rs: one packager. HEVC and VVC take an Enhanced RTMP track's hint, and from a transport stream (no hint) the header or a default, as #483 did; AAC's first header is its ADTS header where there is no hint (#483) and the hint's otherwise (#479). - catalog.rs: #479's (name per entry; the rate as above); contrib.rs's catalog entry now names its layer, as #479 made every entry do. - config.rs, gateway.rs (routes, the Gateway's fields and methods, the server's listeners, srt_task and shutdown), rtc.rs, lib.rs, gateway.example.toml, the README and live-ingest's status, header and test account: both sides. - tests/common: watch_kinds -> watch_layers (#479) -> watch_tracks (#483), one subscriber; Watched.layer is the track name where it is a number. tests/ertmp.rs imports common::rtmp::adts by name, since common now has #483's adts too. - joule-code-conformance.yml's paths, the live-conformance README; CHANGELOG, #483's entry on top. cargo check --locked --all-targets of joule-moq-ingest (with rist), joule-contrib (with rist), joule-moq-relay and joule-moq passes. Co-Authored-By: Claude Opus 5.5 <[email protected]>
114 lines
5.5 KiB
TOML
114 lines
5.5 KiB
TOML
# joule-moq-ingest: every field, with its default where it has one.
|
|
# No secret lives here: the relay token and the signing key are files the operator
|
|
# provides, and a room is its signed descriptor, which is public.
|
|
|
|
[http]
|
|
listen = "127.0.0.1:8088" # the WHIP and WHEP resources; put a TLS front before them
|
|
origin = "" # this gateway's origin as grants name it, e.g. "https://ingest.example"
|
|
cors_allow_origin = "*"
|
|
max_body_bytes = 65536
|
|
request_timeout_ms = 10000
|
|
challenge_ttl_s = 300 # how long a proof-of-possession challenge stays good
|
|
max_challenges = 65536 # challenges held at once, issued and consumed each
|
|
|
|
[media]
|
|
bind_ip = "127.0.0.1" # each session's UDP socket, and its host candidate
|
|
ice_lite = true
|
|
connect_timeout_ms = 15000
|
|
idle_timeout_ms = 20000
|
|
|
|
[relay]
|
|
addr = "127.0.0.1:4443" # the relay's native QUIC endpoint (ALPN moqt-22)
|
|
server_name = "localhost"
|
|
cert_path = "relay-cert.pem" # the relay's certificate, trusted as a root
|
|
token_path = "relay-token" # the token value the relay's grant names by SHA-256
|
|
|
|
[signing]
|
|
key_path = "gateway.key" # 32 bytes, the Ed25519 seed; absent: made at start
|
|
signer_id = "" # empty: the key's did:key
|
|
origin_label = "wai-ingest"
|
|
|
|
[[rooms]]
|
|
descriptor_path = "room.wrd1" # the room's signed descriptor (WRD1)
|
|
revoked = [] # grant digests and viewer tags the room's key log revokes
|
|
|
|
[limits]
|
|
max_whip_sessions = 64 # one more: 503 with Retry-After
|
|
max_whep_sessions = 256
|
|
max_tracks_per_session = 2 # media sections in one offer; more: 422
|
|
max_bitrate_kbps = 8000 # per WHIP session, all tracks; stated per track as b=AS
|
|
bitrate_window_ms = 2000
|
|
max_frame_bytes = 4194304
|
|
max_queue_bytes = 33554432 # a session's queue to the relay
|
|
retry_after_s = 5
|
|
|
|
[groups]
|
|
audio_group_ms = 200 # an audio group's duration
|
|
max_video_group_ms = 2000 # a longer video group asks the publisher for a keyframe
|
|
keyframe_request_interval_ms = 1000
|
|
|
|
[timeline]
|
|
max_skew_ms = 250 # |mapped time - arrival| bound; past it, re-anchor
|
|
|
|
[whep]
|
|
trust = [] # first-hop keys whose receipts WHEP accepts; empty: this gateway's
|
|
hold_ms = 5000 # how long a group's objects wait for its receipts
|
|
catalog_wait_ms = 2000
|
|
retry_after_s = 2 # what a 409 asks a player to wait
|
|
|
|
[summary]
|
|
# out_path = "sessions.jsonl" # session records, one JSON line each; absent: kept in memory only
|
|
# link_out_path = "links.hex" # contribution link records (WCL1), one hexadecimal line each
|
|
|
|
[rtmp]
|
|
# Enhanced RTMP ingest (live-ingest §12); off unless a listener is set.
|
|
listen = "127.0.0.1:1935" # RTMP over TCP
|
|
# tls_listen = "127.0.0.1:1936" # RTMPS, with the two files below
|
|
# cert_path = "rtmps-chain.pem"
|
|
# key_path = "rtmps-key.pem" # PKCS #8
|
|
url = "" # what a stream key's response names; empty: rtmp://<listen>/live
|
|
stream_key_ttl_s = 60 # a stream key from POST /rtmp is good this long for its first use
|
|
max_sessions = 64
|
|
max_message_bytes = 8388608 # the largest message the chunk stream takes
|
|
max_bitrate_kbps = 40000 # per publisher, every track, over limits.bitrate_window_ms
|
|
connect_timeout_ms = 15000 # a connection that has not published by then is closed
|
|
idle_timeout_ms = 20000
|
|
chunk_size = 4096 # the chunk size the gateway sends with
|
|
reconnect_url = "" # the tcUrl a reconnect request names; empty: none
|
|
reconnect_grace_ms = 5000 # how long a session stays after a reconnect request
|
|
|
|
[injector]
|
|
# SCTE 104 automation into signed cues (cue-injection); off unless listen is set.
|
|
# listen = "127.0.0.1:5167"
|
|
room = "" # the room id, 64 hexadecimal digits, one of [[rooms]]
|
|
# key_path = "injector.key" # 32 bytes, the injector principal's Ed25519 seed
|
|
# grant_path = "injector.wrg1" # the principal's room grant, permitting cue and meta
|
|
leap_seconds = 18 # GPS - UTC, for a UTC timestamp()
|
|
fps_num = 30000 # the frame rate duration_extension_frames counts in
|
|
fps_den = 1001
|
|
dpi_pid_index = [] # the DPI_PID_index values answered; empty: any
|
|
max_pending = 256 # cues held for splices still to come
|
|
|
|
# Contribution over SRT and RIST (WAI extensions/live-contribution.md). A publisher POSTs
|
|
# /srt or /rist with its room grant and proof, and gets a one-time session.
|
|
[contrib]
|
|
host = "" # the host name stated in a session's answer
|
|
session_ttl_s = 60 # a session not connected by then is dropped
|
|
max_sessions = 16
|
|
max_bitrate_kbps = 80000 # per session, all streams, over limits.bitrate_window_ms
|
|
record_interval_ms = 10000 # how often a session signs a part of its link record
|
|
idle_ms = 5000 # a link that receives nothing this long is ended
|
|
|
|
[contrib.srt]
|
|
# listen = "127.0.0.1:9000" # the SRT listener; absent: /srt is 404
|
|
latency_ms = 120 # the connection's is the larger of the two ends'
|
|
pbkeylen = 16 # AES key bytes: 16, 24 or 32
|
|
call_allow = [] # publishers' listeners the gateway may call: "ip:port" or "ip"
|
|
|
|
[contrib.rist]
|
|
enabled = false # needs a build with the feature `rist`
|
|
bind_ip = "127.0.0.1"
|
|
port_min = 0 # the ports sessions are given; 0 and 0: any free port
|
|
port_max = 0
|
|
buffer_ms = 1000
|
|
aes = 128 # the Main Profile's PSK key bits: 128 or 256
|