Real-Time System Design

System Design · Real-Time System Design

Live Streaming: RTMP, OBS, FFmpeg & YouTube Live

How a stream gets from a streamer's webcam to a million viewers' screens — capture, ingest, transcode, and adaptive-bitrate delivery.

9 min read
Live StreamingRTMPFFmpeg

Watching a live stream feels instantaneous, but by the time a frame reaches your screen it has already passed through four or five distinct systems — a capture encoder on the streamer's machine, an ingest server, a transcoding farm, and a content delivery network — each adding its own slice of latency and its own opportunity for things to go wrong. Understanding that pipeline end to end explains both why live streaming works as well as it does at massive scale, and why it's never quite as "live" as the name suggests.

The pipeline, end to end

Strip away the branding differences between YouTube Live, Twitch, and a self-hosted setup, and every live stream follows the same four stages. Capture: a streamer's encoder — most commonly OBS Studio — grabs screen, camera, and microphone input and compresses it into a single encoded stream. Ingest: that stream is pushed across the internet to a server, almost always over RTMP. Transcode: the ingest server takes the one incoming stream and re-encodes it into several quality renditions — a "bitrate ladder" — so viewers with different bandwidth and different screens all get something that fits. Distribute: each rendition is chopped into small segments, packaged as HLS or DASH, and pushed through a CDN to millions of viewers' players, which pick whichever rendition fits their current connection.

Four stages, four different sets of engineering trade-offs — and four different places where latency quietly accumulates.

RTMP: the ingest workhorse, not the playback protocol

RTMP (Real-Time Messaging Protocol) was designed by Macromedia for Flash video and has, somewhat improbably, outlived Flash entirely. It keeps a persistent TCP connection open between the encoder and the server, multiplexes audio, video, and metadata over it, and delivers frames with very low overhead — which is exactly what you want when a streamer's laptop is pushing a continuous signal that absolutely cannot afford to stall waiting for a new connection handshake every few seconds.

Ingest only, not playback

RTMP's reach today is almost entirely on the ingest side — streamer to server. No modern browser ships a native RTMP player anymore (Flash is gone, and nothing replaced it as a browser-side RTMP client), so viewers never receive an RTMP stream directly. Playback happens over HTTP-based protocols instead — HLS or DASH — which is precisely why the pipeline needs a transcode and package stage in the middle rather than simply relaying the incoming stream to viewers unchanged.

This split is a deliberate trade-off, not an accident: RTMP is excellent for one long-lived, low-latency, bidirectional connection from a single sender, while HLS/DASH are excellent for fanning a stream out to millions of receivers over ordinary HTTP infrastructure — CDNs, caches, and browsers that already know how to fetch files.

OBS Studio: capture and encode at the source

OBS (Open Broadcaster Software) Studio is the software running on the streamer's own machine that does the actual capture work — compositing scenes from a screen capture, a webcam, overlays, and audio inputs into a single video frame, encoding that frame with H.264 (or increasingly AV1/HEVC) for video and AAC for audio, and pushing the resulting encoded stream out over RTMP to whatever ingest endpoint the platform hands it. Everything downstream depends on the choices made here: the keyframe interval OBS uses determines how finely the server can later cut the stream into segments, and the bitrate and resolution OBS is configured with becomes the ceiling for every rendition the server can produce afterward — you cannot upscale detail that was never captured.

FFmpeg: building the bitrate ladder

Once the stream lands on the ingest server, FFmpeg (or a purpose-built transcoding service built around the same libavcodec internals) takes over. Its job is to decode the single incoming stream and re-encode it into multiple renditions at different resolutions and bitrates — the same adaptive bitrate idea that HLS and DASH rely on for playback, just produced on the server rather than requested by the client. A viewer on a fast fiber connection and a large monitor gets the 1080p rendition; a viewer on patchy mobile data gets 480p without ever seeing the stream stall.

