A concat playlist is a plain-text file containing one media-file path per line. FFmpeg reads that list as one input, so you can join prerecorded clips and send them to YouTube Live without manually changing the command between videos.
For a continuous RTMP stream, you normally add real-time pacing and input looping to the concat input. That workflow is separate from YouTube's HLS workflow, which uses short transport-stream segments and a rolling media playlist rather than an FFmpeg file list.
What the FFmpeg concat playlist does
The concat demuxer reads several files in sequence and presents them to FFmpeg as one continuous input. It does not create a new combined video file first. FFmpeg processes the first clip, then the second, then the next one in the order written in the playlist.
That makes it useful for a devotional channel with a fixed bhajan rotation, a study channel with lessons and breaks, or a local information loop made from several recorded segments. You can rearrange the schedule by editing the text file rather than rebuilding a video.
The playlist controls order. It does not, by itself, control YouTube authentication, real-time pacing, reconnection, output encoding or stream health. Those are separate parts of the command and the overall operating setup.
The concat demuxer is also not the same thing as the concat filter. The demuxer is intended for files that already fit together at the stream level. The filter is the route to consider when you need to decode, transform and re-encode clips that do not match.
FFmpeg's documentation describes the required relationship plainly: all files must have the same streams, codecs and time bases for demuxer concatenation. Treat that as a preparation requirement, not as an optional optimisation. A text file with three filenames is not enough if the media underneath has conflicting properties.
Prepare clips and a stable directory
Start by putting the clips and the playlist in a directory that will remain available for the entire broadcast. For example:
/home/channel/stream/
├── clip-01.mp4
├── clip-02.mp4
├── clip-03.mp4
└── playlist.ffconcat
A stable directory matters because a long-running process should not depend on files being moved, renamed or disconnected from an external drive. It also makes relative paths predictable. If the process will be started by a scheduled task, service or script, use absolute paths in the playlist or confirm the process's working directory explicitly.
Use simple filenames while troubleshooting. Spaces and characters such as apostrophes, brackets and backslashes can be handled, but they introduce quoting rules that make the first test harder to read. Names such as morning-01.mp4 and evening-02.mp4 leave fewer opportunities for a shell or playlist parser to interpret part of the path incorrectly.
Before you build a long rotation, choose a small test set. Two or three clips are enough to reveal whether the order is correct, whether the second file starts, and whether the streams can be joined. Once that works, expand the playlist.
Keep a copy of the original media outside the working directory. If you need to convert a clip, do not overwrite the source until you have checked the converted version. This is particularly useful when your files contain valuable recordings, subtitles or carefully mixed audio.
If you are still preparing the YouTube channel itself, complete live-stream activation and check the current requirements in YouTube Studio first. The practical steps are separate from the FFmpeg playlist. For a channel being managed from a phone, the guide to turning on YouTube live streaming covers that part of the setup.
Write the ffconcat playlist file
Create a plain-text file named playlist.ffconcat. Its contents can be as small as this:
ffconcat version 1.0
file 'clip-01.mp4'
file 'clip-02.mp4'
file 'clip-03.mp4'
There is one file directive for each clip, and the order is the order FFmpeg will read. The optional header must be exactly ffconcat version 1.0 and must be the first bytes in the file if you want automatic ffconcat recognition. Do not place a blank line, extra whitespace or a byte-order mark before it.
A basic relative-path playlist works when the playlist and media files are in the same directory and FFmpeg is started with the expected working directory. For a process that may be launched elsewhere, absolute paths are clearer:
ffconcat version 1.0
file '/home/channel/stream/clip-01.mp4'
file '/home/channel/stream/clip-02.mp4'
file '/home/channel/stream/clip-03.mp4'
Paths containing spaces need quoting. The concat documentation also defines escaping for special characters, so check the FFmpeg concat demuxer documentation when a filename contains an apostrophe or another character that has meaning to the parser.
You can use a file named playlist.txt, but then it is sensible to force the input format in the command with -f concat. Using the .ffconcat extension and the exact header helps FFmpeg recognise the intended format. Explicitly specifying -f concat is still useful when you want the command to be unambiguous.
Do not put comments, shell commands or YouTube settings in this file. It is a media input script, not a general-purpose schedule. The stream key belongs in the output URL or a protected environment variable, never in the playlist.
For an occasional change, stop the process, edit the list, save it and start again. Do not assume that a running FFmpeg process will re-read a playlist after you edit it. If you need to update a rotation during a broadcast, plan that as a controlled restart and check how your YouTube event is configured before doing it.
Check file paths and clip compatibility
Test the playlist before connecting it to YouTube. A local read lets you separate playlist errors from network, account and ingestion errors. A simple diagnostic command is:
ffmpeg -f concat -safe 0 -i playlist.ffconcat -f null -
This asks FFmpeg to read the playlist and discard the output. It does not prove that YouTube will accept the eventual stream, but it can expose a missing file, a malformed directive, an unreadable container or a failure when FFmpeg moves from one clip to the next.
The -safe 0 option permits paths that FFmpeg's safe-path rules would otherwise reject, particularly absolute paths. Use it only when you control the playlist and its contents. It does not repair a bad path.
Check each file individually if the combined test stops at a particular clip:
ffmpeg -i clip-01.mp4 -f null -
ffmpeg -i clip-02.mp4 -f null -
ffmpeg -i clip-03.mp4 -f null -
Look for the following properties across the set:
| Property | Why it matters | What to do when it differs |
|---|---|---|
| Video stream | The demuxer expects a consistent stream layout | Convert the clips to a common format or use a concat-filter and re-encode path |
| Video codec | Streamcopy cannot make different codecs identical | Re-encode before joining, or encode the final output |
| Audio stream | A missing or differently structured audio stream can disrupt the join | Add or normalise audio during preparation |
| Time base and timestamps | Later clips depend on reported timing | Inspect timestamps and remux or re-encode suspect files |
| Duration metadata | Incorrect duration can shift the next clip's timeline | Repair the file or add a duration directive where appropriate |
| Dimensions and frame properties | Output may not remain consistent | Scale and convert during preparation or final encoding |
The concat demuxer joins packet timelines using the durations reported by the files. If a file is truncated or its duration metadata is inaccurate, the next clip may begin at an unexpected timestamp. You may see a pause, an overlap, corrupted frames or an audio/video timing problem rather than a clean transition.
Where the duration cannot be read or is known to be wrong, the concat syntax supports a duration directive after the relevant file entry. For example:
ffconcat version 1.0
file 'intro.mp4'
duration 12.5
file 'main.mp4'
Use a value based on the actual media, not a guess chosen to hide an error. If the underlying file is damaged, correcting the playlist's duration may not be enough. Rebuild or convert the file and test it separately.
If your clips need a logo, crop, colour adjustment, overlay, scaling or audio mixing, -c copy is not the right tool for that operation. Streamcopy copies encoded packets without decoding them, so it cannot apply filters. FFmpeg's streamcopy documentation and concat FAQ explain why the filter-and-re-encode route is needed for these cases.
Loop and pace input for a continuous stream
Once the playlist works locally, a typical RTMP-style starting command is:
ffmpeg -re -stream_loop -1 -f concat -safe 0 -i playlist.ffconcat \
-c copy -f flv 'rtmp://SERVER/STREAM_KEY'
Replace rtmp://SERVER/STREAM_KEY with the ingestion URL and stream key shown for your YouTube broadcast. Keep the key private. Do not paste it into a public tutorial, screenshot, issue report or shared log.
Each option has a separate job:
-reasks FFmpeg to read a file input at approximately its native rate rather than consuming it as quickly as the computer can process it. This is the pacing part of the command.-stream_loop -1asks FFmpeg to repeat the input indefinitely. This is the looping part.-f concatselects the concat demuxer explicitly.-safe 0allows the paths used by the playlist, including controlled absolute paths.-i playlist.ffconcatsupplies the playlist as the input.-c copyrequests streamcopy rather than decoding and re-encoding.-f flvselects the container commonly used for an RTMP output.
Looping and pacing solve different problems. Without pacing, a file-based input may be read faster than real time, which is unsuitable for a live endpoint. Without looping, FFmpeg reaches the end of the final playlist entry and exits. Adding both does not guarantee a gapless transition. The files' timestamps, duration metadata and compatibility still affect what happens at each boundary.
The example uses streamcopy because it avoids unnecessary processing when the clips already match and the output accepts their streams. It is not a universal YouTube command. If the output reports codec, timestamp, pixel-format or audio problems, try a prepared set of matching files or change to an explicit encoding command.
For example, an encoding path might look like this in principle:
ffmpeg -re -stream_loop -1 -f concat -safe 0 -i playlist.ffconcat \
-c:v libx264 -c:a aac -f flv 'rtmp://SERVER/STREAM_KEY'
This is not a complete quality or bitrate recommendation. Encoding settings depend on your source dimensions, frame rate, audio, computer and current YouTube requirements. It does show the important distinction: the media is decoded and encoded instead of being copied unchanged. The FFmpeg settings guide for looping educational videos on YouTube Live is useful when you need to work through those output choices.
Run the command in a terminal where you can see warnings. Save the console output privately if you need to diagnose a stop. A failure near the end of the playlist may indicate a duration or compatibility issue rather than a problem with the first clip.
A local computer must remain powered, connected and able to keep the process running for the intended schedule. StreamNeo removes the need to leave that computer running by taking an uploaded video, the YouTube stream key and the continuous broadcast operation into one cloud-based workflow, with monitoring and automatic restart when the broadcast drops; it does not run arbitrary FFmpeg commands for you.
Send the stream to YouTube over RTMP
Create or open the live event in YouTube Studio and copy the current server URL and stream key shown there. YouTube's interface and eligibility requirements can change, so use the values displayed for your account rather than copying an old URL from a forum post.
Paste the key into a protected script or environment variable rather than placing it directly in a command that will be shared. On a multi-user machine, also consider who can read shell history and process listings. If the key is exposed, use YouTube Studio's controls to manage or replace it according to the current account interface.
Start with a short private or unlisted test if that suits your channel. Watch for three separate signals:
- FFmpeg should continue reading files and show output progress rather than reaching end of input.
- YouTube Studio should receive the broadcast and show an input preview or health information.
- The actual playback should move from one clip to the next with usable audio and video.
If FFmpeg runs but YouTube does not receive the stream, check the output URL, key, network connection and YouTube event state. If YouTube receives the stream but reports an encoding or format warning, inspect the media streams and consider re-encoding. If the first clip plays but the next one fails, return to the compatibility and duration checks rather than changing the RTMP URL.
RTMP is only the transport in this example. It does not create a schedule, repair a broken source file or tell YouTube how to rebuild a missing segment. If the process stops, the broadcast may stop as well unless you have separately arranged a restart and checked the consequences for your YouTube event. A restart and recovery plan for a 24/7 YouTube stream is worth preparing before you rely on the setup overnight.
Do not describe the result as guaranteed 24/7 uptime. The process depends on the host computer, power, network, FFmpeg process, source files, stream key, YouTube account and current ingestion behaviour. If you want to understand the limits of uptime claims, see what can and cannot be promised on a 24/7 stream.
How the HLS workflow differs
An FFmpeg concat playlist is an input list. It is not a YouTube HLS media playlist. Do not take the playlist.ffconcat file from the RTMP example and upload or POST it as though it were an HLS output playlist.
YouTube's official HLS streaming instructions describe a different workflow. The encoder produces short MPEG transport-stream segments and maintains a rolling media playlist. The segments and playlist are sent using the current HTTPS method and URL supplied by YouTube, with requirements for segment duration and the number of outstanding segments.
The HLS output therefore has its own concerns: segment creation, segment naming, playlist updates, HTTPS delivery, codec support and latency. The official YouTube page states that HLS has higher latency than RTMP. Those requirements do not come from the concat demuxer, and an RTMP command does not configure HLS.
You can still use a concat demuxer upstream of an HLS encoder if your overall FFmpeg design requires it, but the output side must follow YouTube's current HLS instructions. In other words, the input playlist and the delivery protocol are two separate layers:
| Layer | RTMP example | HLS example |
|---|---|---|
| Input selection | FFmpeg concat demuxer | Could also use a concat demuxer, if the files fit |
| Timing | Real-time pacing with -re for file input |
Segment production and playlist timing |
| Output | FLV-style RTMP publishing | TS segments and a rolling media playlist |
| Delivery | YouTube ingestion URL and stream key | YouTube's current HTTPS HLS endpoint and requirements |
| Latency | Usually the lower-latency branch of these two workflows | Higher latency, as stated in YouTube's guidance |
Choose the branch based on what YouTube and your encoder setup require. If your goal is simply to send a prepared rotation of compatible prerecorded videos to a normal YouTube Live ingestion point, the RTMP-style command is the more direct place to begin. If you specifically need HLS, read the current official instructions from the start rather than adapting only the last line of an RTMP command.
Before committing, compare the operating options on the pricing page. When the file and channel are ready, start free — 24-hour trial, no card.
FAQ
Can I put any MP4 files into the concat playlist?
No. The concat demuxer expects compatible streams, codecs and time bases, and it relies on the files' reported timing. Prepare matching files first, or use a concat-filter and re-encode when the clips need conversion, scaling, filtering or audio changes.
Why does FFmpeg stop after the last clip?
A playlist ends when its final file entry ends. For a repeating input, add -stream_loop -1 in the appropriate position for your installed FFmpeg and test the command locally before sending it to YouTube. Also check that FFmpeg is not stopping because the final file is damaged or has incorrect duration metadata.
Does -re make the stream continuous?
No. -re controls the reading pace of a file input so it is processed around real time. It does not loop the playlist, repair timestamps, reconnect a failed process or guarantee uninterrupted transitions.
Can I use the same playlist for YouTube HLS?
You can use a concat demuxer as an input in a larger HLS design, but the .ffconcat file itself is not an HLS media playlist. HLS needs its own segmented output, rolling playlist and delivery method, so follow YouTube's current HLS documentation rather than applying the RTMP command unchanged.