SRT Ingest#

go-rtmp accepts SRT (Secure Reliable Transport) streams over UDP alongside RTMP. SRT publishers are transparently converted to RTMP format — existing RTMP subscribers can watch SRT sources without any changes.

Enabling SRT#

Add the -srt-listen flag to start the UDP listener:

./rtmp-server -listen :1935 -srt-listen :4200 -log-level info

The server now accepts RTMP on TCP port 1935 and SRT on UDP port 4200 simultaneously.

Publishing via SRT#

FFmpeg#

ffmpeg -re -i test.mp4 -c copy -f mpegts \
  "srt://localhost:4200?streamid=live/test&pkt_size=1316"

OBS Studio#

  1. Settings → Stream → Service: Custom
  2. Server: srt://your-server:4200
  3. Stream Key: live/test

IP Cameras#

Most IP cameras with SRT support can publish directly. Set the SRT destination to:

srt://your-server:4200?streamid=live/camera1

Stream ID Formats#

SRT uses the Stream ID to identify the target stream key. Three formats are supported:

FormatExampleStream Key
Simplelive/testlive/test
Prefixedpublish:live/testlive/test
Structured#!::r=live/test,m=publishlive/test

SRT Encryption#

SRT encryption provides end-to-end AES-CTR encryption of all media data using a shared passphrase. When enabled, clients must provide the correct passphrase during the SRT handshake — connections with wrong or missing passphrases are rejected.

Server setup:

# AES-128 (default key length)
./rtmp-server -listen :1935 -srt-listen :4200 -srt-passphrase "my-secret-key"

# AES-256 (recommended for maximum security)
./rtmp-server -listen :1935 -srt-listen :4200 -srt-passphrase "my-secret-key" -srt-pbkeylen 32

Publisher (FFmpeg):

ffmpeg -re -i test.mp4 -c copy -f mpegts \
  "srt://localhost:4200?streamid=publish:live/test&passphrase=my-secret-key&pbkeylen=32"

Publisher (OBS Studio):

In OBS, set the Stream URL to srt://server:4200?streamid=publish:live/test&passphrase=my-secret-key.

FlagDefaultDescription
-srt-passphrase(none)Shared secret for AES encryption (10-79 characters)
-srt-pbkeylen16Key length in bytes: 16 (AES-128), 24 (AES-192), or 32 (AES-256)

How It Works#

During the SRT handshake, the client and server exchange encryption keys:

  1. The client generates a random Stream Encrypting Key (SEK) and salt
  2. The SEK is wrapped using a Key Encrypting Key (KEK) derived from the shared passphrase via PBKDF2
  3. The wrapped key is sent to the server in a KMREQ extension
  4. The server derives the same KEK, unwraps the SEK, and confirms with KMRSP
  5. All subsequent data packets are encrypted with AES-CTR

Key Rotation#

For long-running streams, the client automatically rotates the encryption key (typically every ~6-7 hours). SRT uses a hitless dual-key model — both the old and new keys are active during the transition, so no packets are lost.

Supported Key Lengths#

Key Length-srt-pbkeylenNotes
AES-12816 (default)Standard security
AES-19224Enhanced security
AES-25632Maximum security (recommended)

Security Notes#

  • The passphrase must be 10-79 characters (enforced by the SRT specification)
  • Connections without a passphrase are rejected when encryption is configured
  • Plaintext packets on encrypted connections are dropped
  • The server validates all crypto parameters and rejects unsupported configurations

Per-Stream Encryption#

Instead of a single passphrase for all streams, you can assign each stream its own passphrase using a JSON file. This is useful when different publishers need independent credentials.

1. Create a passphrase file (e.g. /etc/rtmp/srt-keys.json):

{
  "live/stream1": "passphrase-at-least-10-chars",
  "live/stream2": "another-secret-key-here"
}

Each key is a stream key and each value is the passphrase (10-79 characters per the SRT spec). Passphrases are validated at load time — the server refuses to start if any are out of range.

2. Start the server with -srt-passphrase-file:

./rtmp-server -srt-listen :10080 -srt-passphrase-file /etc/rtmp/srt-keys.json -srt-pbkeylen 16

3. Publish with the stream’s passphrase:

ffmpeg -re -i input.mp4 -c copy -f mpegts \
  "srt://server:10080?streamid=publish:live/stream1&passphrase=passphrase-at-least-10-chars&pbkeylen=16"

Each client provides the passphrase assigned to its stream key — exactly the same syntax as single-passphrase mode.

4. Hot reload via SIGHUP:

You can update the passphrase file and apply changes without restarting the server:

kill -HUP $(pidof rtmp-server)

The server re-reads the file and swaps in the new passphrases. If the file contains errors (invalid JSON, out-of-range passphrases), the reload is rejected and the previous valid passphrases are preserved.

Note: -srt-passphrase and -srt-passphrase-file are mutually exclusive. The server will refuse to start if both are set. Use -srt-passphrase for a single global passphrase or -srt-passphrase-file for per-stream passphrases.

Latency Tuning#

The -srt-latency flag controls the TSBPD (Timestamp-Based Packet Delivery) jitter buffer:

./rtmp-server -srt-listen :4200 -srt-latency 200ms
LatencyUse Case
50msLow-latency LAN streaming
120msDefault — good for most internet streams
200ms–500msUnreliable networks, high-jitter connections

Codec Support#

SRT streams carry MPEG-TS containers. The server automatically detects and converts:

CodecSupportRTMP Output
H.264/AVC✅ FullStandard RTMP video (TypeID 9)
H.265/HEVC✅ FullEnhanced RTMP with FourCC hvc1
AAC✅ FullStandard RTMP audio (TypeID 8)

H.265 streams from SRT are automatically converted to Enhanced RTMP format, allowing modern players (FFmpeg 6.1+, OBS 29.1+) to subscribe.

Recording SRT Streams#

SRT streams are recorded just like RTMP streams when -record-all is enabled. The server automatically selects the container format:

  • H.264 streams → FLV recording
  • H.265 streams → MP4 recording
./rtmp-server -srt-listen :4200 -record-all true -record-dir ./recordings

SRT Metrics#

When metrics are enabled (-metrics-addr), SRT adds 6 counters:

CounterDescription
srt_connections_activeCurrently connected SRT publishers
srt_connections_totalTotal SRT connections since startup
srt_bytes_receivedTotal bytes received over SRT
srt_packets_receivedTotal SRT data packets received
srt_packets_retransmitPackets retransmitted (NAK recovery)
srt_packets_droppedPackets dropped (too late for TSBPD)

Architecture#

SRT Publisher → UDP → SRT Handshake → TSBPD Buffer → MPEG-TS Demux
    → Codec Convert (Annex B→AVCC, ADTS→raw) → chunk.Message → Stream Registry
    → RTMP Subscribers / Recording / Relay

The conversion is transparent: RTMP subscribers see the SRT source as a regular RTMP publisher.

Example: Full Setup#

# Accept RTMP, SRT, and RTMPS — record everything, expose metrics
./rtmp-server \
  -listen :1935 \
  -tls-listen :1936 \
  -tls-cert cert.pem \
  -tls-key key.pem \
  -srt-listen :4200 \
  -srt-latency 120ms \
  -record-all true \
  -record-dir /data/recordings \
  -metrics-addr :8080 \
  -log-level info

Publish via SRT and watch via RTMP:

# Publish H.265 via SRT
ffmpeg -re -i test.mp4 -c:v libx265 -c:a aac -f mpegts \
  "srt://localhost:4200?streamid=live/test"

# Subscribe via RTMP
ffplay rtmp://localhost:1935/live/test