Why RTMP ingest and HLS delivery pair well
RTMP ingest remains the workhorse of live contribution from encoders like OBS, vMix, Wirecast, ATEM, and many hardware boxes. HLS delivery is the de facto playback format across the web, iOS, and most TV platforms. Together, “RTMP to HLS” gives you broad encoder compatibility on the input and near-universal playback on the output.
- RTMP ingest benefits:
- Ubiquitous support in software/hardware encoders
- Simple push workflow over TCP (port 1935)
- Stable at typical bitrates on reliable networks
- HLS delivery benefits:
- Native on iOS/tvOS and supported via hls.js on major browsers
- Adaptive bitrate (ABR) streaming, DVR windows, captions, timed metadata
- Low-Latency HLS (LL-HLS) can reduce end-to-end delay to low single-digit seconds when tuned
Tradeoffs:
- RTMP is older (H.264/AAC only in practice), no built-in FEC/ARQ; SRT ingest is often better over lossy networks.
- HLS delivery is segment-based; default setups yield 6–20 seconds glass-to-glass latency; LL-HLS reduces this but adds operational complexity.
Reference live streaming architecture (RTMP to HLS)
Typical live streaming architecture:
- Ingest: RTMP push from encoders
- Transcode: Create ABR ladder (e.g., 1080p, 720p, 480p, 360p)
- Package: HLS manifests and segments (MPEG-TS or fMP4/CMAF)
- Storage/Origin: Serve manifests/segments
- CDN: Cache and deliver globally
- Player: hls.js (web), AVPlayer (iOS), ExoPlayer (Android)
A simplified diagram:
Encoders (OBS, vMix, ATEM) --RTMP--> Ingest/Origin --Transcode/Package--> HLS (m3u8/segments)
| |
v v
Storage/Origin <-----> CDN
Core configuration decisions
Before touching configs, decide:
- Codecs: H.264 (Baseline/Main/High) + AAC-LC are the safest for RTMP to HLS. HEVC in HLS is possible, but not via RTMP.
- GOP/keyframe interval: Align keyframes to segment boundaries. Common: 2-second segments with a 2-second GOP (e.g., 60 frames at 30 fps). For LL-HLS, consider 1–2 second target duration with partial segments.
- ABR ladder: 3–6 rungs typically. Example starting point:
- 1080p: 6 Mbps video, 192 kbps audio
- 720p: 3 Mbps video, 128 kbps audio
- 480p: 1.5 Mbps video, 128 kbps audio
- 360p: 800 kbps video, 96 kbps audio
- 240p: 400 kbps video, 64 kbps audio
Tune per content complexity; sports needs higher bitrates than talking heads.
- Container: MPEG-TS (broadest support) vs fMP4/CMAF (better for LL-HLS and cache efficiency). For legacy devices, TS remains common; for modern stacks, CMAF is attractive.
- Latency target:
- Standard HLS: 6–12s typical (2–4s segments, 3–5 segments in playlist)
- LL-HLS: ~2–6s with partial segments and tuned player retry intervals
- DVR/recording: Decide on window (e.g., 30–120 minutes). Larger windows increase storage and playlist size.
Step-by-step: rtmp server setup and HLS packaging
There are two common paths:
1) Quick start with open-source components (Nginx RTMP + FFmpeg)
2) Production server software or a managed platform (Nighthawk Server/Cloud, Wowza, Nimble, etc.)
Option 1: Nginx-RTMP + FFmpeg (reference workflow)
This is good for labs, PoCs, or small streams. For larger scale or LL-HLS, move to a full streaming server.
- Install Nginx with the RTMP module
- On many Linux distros you can install from packages or build the nginx-rtmp-module. Minimal config:
rtmp {
server {
listen 1935;
chunk_size 4096;
application live {
live on;
record off;
# Authentication hook recommended in production
}
}
}
http {
server {
listen 8080;
location /hls/ {
types { application/vnd.apple.mpegurl m3u8; video/mp2t ts; }
add_header Cache-Control "public, max-age=10";
add_header Access-Control-Allow-Origin *;
root /var/www;
}
}
}
- Push RTMP from your encoder
- OBS example: rtmp://your-server:1935/live/streamKey
- Hardware encoder: same pattern; use a strong stream key.
- Transcode + package to HLS with FFmpeg
- Read the RTMP input and emit a multi-variant HLS. This example creates 4 variants (H.264/AAC) with 2-second segments, keyframe-aligned:
ffmpeg -i rtmp://localhost/live/streamKey \
-c:v libx264 -preset veryfast -g 60 -keyint_min 60 -sc_threshold 0 \
-c:a aac -ar 48000 -ac 2 -b:a:0 192k -b:a:1 128k -b:a:2 96k -b:a:3 64k \
-filter_complex " \
[0:v]split=4[v1080][v720][v480][v360]; \
[v1080]scale=w=1920:h=1080:force_original_aspect_ratio=decrease[v1080out]; \
[v720] scale=w=1280:h=720:force_original_aspect_ratio=decrease[v720out]; \
[v480] scale=w=854:h=480:force_original_aspect_ratio=decrease[v480out]; \
[v360] scale=w=640:h=360:force_original_aspect_ratio=decrease[v360out]" \
-map [v1080out] -b:v:0 6000k -maxrate:0 6600k -bufsize:0 12000k \
-map 0:a -map [v720out] -b:v:1 3000k -maxrate:1 3300k -bufsize:1 6000k \
-map 0:a -map [v480out] -b:v:2 1500k -maxrate:2 1650k -bufsize:2 3000k \
-map 0:a -map [v360out] -b:v:3 800k -maxrate:3 880k -bufsize:3 1600k \
-var_stream_map "v:0,a:0 v:1,a:1 v:2,a:2 v:3,a:3" \
-f hls -hls_time 2 -hls_list_size 10 -hls_flags independent_segments \
-master_pl_name master.m3u8 \
-strftime_mkdir 1 -hls_segment_filename "/var/www/hls/v%v/seg_%Y%m%dT%H%M%S.ts" \
"/var/www/hls/v%v/stream.m3u8"
- Serve /var/www/hls via Nginx HTTP at http://your-server:8080/hls/master.m3u8
Notes:
- For fMP4/CMAF packaging, add -hls_segment_type fmp4 -hls_flags +independent_segments+split_by_time. Confirm player/CDN support.
- LL-HLS with FFmpeg-only is possible but fragile; production LL-HLS generally requires server and CDN support for partial segments and preload hints.
Option 2: Production streaming server or managed platform
A streaming server consolidates RTMP ingest, ABR transcoding, HLS packaging, DVR, origin-edge clustering, APIs, and observability. This reduces glue code and adds controls like WebRTC preview, SRT ingest, and webhooks.
- Self-hosted: Nighthawk Server (Docker-native, perpetual license), Nimble Streamer, Wowza Streaming Engine, etc.
- Managed: Nighthawk Cloud, plus other SaaS providers. Managed options eliminate rtmp server setup and CDN plumbing, useful for teams prioritizing velocity over control.
With Nighthawk Server, a typical flow is:
- Run the container on your compute (on-prem or cloud)
- Create an RTMP application and stream keys via the portal/API
- Enable transcoding profiles per channel
- Serve HLS directly to your CDN with tokenized URLs
Player and manifest fundamentals
- HLS master playlist lists all variants; each variant playlist contains EXT-X-TARGETDURATION, EXT-X-MEDIA-SEQUENCE, and segments.
- Align keyframes with segment boundaries to enable seamless ABR switching (use -g and -sc_threshold 0 in x264).
- Include CODECS and RESOLUTION attributes for better device selection.
- For DVR, use a sliding window (EXT-X-PLAYLIST-TYPE: EVENT) and optionally EXT-X-START to bias playback.
- Timed metadata: In-band ID3 for live captions/graphics sync; keep it sparse to avoid cache churn.
CDN and cache strategy for HLS delivery
HLS delivery performance depends heavily on cache behavior:
- Cache policy
- Segments: long TTL (e.g., 1–24 hours); immutable naming with timestamps makes this safe
- Playlists: very short TTL (2–10 seconds standard; 0.5–2 seconds for LL-HLS)
- Headers
- Cache-Control on segments: public, max-age=NNNN, immutable
- Cache-Control on playlists: public, max-age=short, must-revalidate
- CORS: Access-Control-Allow-Origin: * (or your domains) for web playback
- Origin shielding and coalescing reduce thundering herd on playlist refreshes.
- Path structure: /hls/<channel>/v<bitrate>/seg_<timestamp>.<ext>; avoid overwriting filenames to maximize CDN hit ratio.
Security: ingest and playback
- RTMP ingest
- Require authentication (signed query, RTMP on_connect hook, or whitelist)
- TLS for RTMP (RTMPS) if traversing untrusted networks; otherwise, prefer SRT for resilience
- HLS delivery
- TLS everywhere (HTTPS)
- Tokenized URLs (expiring query params or path tokens) validated at origin/CDN edge
- AES-128 or SAMPLE-AES encryption if needed; distribute keys via token-protected endpoints
- Hotlink protection and domain referrer checks where appropriate
High availability and scaling
- Redundant ingest: Provide primary/backup RTMP endpoints and stream keys; configure encoders for failover.
- Transcoder scaling: Horizontal scale by channel; pin real-time workloads to vCPU/NUMA; consider GPU if you need many ladders per host.
- Origin-edge clustering:
- Origins handle writes (incoming segments) and short-TTL playlist requests
- Edges cache segments long TTL and serve high fan-out
- Storage: Local NVMe for segment IO; object storage for recording/DVR export. Keep HLS hot on fast disk for live.
- LL-HLS: Ensure CDN supports partial object caching and HTTP/2/3; tune target duration, part hold-back, and player retry intervals.
Monitoring and troubleshooting
Track:
- Ingest health: input bitrate, dropped frames, encoder RTT, reconnects
- Transcode health: per-variant FPS, queue depth, CPU/GPU usage, x264 VBV violations
- HLS correctness: media sequence monotonicity, segment continuity, discontinuities on encoder scene changes
- CDN metrics: playlist/segment hit ratio, 4xx/5xx rates, tail latency
- Player QoE: startup time, rebuffer ratio, average bitrate, error rates
Common issues:
- Player stalling: playlist cache TTL too long; reduce max-age or enable revalidation
- ABR thrash: ladder too steep or player bandwidth estimation too aggressive; smooth with BOLA/ABR config and reasonable rung spacing (~1.5x)
- Desync A/V: incorrect PTS/DTS after transcoding; ensure -vsync passthrough and consistent audio sample rate
- Latency creep: segments or part durations too long; decrease target duration and ensure CDN respects low TTLs
RTMP to HLS server options (balanced comparison)
| Tool | Packaging | LL-HLS | License model | Deploy style | When it fits |
|---|---|---|---|---|---|
| Nginx-RTMP + FFmpeg | TS and fMP4 via FFmpeg | Possible but fragile | Open-source | DIY on VMs/bare metal | Labs, PoC, small streams, custom pipelines |
| Nighthawk Server | TS and CMAF, ABR, DVR | Supported with proper CDN | Perpetual license (buy once) | Docker-native self-hosted | Teams wanting control, API, clustering, and no software rent |
| Wowza Streaming Engine | TS and CMAF, ABR | Supported | Subscription | VM/bare metal | Enterprises with existing Wowza ops |
| Nimble Streamer | TS and CMAF, ABR | Supported | Commercial | VM/bare metal | Efficient pipelines, low resource usage |
| Nighthawk Cloud | Managed HLS output | Supported | Pay-as-you-go | SaaS | Teams that don’t want to run servers |
This isn’t exhaustive; other vendors and clouds exist. Choose based on your latency goals, ops maturity, and budget.
Cost considerations
- Compute: Transcoding is CPU/GPU-heavy. Expect on the order of 1–2 dedicated vCPUs per 1080p ladder rung with software x264 at veryfast; GPUs increase density.
- Storage/IO: Live HLS is write-heavy small files; fast local SSDs help. DVR windows and recordings drive capacity.
- CDN egress: Usually the largest ongoing cost; ABR multiplies segment volume. Optimize cache hit ratio and ladder size.
- Software: Self-hosted licensing vs subscriptions. Perpetual licenses can reduce long-term TCO if you run steady workloads.
SRT and other ingest protocols
RTMP ingest is simple, but SRT is often better over the public internet due to ARQ and encryption. Many modern servers accept both. A pragmatic pattern is:
- Encourage SRT for field and long-haul contribution
- Keep RTMP ingest for studio/software encoders and as a fallback
- Output remains HLS delivery for broad playback
Call to action: own your RTMP-to-HLS workflow
If you want an RTMP to HLS pipeline that you can run on your own infrastructure—and own outright—Nighthawk Server provides Docker-native ingest, ABR transcoding, HLS/CMAF packaging, DVR/recording, origin-edge clustering, APIs, webhooks, and cloud management. It’s sold as a perpetual license (buy once, own forever) with optional annual support plans. Prefer fully managed? Nighthawk Cloud offers a free tier and pay-as-you-go plans so you can skip rtmp server setup and CDN plumbing.
Nighthawk is the streaming company that will never charge you rent on software you host yourself. Explore Nighthawk Server and Nighthawk Cloud at https://nighthawk.tv.
Practical checklist
- Encoder
- H.264 High profile, 30/60 fps, keyframe interval = 2s (or your segment size)
- CBR or capped CRF with VBV; audio AAC-LC 48 kHz
- Ingest
- RTMP(S) endpoint with auth; SRT as preferred option for tough networks
- Transcode
- 3–6 rung ABR ladder; aligned GOPs; tune VBV
- Package
- HLS (TS for legacy, CMAF for LL-HLS); short playlists; immutable segments
- Delivery
- CDN with segment-long TTL and short playlist TTL; CORS headers
- Security
- Tokenized URLs; TLS; optional AES-128
- Observability
- Ingest/transcode metrics; HLS validators; CDN 4xx/5xx; player QoE
Minimal player example (web)
For desktop browsers, hls.js plays master.m3u8 on HTML5 video:
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<video id="video" controls playsinline></video>
<script>
const url = 'https://cdn.example.com/hls/master.m3u8';
const video = document.getElementById('video');
if (video.canPlayType('application/vnd.apple.mpegurl')) {
video.src = url; // Safari
} else if (Hls.isSupported()) {
const hls = new Hls({lowLatencyMode: true});
hls.loadSource(url);
hls.attachMedia(video);
}
</script>
FAQ
What latency should I expect from RTMP to HLS?
With 2–4 second segments and 3–5 segments in the playlist, end-to-end latency is typically 6–20 seconds. With LL-HLS (partial segments, preload hints, tuned player), you can often get to the 2–6 second range, assuming CDN and player support.
Can I ingest with SRT and still deliver HLS?
Yes. Many servers accept SRT ingest and produce HLS delivery. SRT offers better resilience on lossy networks than RTMP. The output HLS manifest/segments are the same from the player’s perspective.
How do I secure RTMP ingest and HLS playback?
Use authenticated stream keys or signed URLs for RTMP, ideally over RTMPS or SRT. For HLS, serve over HTTPS with tokenized (expiring) URLs. If required, use AES-128 or SAMPLE-AES encryption with keys delivered via authorized endpoints.
How do I choose segment duration and GOP size?
Pick a segment duration that matches your latency goals: 6–10 seconds for traditional broadcast-like stability, 2–4 seconds for lowish latency, and shorter parts for LL-HLS. Set GOP = segment duration (e.g., 2s segments → 2s GOP) and ensure keyframes land on boundaries to enable smooth ABR switching.