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.m3u8

Command 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.