Create Non-Seekable Live Stream from MP4 with FFmpeg
This article explains how to use FFmpeg to stream static MP4 video files as a continuous, non-seekable live broadcast. You will learn how to set up a playlist of MP4 files, stream them at real-time speed, and configure an HLS (HTTP Live Streaming) output that restricts viewers from rewinding or seeking through the video playback.
To simulate a true live broadcast using static MP4 files, you must stream the files in real-time and package them into a rolling live playlist. This prevents the media player from knowing the total duration of the stream and limits the available playback window to only the most recent few seconds.
Step 1: Create an Input Playlist
To stream multiple MP4 files sequentially, create a text file named
playlist.txt. List the paths to your MP4 files in the order
you want them to play:
file 'video1.mp4'
file 'video2.mp4'
file 'video3.mp4'
If you want the stream to loop infinitely, you can add loop instructions to the FFmpeg command later.
Step 2: Run the FFmpeg Live Stream Command
Execute the following FFmpeg command to read the playlist, process the files in real-time, and output a live, non-seekable HLS stream:
ffmpeg -re -f concat -safe 0 -i playlist.txt \
-c:v libx264 -preset veryfast -g 48 -sc_threshold 0 \
-c:a aac -b:a 128k \
-f hls -hls_time 4 -hls_list_size 5 -hls_flags delete_segments \
output.m3u8Command Breakdown
-re: This flag forces FFmpeg to read the input files at their native frame rate (real-time). Without this, FFmpeg will process the files as fast as possible, which will break the live stream.-f concat -safe 0 -i playlist.txt: This uses the concatenation demuxer to stream the MP4 files listed in your text file seamlessly back-to-back.-g 48 -sc_threshold 0: Forces a keyframe (I-frame) every 48 frames (2 seconds for a 24fps video). Regular keyframes are required for clean segment cutting in live HLS.-f hls: Specifies the output format as HTTP Live Streaming (HLS).-hls_time 4: Sets the target segment length to 4 seconds.-hls_list_size 5: Limits the HLS manifest (output.m3u8) to only list the 5 most recent segments.-hls_flags delete_segments: Automatically deletes older segment files from the server’s storage as new ones are created.
How this Prevents Seeking
By setting -hls_list_size 5 and deleting older segments,
the player only ever has access to approximately 20 seconds of video at
any given time. Because the HLS manifest does not contain an
#EXT-X-ENDLIST tag, player software (such as Video.js,
ExoPlayer, or Safari’s native player) recognizes the stream as a live
broadcast with no DVR history. The seeker bar on the player will be
locked to the “Live” position, making it impossible for the viewer to
rewind or fast-forward.