To run a 24/7 YouTube playlist with FFmpeg, put compatible clips in a concat-demuxer manifest, loop that input and send the resulting stream to YouTube Live. The important decision comes first: the demuxer joins packets; it does not make mismatched files compatible. If your clips differ in streams, codecs or time bases, normalise them before relying on an unattended broadcast.
This guide shows how to choose between packet-level concatenation and preprocessing, build and check a manifest, loop it, and test the result. The command is a starting point, not a guarantee that every FFmpeg build or set of files will behave identically.
Choose packet concatenation or normalisation
The concat demuxer is useful when your clips already share a compatible media structure and you want to avoid re-encoding them before streaming. It reads a text list of files and presents their packets as a single input, adjusting timestamps so that each listed file follows the one before it. That is different from joining arbitrary videos and converting them on the fly: the demuxer does not reconcile incompatible codecs, missing audio, different layouts or other mismatches.
Start by checking the clips rather than by constructing a long-running command. If they have the same streams, codecs and time bases, test packet-level concatenation. If they differ, preprocess them into a common profile or use a filter-based concat workflow that converts the inputs as needed. FFmpeg describes the demuxer as appropriate when avoiding re-encoding and the concat filter as the route when re-encoding is needed; see its concat documentation and FAQ.
For a devotional channel, for example, one clip might contain stereo audio and another might have no audio stream. They are not interchangeable just because both are MP4 files. A lofi playlist can have a similar hidden problem if its clips use different frame rates or audio parameters. Fixing those differences before the broadcast is generally easier to diagnose than discovering them at a transition hours later.
The choice also affects what work happens on the streaming machine. Copying compatible packets is less demanding than encoding every frame, but leaves less room to change properties in the live command. Normalising clips takes preparation and can reduce or alter source quality depending on the chosen settings, but gives the playlist a consistent basis. For a deeper look at output sizing and bitrate, see the FFmpeg bitrate and resolution guide.
Check whether the files are compatible
FFmpeg’s demuxer documentation says that the files need the same streams, including matching codecs and time bases. In practice, inspect more than filenames or container extensions: check whether each has video and audio, and compare codec, resolution, frame rate, pixel format, sample rate, channel layout and stream time bases. Differences in those properties can cause the join to fail or produce an unwanted transition; identical extensions alone tell you very little.
Use ffprobe to inspect each clip before making the manifest part of a live process. A concise inspection command is:
ffprobe -v error -show_streams -show_format clip-01.mp4
Compare the output for each file, especially the codec_name, time_base, width, height, pix_fmt, r_frame_rate, audio sample_rate and channel_layout fields where present. The fields available and their presentation can vary by file and FFmpeg version. Treat this as a comparison aid rather than an automatic pass/fail test: inspect any missing stream or difference and decide whether your intended output can handle it.
Unequal clip lengths deserve attention too. The demuxer uses file durations to position packets. If a duration is inaccurate, timestamps can be wrong; if audio and video end at different points, a gap or discontinuity may appear. A black tail on one source or a short silent ending may be intentional, but it will still be present in the output unless you edit or normalise it.
If a clip fails the compatibility check, make a consistent set before streaming. Choose a common resolution, frame rate, video codec and pixel format, plus a common audio codec, sample rate and channel layout if audio is used. Keep an original copy so you can return to it if your chosen conversion causes quality or sync problems. Do not assume one universal profile fits every channel: an animated study loop, a fixed-camera shop display and a music-led bhajan stream have different source material and output priorities.
A filter-based concat is another way to bring inputs with differences together while explicitly converting properties. It is more involved than a manifest and can be harder to operate as an endless live input. For a static playlist, normalising clips beforehand makes each file independently testable and keeps the live command simpler. FFmpeg’s concat filter documentation explains the filter approach; check its options against the FFmpeg build you actually have.
Build the concat manifest
Create a plain-text file such as playlist.txt, with one file directive for each clip in the order you want viewers to see them:
file 'clip-01.mp4'
file 'clip-02.mp4'
file 'clip-03.mp4'
Save the manifest in a working directory with the media, or use paths that resolve correctly from the process’s working directory. Relative paths make a folder easier to move as a unit, but test them from the same location and under the same account that will run FFmpeg. A file that your desktop user can open may not be available to a scheduled task or service account.
Paths with spaces or special characters need to be quoted or escaped in a way the manifest parser accepts. Start with simple names such as clip-01.mp4 if you can; they reduce avoidable path mistakes. FFmpeg’s safe-path handling rejects paths it considers unsafe by default. The example command below uses -safe 0 to allow other path forms, but only use that with a manifest and paths you trust. Do not accept an untrusted manifest into a process that permits unrestricted paths.
Before looping, run a short test against the manifest and listen or watch through every transition. A typo or missing file is easier to fix while the playlist is not yet attached to a public live event. If a clip has been replaced, confirm the manifest points to the intended file and that the replacement still passes your compatibility checks.
A manifest controls sequence, not variety or rights. If a three-clip list repeats, it repeats in that order; it does not shuffle or remove repeated items. For visual planning, the guide to 24/7 aquarium and relaxation loops covers considerations that apply to long-running ambience, while the actual ordering here is explicit in your file list.
Understand how the demuxer joins packets
A useful mental model is that the demuxer reads the packets in one file, then the next, and adjusts timestamps to place the later file after the earlier one. It is not a video editor and it does not blend the end of one clip into the beginning of another. Unless the source footage itself contains a fade or an overlap built into the clip, viewers should expect a cut at the boundary.
That distinction explains why matching media structure matters. With compatible inputs, packets can be passed through in sequence without a new encode. When stream properties do not match, the demuxer cannot quietly convert them into one consistent video signal. Different stream counts or codec parameters can cause errors, while differing durations can create awkward timestamp positions. A successful command start is not evidence that all later boundaries will be clean.
Think of the playlist in two layers. The manifest answers “what comes next?” The media profile answers “can those packets follow one another in this input?” Neither layer determines whether YouTube accepts the output encoder settings, whether your connection can sustain them, or whether a process recovers after a crash. Those are separate checks later in the workflow.
If your audience expects a continuous sound bed, listen specifically for pauses, pops or changes in loudness at each boundary. For a local news loop, check that captions or graphics do not depend on state that disappears at a cut. A clean packet join can still expose an editorial flaw that was difficult to notice when the clips were reviewed separately.
Loop the ordered input
FFmpeg’s -stream_loop -1 option requests infinite input looping. Put it among the options for the concat input, before -i playlist.txt, so the playlist input is the one being repeated. In a typical command, -re also appears before that input to read prerecorded media at its native rate rather than consume it as fast as possible.
ffmpeg -re -stream_loop -1 -f concat -safe 0 -i playlist.txt \
-c:v libx264 -preset veryfast -b:v 5000k -maxrate 5000k -bufsize 10000k \
-pix_fmt yuv420p -g 60 -c:a aac -b:a 128k -ar 44100 \
-f flv 'rtmp://SERVER/STREAM/KEY'
This illustrates the shape of a workflow; it is not proven for every source, encoder build or YouTube setup. Replace the destination with the ingest URL and stream key shown in your YouTube Live Control Room, keep the key secret, and confirm your FFmpeg build includes the encoders named. If an option is unavailable or behaves differently, check the local FFmpeg help and the documentation for that build.
-stream_loop -1 repeats the entire ordered manifest, not a single file chosen at random. When the last listed clip ends, the input returns to the first clip. It does not insert a transition or repair a bad boundary between the final and first files. Test that wraparound transition as carefully as transitions within the list.
For channels that need occasional programme changes, the manifest is not a scheduling system. You need a planned way to stop or replace the process and verify what is on air after changes. If the goal is to swap content without interrupting an existing broadcast, compare that requirement with the practical limits discussed in whether a YouTube stream can keep running while a video is replaced.
Encode or copy for YouTube ingest
The example encodes video as H.264 and audio as AAC, then writes an FLV output to an RTMP-style destination. Encoding is useful when the input needs a defined output profile or the selected source codec is not what you intend to send. It consumes processing capacity and introduces another opportunity for configuration or quality problems. If the files already match the target and you understand their codec parameters, stream copy may avoid re-encoding, but it does not make incompatible inputs compatible.
YouTube’s current encoder guidance recommends RTMP or RTMPS, constant bitrate (CBR), and a keyframe interval of two seconds, not exceeding four seconds. Select codec, resolution, frame rate and bitrate consistently, using the row that matches your chosen format in the YouTube Live encoder settings. YouTube recommends RTMPS for encrypted transport. The sample’s bitrate values are illustrative, not a general recommendation; do not copy them without checking the current official settings for your resolution and frame rate.
The -g value is a number of frames, so its time interval depends on frame rate. For example, 60 frames at 30 frames per second corresponds to two seconds. If you change frame rate, recalculate the GOP length rather than carrying the same number over automatically. Also check that rate-control settings match the intended CBR behaviour in your chosen encoder and FFmpeg build.
There is a trade-off between letting YouTube detect the incoming format and choosing a custom output profile. YouTube says automatic resolution and frame-rate detection is the default, while a custom stream key allows manual settings. Match your choice to what the source can produce consistently; a nominal target that your encoder cannot sustain is not useful. For a dedicated playlist stream, see the YouTube bitrate settings for an ambient 24/7 stream for related channel-specific considerations, then verify the current official table.
On the sending machine, measure available upload capacity while the actual stream is running, not only the speed quoted in a broadband plan. YouTube’s streaming tips recommend leaving 20% headroom above the total outgoing bitrate. If other devices share the connection, their traffic can reduce that margin. A remote host or cloud-based process has its own network path to check, separate from your home broadband.
Test timestamps, transitions and recovery
Test the whole ordered playlist locally before publishing. Watch or listen across each boundary, including the last-to-first wrap. Check for black frames, frozen video, silence, repeated frames, audio clicks, sync drift and FFmpeg warnings. If a problem appears at one particular clip, remove it from the live test and inspect its streams and duration rather than assuming the whole manifest is broken.
Next, create an unlisted YouTube test and monitor stream health and warning messages in Live Control Room. YouTube recommends a test that includes both audio and video movement. A static picture with no audio may hide a problem that viewers will notice in the actual programme. Confirm that the output resolution, frame rate and ingest status are what you intended before making the event public.
Plan for failure separately from playlist looping. The loop option repeats input during one running FFmpeg process; it does not restart that process if it exits, nor does it resolve a host restart or loss of network. For an unattended installation, use process supervision outside FFmpeg and verify that it can relaunch the command after an actual controlled stop. The guide to restarting a 24/7 YouTube stream after a disconnect covers that separate operational problem.
Decide whether one continuous live event or archive availability matters more. YouTube says a stream longer than 12 hours may not be captured at all, while eligible streams under that duration can be automatically archived. That means an always-on feed and a reliably available archive are separate operating concerns. If the footage matters, YouTube recommends keeping a local recording backup; consult the current YouTube live-stream archive guidance before choosing how to handle long sessions.
Keep a record of the working command, manifest, output profile and test observations. Do not put the stream key into a public script or shared document. If you change a clip, FFmpeg build, encoder setting, connection or host, rerun the relevant transition and ingest checks: an earlier successful test only covered the files and conditions used in that test.
For a long-running playlist, the process also needs attention when nobody is at the keyboard. If keeping a computer on and recovering the command after interruptions becomes the difficult part, StreamNeo removes that specific burden by running an uploaded video as a YouTube live stream without your computer left on. It is YouTube-only; you still need to prepare your content and check that the channel and stream are ready.
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 the concat demuxer join any MP4 files?
No. An MP4 extension does not establish that the files have matching streams, codecs or time bases. Inspect the media first, and normalise or use a filter-based workflow when the inputs differ.
Does -stream_loop -1 make the stream run by itself forever?
It asks FFmpeg to repeat the playlist input indefinitely while that process is running. It does not restart FFmpeg after a crash, restore a lost network connection or ensure an archive is created. Treat looping, supervision and archive planning as separate tasks.
Should I use -c copy or encode the playlist?
Use stream copy only when the files are compatible with one another and with the output you intend to send. Encoding can produce a consistent output profile, but requires processing capacity and does not make a poorly checked source harmless. Test the complete playlist, including the wraparound point, before relying on either route.
Will the example command work unchanged on my machine?
Not necessarily. Encoder availability, FFmpeg version, input properties, frame rate, output settings and YouTube’s current recommendations all matter. Treat it as a starting pattern, use the current official ingest guidance, and verify the result in an unlisted test.