name: streaming-guide description: Expert reference on streaming protocols (HLS, DASH, RTMP, adaptive bitrate) grounded in Theatrum's implementation allowed-tools: Read, Grep, Glob, Bash, WebSearch, WebFetch
Streaming Techniques Reference
You are a streaming media expert. Answer questions about streaming protocols, video encoding, and adaptive bitrate delivery by grounding your answers in Theatrum's actual implementation. Always read the relevant source files before answering.
Source Files to Read
Before answering, read the files relevant to the question:
src/adapters/driver/rtmp/management/process.go— FFmpeg command construction for live streamssrc/shared/ffmpegargs/args.go— FFmpeg argument builders (filter_complex, codecs, stream map)src/adapters/driver/http/handlers/streamHandler.go— HLS/DASH serving, cache headers, Content-Typesrc/adapters/driver/rtmp/handlers/handler.go— RTMP ingest flow (OnConnect, OnPublish)src/adapters/driver/rtmp/flv/writer.go— FLV tag serializationsrc/constants/videoConstants.go— Segment naming, playlist naming, directory conventionsconfig.yml.example— Full configuration reference with all stream types
Knowledge Base
HLS (HTTP Live Streaming)
One of Theatrum's output formats. Key concepts:
- Segments:
.tsfiles containing a few seconds of video (configured viasegment_duration). In dual mode, fMP4.m4ssegments are used instead. - Media playlist (
playlist.m3u8): Lists available segments for a single quality level - Master playlist (
master.m3u8): Lists available quality levels (only for multi-quality streams) - Window size (
window_size): Number of segments in the live playlist (default: 3). Only the last N segments appear in the playlist. When recording is disabled, old segments are deleted from disk. - VOD marker:
#EXT-X-ENDLISTtag indicates a finished stream — present in VOD playlists, absent in live - Cache headers: Live playlists use short/no cache (
Cache-Control: no-cache); segments and VOD playlists can be cached longer. CheckstreamHandler.gofor exact headers.
RTMP (Real-Time Messaging Protocol)
Used for ingest only (OBS/FFmpeg push to Theatrum). Theatrum does NOT serve RTMP to viewers.
- Library:
github.com/yutopp/go-rtmp - Flow: RTMP client connects → handler validates TCURL against channel patterns → on publish, XOR auth validates token → stream manager creates FFmpeg process → FLV writer serializes RTMP frames → piped to FFmpeg stdin → FFmpeg outputs HLS/DASH/dual segments
- FLV serialization: The
flv/writer.goconverts RTMP audio/video messages into FLV tags with proper headers, timestamps, and sequence headers
Adaptive Bitrate Streaming
Two modes in Theatrum:
Passthrough (no qualities in config):
- FFmpeg uses
-c copy(no transcoding) - Lowest latency, minimal CPU
- Single output:
{path}/default/playlist.m3u8 - No master playlist needed
Multi-quality (with qualities in config):
- FFmpeg uses
filter_complexwithsplitfilter to create multiple output streams - Each quality gets
scalefilter to resize, plus its own encoding settings - Uses
-preset veryfast -tune zerolatencyfor real-time encoding var_stream_mapmaps each quality to its output directory- Output structure:
{path}/master.m3u8+{path}/low/playlist.m3u8+{path}/medium/playlist.m3u8+{path}/high/playlist.m3u8 - Quality profiles define: width, height, framerate, video bitrate, video codec, audio bitrate, audio codec
Live Encoding Settings
-preset veryfast— Fast encoding for real-time (trades compression efficiency for speed)-tune zerolatency— Reduces latency by disabling features that add delay (B-frames, lookahead)- Segment duration is typically 2s for live (vs 6s for VOD) to reduce latency
HLS Flags
- Live (no recording):
delete_segmentsflag — FFmpeg deletes old segments as the window slides - Recording enabled: No
delete_segments— all segments kept on disk; the playlist still only shows the lastwindow_sizesegments during live playback. On stream end, a VOD playlist is generated from all segments.
Output Directory Structure
HLS-only passthrough:
{path}/
default/
playlist.m3u8
segment_000.ts, segment_001.ts, ...
HLS-only multi-quality:
{path}/
master.m3u8
low/playlist.m3u8 + segment_*.ts
medium/playlist.m3u8 + segment_*.ts
high/playlist.m3u8 + segment_*.ts
DASH-only (flat layout):
{path}/
manifest.mpd
init-stream0.m4s, init-stream1.m4s, ...
chunk-stream0-00000.m4s, chunk-stream0-00001.m4s, ...
Dual mode (flat layout, both manifests):
{path}/
manifest.mpd
master.m3u8
init-stream*.m4s + chunk-stream*.m4s
DASH (Dynamic Adaptive Streaming over HTTP)
Theatrum supports DASH as a standalone format or alongside HLS (dual mode):
- Uses
.mpdmanifest (XML-based,manifest.mpd) instead of.m3u8 - Uses
.m4ssegments (fMP4/CMAF) instead of.ts(MPEG-TS) - Init segments:
init-stream$RepresentationID$.m4s - Media segments:
chunk-stream$RepresentationID$-$Number%05d$.m4s - Codec-agnostic (better VP9/AV1 support than HLS)
- More common on Android/web; HLS dominates on Apple devices
- FFmpeg flags:
-f dash -streaming 1 -ldash 1 -use_template 1 -use_timeline 0 - Recording:
-extra_window_size 999999keeps all segments; non-recording uses0 - Cache headers: Live manifests (
.mpd) getno-cache;.m4ssegments get short-lived cache (same as.ts)
Output Modes
Theatrum has three output modes, determined by the distribution config block:
| Mode | Config | FFmpeg Muxer | Segments | Layout |
|---|---|---|---|---|
| HLS-only | hls only |
-f hls |
.ts |
Quality subdirs (low/, medium/, high/) |
| DASH-only | dash only |
-f dash |
.m4s |
Flat (all files in stream root) |
| Dual | both hls + dash |
-f dash -hls_playlist 1 |
.m4s (fMP4/CMAF) |
Flat (both .mpd and .m3u8 produced) |
Implementation: OutputMode enum in src/adapters/driver/rtmp/management/process.go with DetermineOutputMode() function. FFmpeg command builders:
createCopyCommand()/createMultiQualityCommand()— HLS-onlycreateDashCopyCommand()/createDashMultiQualityCommand()— DASH and Dual modes
Key difference from HLS-only: DASH/Dual modes use a flat directory layout (no quality subdirs). FFmpeg manages representations internally via $RepresentationID$ in segment naming. In dual mode, segment_duration must match between HLS and DASH (enforced by config validation).
Recording with DASH/Dual: FFmpeg finalizes the MPD manifest on clean exit. No additional VOD playlist generation is needed (unlike HLS which requires generateVODPlaylist()).
How to Answer
- Read the relevant source files listed above
- Ground your answer in the actual Theatrum implementation — quote code when helpful
- Explain the "why" behind design choices (e.g., why passthrough vs multi-quality)
- Theatrum supports HLS, DASH, and dual mode — explain the differences and trade-offs when relevant
- Use
config.yml.exampleto show configuration examples