SRT¶
media.play.srt
Transport¶
MPEG-TS over SRT/UDP; the client connects in caller mode to the stream’s dedicated port.
Supported codecs¶
Video
- H.264
- HEVC
- AV1
- JPEG 2000
- MPEG-2 Video
Audio
- AAC
- MP2
- MP3
- AC-3
- E-AC-3
- SMPTE 302M
Other tracks
- SCTE-35
- KLV
- ID3
- tx3g
- Teletext
- DVB subtitles
This list describes Sapsan output; decoding support depends on the player. Tracks also need valid codec parameters for packaging in the selected container.
Sapsan serves a stream over SRT: each stream gets a dedicated UDP port that SRT clients connect to in caller mode.
AV1 in MPEG-TS uses the stream_type = 0x06 convention with the AV01 registration descriptor; the receiver must understand this form. This does not guarantee compatibility with every AV1-in-TS implementation. Opus is excluded from the list: recognizing or announcing a codec alone does not establish usable output, and the current path does not provide the required Opus TS/PES framing.
Configuration¶
Set these options through central in the streamer config.
streams:
- name: tv1
inputs:
- udp: {host: 239.0.0.1, port: 5000}
srt_play:
port: 4010
passphrase: verysecretpass
passphrase enables encryption; without it the stream is served unencrypted.
The srt_play section may carry an mpegts subsection — its own program number, track PIDs, and SDT for playback from this port only.
Client map¶
A port-wide passphrase is a single lock shared by everyone: everyone you gave the key to holds it. A client map defines personal locks: each viewer gets a secret of their own, and the session automatically receives an owner — the name of the matching record.
streams:
- name: tv1
inputs:
- udp: {host: 239.0.0.1, port: 5000}
srt_play:
port: 4010
clients:
ivan:
passphrase: ivan-personal-secret
office:
ips: [198.51.100.0/24]
A map record is a client name with two optional fields:
passphrase— the record's personal secret: when set, the handshake is encrypted and the viewer must present exactly this one; when unset, the record accepts unencrypted handshakes.ips— an address filter: an address or subnet connections are accepted from. A missing or empty set does not restrict connections.
Admission follows from the record fields: an encrypted connection is accepted when its key material unfolds with the passphrase of one of the records with a password whose addresses include the viewer's address; an unencrypted one — by a passwordless record with a matching address, or by an open record (no password, no addresses) from any address. Records with and without a password coexist in one map: encryption is a property of the handshake, not of the port.
The viewer's session carries the owner — the name of the matching map record. For a delivery without a map, the owner comes from the user_id_<name> tag in labels; sessions of an untagged, map-less delivery stay without a subject.
The configuration is validated on save:
- Identical
passphrasevalues of two clients of one delivery are rejected: the secret is how a session identifies its client. - Overlapping
ipssets of two clients are rejected: an address filter must belong to exactly one client.
In the management console the secret is generated by the server when a client is added. In YAML, an open record is a valid form of unrestricted access.
The viewer connects with their own secret:
ffplay "srt://server:4010?passphrase=ivan-personal-secret"
Handshake observability¶
A delivery with a client map accepts handshakes from the network, and its primary load is secret checking. The node counts handshakes as series in the node scrape (GET /streamer/api-v4/runtime/metrics):
| Series | What it counts |
|---|---|
srt_handshake_attempts_total |
attempts that reached an admission decision |
srt_handshake_secret_candidates_total |
secret candidates tried — the total number of key material checks |
srt_handshake_bad_secret_total |
rejections: no candidate matched |
srt_handshake_address_filter_rejects_total |
address-filter rejections |
# a regular viewer spends a couple of candidates per attempt; brute force tries the whole map
rate(srt_handshake_secret_candidates_total[5m])
/ rate(srt_handshake_attempts_total[5m])
Playback¶
ffplay "srt://server:4010?passphrase=verysecretpass"