FFmpeg automates the conversion of live streams to video-on-demand (VOD) by segmenting input into HLS-compliant media segments and dynamically generating the manifest files needed for smooth device playback. This workflow supports adaptive streaming and aligns with the latest Apple requirements for HLS, including proper playlist finalization and discontinuity management.
Prerequisites for FFmpeg HLS Automation Setup
- Install FFmpeg 4.2 or newer with HLS muxer support (--enable-muxer=hls if compiled from source)."
- A live input stream (RTMP, SRT, or HTTP FLV).
- Scripting environment (e.g., Bash, Python) for advanced automation scenarios.
- Output directory with write permissions for segments and manifests.
- Verify HLS output with ffmpeg -formats | grep hls.
Ingesting Live Stream Input into FFmpeg for HLS Processing
FFmpeg can ingest a live stream and generate HLS segments in one step. Here is a basic command for ingesting via RTMP and creating segments:
ffmpeg -i rtmp://example.com/live/stream -c copy -f hls -hls_time 10 \
-hls_list_size 0 -hls_flags independent_segments+delete_segments \
-hls_segment_filename "segment_%03d.ts" output.m3u8- -c copy preserves codecs for efficiency.
- -hls_time 10: segment length (seconds) recommended to align with keyframes.
- -hls_flags independent_segments ensures all segments start with a keyframe, improving compatibility across players."
- For HTTP FLV input, change the URL accordingly.
Segmenting Live Stream into HLS TS Files with FFmpeg
To support ABR (multiple variants for different bandwidths), encode separate streams with aligned keyframes. Use the following command to produce variants and a master playlist:
ffmpeg -i input.mp4 \
-map 0:0 -map 0:1 -map 0:0 -map 0:1 \
-s:v:0 1280x720 -c:v:0 libx264 -b:v:0 3000k -g 50 -keyint_min 50 -sc_threshold 0 \
-s:v:1 960x540 -c:v:1 libx264 -b:v:1 2000k -g 50 -keyint_min 50 -sc_threshold 0 \
-c:a:0 aac -b:a:0 128k -c:a:1 aac -b:a:1 96k \
-f hls -hls_time 6 -hls_playlist_type vod \
-master_pl_name master.m3u8 \
-hls_segment_filename "v%v/segment_%03d.ts" \
-var_stream_map "v:0,a:0 v:1,a:1" \
v%v/prog_index.m3u8- All video and audio variant streams must be keyframe-aligned (-g, -keyint_min, -sc_threshold 0), which ensures seamless switching."
- The master playlist (master.m3u8) is automatically generated, referencing each variant."
Manifest Finalization for VOD
After the live stream concludes, make sure the playlist meets VOD (Video on Demand) standards. To do this, use the -hls_playlist_type vod option, which automatically adds #EXT-X-PLAYLIST-TYPE:VOD and ensures all segments are included.
Properly finalizing the playlist requires adding #EXT-X-ENDLIST at the end to mark the playlist's conclusion. When using FFmpeg with the VOD playlist type and without any live flags, it will automatically insert this #EXT-X-ENDLIST tag to finalize the playlist correctly.
Example Command for Finishing mManifest Conversion:
ffmpeg -i archived_stream.mp4 -c copy -f hls -hls_time 10 -hls_playlist_type vod \
-hls_segment_filename "segment_%03d.ts" output_vod.m3u8Handling Discontinuities and Reliable Automation
Discontinuities can happen when restarting encoders, switching sources, or transitioning from live to VOD. FFmpeg automatically adds #EXT-X-DISCONTINUITY in the playlist when needed. However, for more control, custom automation or scripting may be required. This is especially important when combining non-continuous content or segments from different live sources. To monitor segment creation, tools like inotifywait or fswatch can be used, triggering new manifest updates as segments are generated.
After the stream ends, the manifest can be updated by running a new FFmpeg pass with all segments, or by programmatically adding #EXT-X-ENDLIST to mark the end of the playlist.
Sample Automation Script (Bash):
#!/bin/bash
INPUT="rtmp://example.com/live/stream"
OUTPUT_DIR="/path/to/hls"
FFMPEG_OPTS="-c copy -f hls -hls_time 10 -hls_list_size 0 \
-hls_flags independent_segments+append_list+delete_segments -hls_segment_filename \"$OUTPUT_DIR/segment_%03d.ts\""
ffmpeg -re -i "$INPUT" $FFMPEG_OPTS "$OUTPUT_DIR/live.m3u8"
# For VOD finalization, post-process with:
ffmpeg -f concat -safe 0 -i segment_list.txt -c copy -f hls -hls_playlist_type vod \
-hls_segment_filename "$OUTPUT_DIR/vod_segment_%03d.ts" "$OUTPUT_DIR/vod.m3u8"Always use -hls_flags independent_segments for HLS compliance and generate segment_list.txt programmatically, listing all TS files.
Confirming HLS Compliance
Verify that all playlists include: #EXT-X-PLAYLIST-TYPE:VOD, #EXT-X-ENDLIST (for Video on Demand). → Ensure master manifests enumerate bandwidth, codecs, and resolution per Apple's spec. → Check for keyframe alignment across ABR variants.