bash
# Take one incoming RTMP stream and transcode it into a bitrate ladder
# of three renditions, each ready to be packaged as HLS.
ffmpeg -i rtmp://ingest.example.com/live/streamkey \
  -filter_complex \
    "[0:v]split=3[v1][v2][v3]; \
     [v1]scale=w=1920:h=1080[v1out]; \
     [v2]scale=w=1280:h=720[v2out]; \
     [v3]scale=w=854:h=480[v3out]" \
  -map "[v1out]" -c:v:0 h264 -b:v:0 5000k \
  -map "[v2out]" -c:v:1 h264 -b:v:1 2800k \
  -map "[v3out]" -c:v:2 h264 -b:v:2 1400k \
  -map a:0 -c:a aac -b:a 128k -ac 2 \
  -f hls -hls_time 4 -hls_playlist_type event \
  -master_pl_name master.m3u8 \
  -var_stream_map "v:0,a:0 v:1,a:0 v:2,a:0" \
  stream_%v/segment_%03d.ts

Transcoding at this scale is CPU- and GPU-intensive — a single popular stream might need this same ladder computed continuously for hours — which is why large platforms lean heavily on hardware encoders (NVENC, Quick Sync, dedicated ASICs) rather than software-only x264 to keep the cost per concurrent stream manageable.

Packaging and delivery: HLS/DASH over a CDN

Each rendition coming out of the transcoder is sliced into short segments — typically two to six seconds each — and described by a manifest (an .m3u8 playlist for HLS, an.mpd manifest for DASH) that lists the available renditions and where their segments live. Those segments are ordinary files, which means they can be cached and fanned out through a standard HTTP CDN exactly like any other static asset — this is the trick that lets a platform serve a live stream to millions of concurrent viewers without millions of persistent server-side connections. The video player on each viewer's device reads the manifest, starts on a sensible rendition, and continuously re-evaluates measured download speed to switch renditions up or down as conditions change.

The latency budget

Add up every stage and the "glass-to-glass" latency — from a photon hitting the streamer's camera to a pixel lighting up on a viewer's screen — typically lands somewhere between three and fifteen seconds for a traditional HLS/DASH pipeline like the one above. Capture and encode on OBS contributes a few hundred milliseconds. RTMP ingest is fast, but the transcoder has to buffer enough frames to produce clean segment boundaries, adding another second or two. Packaging into two-to-six-second segments — and most players deliberately keeping two or three segments queued to absorb network jitter — is usually the single largest contributor, often six to twelve seconds by itself. CDN propagation adds a little more, and the player's own playback buffer rounds it out.

Why this isn't good enough for everything

Several seconds of delay is invisible for a one-way broadcast — a conference keynote or a gaming stream — but it's unworkable for anything that needs a viewer's reaction to travel back in real time: a live auction, an interactive quiz overlay, or a video call. That gap is exactly what low-latency HLS/DASH variants and WebRTC-based pipelines exist to close, trading some of this architecture's simplicity and CDN-friendliness for sub-second latency.

None of that makes the HLS/DASH pipeline obsolete — it's still the right choice whenever reach and cost-per-viewer matter more than shaving off the last few seconds, which is most live streaming on the internet today.

Key takeaways

  • The pipeline is always capture → ingest → transcode → distribute, no matter which platform is running it.
  • RTMP is an ingest protocol today, not a playback one — encoders like OBS push over RTMP, but viewers receive HLS or DASH.
  • OBS captures and encodes on the streamer's machine; its settings set a ceiling every downstream rendition inherits.
  • FFmpeg builds the server-side bitrate ladder, mirroring the same adaptive-bitrate idea HLS/DASH use for playback.
  • Segmenting renditions into HLS/DASH lets a plain HTTP CDN handle fan-out to millions of viewers.
  • Segment buffering, not the network, is usually the biggest contributor to glass-to-glass latency — which is why sub-second use cases turn to low-latency HLS or WebRTC instead.
2026 — Built by Arpit Mishra