The reliable way to loop a playlist with FFmpeg is to put the clips in a concat demuxer text file, read that file with -stream_loop -1, and use -re so file input is paced at live speed. That command only works cleanly when the clips have compatible streams and timestamps, so stream copying should be treated as a compatibility choice, not a universal setting.
Start with a short local test rather than sending an unverified playlist straight to YouTube. Check the video and audio properties, test every boundary, and choose between -c copy and re-encoding only after you know what the files require.
Build the playlist script
The concat demuxer reads a plain text script in the order you provide. Create a file such as playlist.txt in a working folder and add one file line for each clip:
file 'clip1.mp4'
file 'clip2.mp4'
file 'clip3.mp4'
The order is explicit. If clip1.mp4 is a morning prayer, clip2.mp4 is a music bed, and clip3.mp4 is an information card, that is the order FFmpeg will present them. The playlist is not a folder scan, so adding a new video to the directory does not automatically add it to the stream.
For a playlist in another directory, use relative or absolute paths according to the safety rules explained below. Keeping the script and media in a simple working directory makes early testing easier. It also makes it less likely that a renamed file, a moved folder, or a typographical error will appear only after the stream has already started.
A basic RTMP-style command looks like this:
ffmpeg -re -stream_loop -1 -f concat -safe 0 -i playlist.txt -c copy -f flv 'rtmp://a.rtmp.youtube.com/live2/YOUR-STREAM-KEY'
Here, -f concat selects the concat demuxer, -i playlist.txt supplies the script, and -stream_loop -1 repeats that input indefinitely. FFmpeg documents -1 as infinite looping in its command-line documentation. The output URL and stream key must come from your YouTube Live setup. Keep the key private, including when sharing a command in a support forum.
This is a pattern rather than a promise that every playlist will work with -c copy. The copy option avoids re-encoding, but it does not turn different codecs, dimensions, frame rates, time bases, or audio layouts into one uniform output. If the files are not suitable for the concat demuxer, use a preparation or re-encoding workflow instead.
Put the ffconcat header in the right place
The playlist can begin with the optional format header:
ffconcat version 1.0
file 'clip1.mp4'
file 'clip2.mp4'
file 'clip3.mp4'
When you use it, the first line must be exactly ffconcat version 1.0. It must be at the very beginning of the file, without leading spaces and without a byte-order mark. A byte-order mark can be inserted by some text editors and may prevent automatic recognition of the script format.
The header is not a command-line flag and does not belong inside a file entry. It tells FFmpeg which concat script format the text follows. If you omit it, a simple list may still be recognised when you explicitly use -f concat, but the documented header is useful when you want the file format to be unambiguous.
Save the file as plain text. Avoid rich-text editors that add formatting, quotation marks, hidden characters, or a different line ending arrangement. If FFmpeg reports that it cannot parse the script, inspect the first line before changing the streaming command. A malformed header can look like a media problem even though FFmpeg has not reached the clips yet.
The relevant rules are in the FFmpeg Project's concat demuxer documentation. Keep that reference available when you need directives beyond a basic ordered list, especially if stored duration information is inaccurate.
Quote and escape paths safely
Each playlist entry contains a path after the file directive. Quoting paths is important when names contain spaces or characters that have meaning in the concat script. For example:
file 'Morning Prayer 01.mp4'
file 'city-news-2026-10-04.mp4'
A single quote inside a path needs the concat script's escaping treatment rather than being left unescaped. The exact grammar is documented by FFmpeg, so do not assume that shell quoting rules and concat-file quoting rules are identical. The playlist is parsed by FFmpeg after your shell has already started the program, which means there are two separate places where characters can be interpreted.
On a Unix-like system, the shell quoting around 'playlist.txt' protects the input filename passed to FFmpeg. The quotes inside the playlist protect each media path from the concat demuxer. On Windows, a path such as C:\media\clip.mp4 may need a different arrangement from a Unix path, and backslashes can have meaning in the script. Test one file first and follow the path syntax in the demuxer documentation rather than copying a shell example unchanged.
The -safe option is a separate concern. With its default safety setting, the concat demuxer accepts only safe paths, which are generally relative paths using a restricted portable character set. -safe 0 permits paths outside that default. It is appropriate only when you control the playlist and every path it contains. It should not be used to make an untrusted playlist acceptable.
A practical approach is to start with simple relative names:
ffconcat version 1.0
file 'clip1.mp4'
file 'clip2.mp4'
Once that works, add folders or spaces one change at a time. If you use -safe 0, review the final text file manually before launching FFmpeg. A path that points to the wrong file can produce a technically valid stream containing the wrong content.
Check compatibility before choosing stream copy
The most important decision is whether the files can be presented as one compatible sequence without re-encoding. The concat demuxer expects the listed files to have the same streams, including matching codecs and time bases. In practice, inspect more than just the filename extension.
Check the following for every clip:
| Property | Why it matters | What to do if it differs |
|---|---|---|
| Video codec | Stream copy does not convert codecs | Normalise or re-encode the video |
| Audio codec | Each audio stream must fit the output sequence | Normalise or re-encode the audio |
| Frame dimensions | Different widths or heights do not become equal through copying | Prepare files at one size |
| Frame rate and timing | Uneven timing can affect playback at boundaries | Inspect timestamps and test transitions |
| Audio channel layout and sample characteristics | A changing audio layout can create an incompatible sequence | Prepare a consistent audio format |
| Stream presence and order | A clip with no audio, or a different stream layout, changes the sequence | Add or remove streams during preparation |
| Duration metadata | Incorrect duration can shift later timestamps | Verify the file or use a documented duration override where appropriate |
You can inspect a file with ffprobe, which is distributed with FFmpeg. For example:
ffprobe -v error -show_entries stream=index,codec_name,codec_type,width,height,r_frame_rate,time_base,channels,sample_rate -of json 'clip1.mp4'
Run an equivalent check on each input and compare the results. The exact output depends on the files, so there is no single set of values that can be declared safe for every YouTube channel. A devotional channel might have several MP4 clips that look alike but contain different audio layouts. A local news loop might mix an older export with a newer file using a different frame size. The filenames will not reveal those differences.
The -c copy setting is efficient when the streams really are compatible because FFmpeg passes the encoded streams through instead of decoding and encoding them again. It does not repair a codec mismatch, resize a frame, create missing audio, or correct all timestamp problems. It can also expose a boundary problem only after the first clip has ended.
When the files need conversion, prepare a consistent set before streaming or use FFmpeg's concat filter with the required re-encoding. The FFmpeg Project explains in its FAQ that the concat demuxer is useful when you want to avoid re-encoding and the format does not support file-level concatenation, while the concat filter is the route when re-encoding is needed. That distinction is more useful than treating -c copy as a default that must be forced to work.
Choose a preparation path when files differ
There are three sensible paths, depending on what your inspection shows.
First, use stream copy when the files already have the same relevant stream structure and your boundary test is clean. This keeps the process light, but the output remains dependent on the source files' timing and encoding details.
Second, make a normalised set before building the playlist. Re-export each clip with the same frame dimensions, video codec, frame rate, audio codec, channel layout, and general timing. The settings should match the needs of your channel and the ingestion configuration you choose. A normalised set is often easier to reason about overnight than a collection of files gathered from different editors.
Third, use the concat filter when you need FFmpeg to decode and re-encode the material into one consistent output. This gives you control over scaling, frame rate, audio format, and other properties, but it requires more processing and introduces another encoding stage. It is not automatically better; it is the appropriate trade-off when the source files cannot be joined safely by the demuxer.
Do not confuse a successful command start with a successful playlist. FFmpeg may open the first clip correctly and still stop, show a timestamp warning, or produce an audible or visible fault when it reaches the next file. The first boundary is a test condition, not proof that the whole sequence is compatible.
If you are deciding between software workflows, the practical differences are set out in OBS versus FFmpeg for looping videos on YouTube Live. FFmpeg is well suited to a repeatable command-line playlist, while a graphical workflow may be easier when you need to preview sources and change scenes manually.
Loop the sequence and send it at live speed
For local files, -re is the setting that makes the input behave like a real-time source rather than being read as quickly as the computer can process it. FFmpeg describes it as equivalent to -readrate 1. Place it before the input so it applies to the file input:
ffmpeg -re -stream_loop -1 -f concat -safe 0 -i playlist.txt -c copy -f flv 'rtmp://a.rtmp.youtube.com/live2/YOUR-STREAM-KEY'
-stream_loop -1 repeats the concat input indefinitely. -re paces the file input at its native frame rate. Together, they address two different problems: one controls repetition, and the other controls reading speed.
Do not apply file-style real-time pacing blindly to a live capture or network input. FFmpeg's command-line reference warns that using low read rates on inputs that are already live can cause packet loss. The command above is for a playlist made from files, not a universal rule for every source type.
The -f flv output format belongs to this RTMP-style example. YouTube's output URL and stream key come from your live configuration, and you should confirm the current ingestion details in YouTube Live Control Room. HLS is a different workflow. YouTube's HLS streaming guidance describes HLS-specific segment, playlist, request, and latency requirements; those are not concat-demuxer settings to insert into an RTMP command.
You may find that a stream appears to run faster than live speed when -re is omitted, especially with short files. That is not a valid overnight test because the process can consume the playlist faster than YouTube can handle it or reach the end of a sequence much sooner than expected. Conversely, if the machine cannot process a re-encoded output in real time, adding -re cannot solve the processing load. It only controls input pacing.
A local FFmpeg process also leaves you responsible for the computer, network connection, process supervision, and recovery after a failure. If the practical problem is keeping a prepared file and YouTube channel running while your own computer is switched off, StreamNeo removes that particular routine by accepting the file and stream key once, then handling the continuous broadcast and restart monitoring as part of its hosted workflow. You still need to check your content and YouTube settings, and it is YouTube-only.
Test every boundary before going live
Make a short test playlist with at least two clips and place it on a loop. Choose clips whose transitions represent the real channel: a quiet devotional video followed by a louder one, a news card followed by footage, or a study lesson followed by an interval screen. A test made only from identical files can hide the fault you will encounter overnight.
Watch the end of each clip and the beginning of the next. Check for:
- a frozen final frame or a flash of black
- a missing or delayed first frame
- a click, silence, doubled audio, or sudden volume change
- a change in aspect ratio or visible scaling
- a timestamp warning in the FFmpeg log
- a short pause before the next file starts
- FFmpeg stopping when the playlist returns to its first entry
Let the test pass through the last file and return to the first. The loop boundary matters as much as the clip-to-clip boundaries because the concat input is being opened again through the loop mechanism. If you use stream copy, repeat the test after replacing one clip with every different source type you plan to use.
Read the log while the test runs. Warnings about non-monotonic timestamps, invalid duration, missing streams, or failed packet processing deserve investigation before deployment. Do not silence warnings simply because the YouTube preview appears to move. A platform preview can conceal a brief transition fault that a viewer hears clearly.
Duration information deserves special attention. The concat demuxer uses the duration of one file when calculating the timestamps for the next. If a file contains inaccurate duration metadata, later material can be shifted. The FFmpeg documentation describes a duration directive for overriding stored duration when appropriate, but it should be used because you have measured or otherwise verified the duration, not as a generic fix.
If the stream stops after an error, note which file was being read and test that file separately. Then test the pair around the boundary. This narrows the problem more effectively than changing several command options at once. Keep a known-good copy of the playlist so that an experiment with paths or directives does not become the new production file by accident.
For problems that appear as buffering rather than a clean FFmpeg error, the guidance on fixing buffering in an FFmpeg YouTube loop covers a different class of diagnosis, including the distinction between input, processing, and network symptoms.
Prepare the overnight run
Once the files pass boundary tests, make the production folder deliberately boring. Use stable filenames, keep the playlist under version control or make dated backups, and avoid editing the active file while FFmpeg is reading it. If you need to change the order, prepare a new file, test it, and restart or switch at a planned point.
Keep the stream key out of scripts that will be uploaded publicly. Use file permissions and environment-specific storage appropriate to your operating system. A leaked key can allow someone else to broadcast to your channel until you revoke or replace it through YouTube.
Record which command was tested, which files were included, and whether the output used copy or re-encoding. When a viewer reports a problem at a particular time, that record helps you identify the clip and boundary instead of guessing. For a machine that runs FFmpeg continuously, also plan how you will restart the process after a crash or maintenance event. The practical recovery steps are separate from playlist syntax, but they determine whether a technically correct command survives an unattended night.
Do not assume an old setup remains valid after changing FFmpeg, the operating system, a media export, or the YouTube live configuration. Re-run a short boundary test after those changes. If you are maintaining FFmpeg on a VPS, the guide to updating FFmpeg without interrupting a YouTube stream is relevant to the operational side, while this article focuses on the playlist and input sequence.
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
Does -stream_loop -1 loop the individual file or the whole playlist?
With the concat demuxer as the input, the loop option is intended to repeat that input sequence, so the listed files are read again in order. Test the return from the final entry to the first rather than assuming the loop boundary is clean. A failure at that point can still come from incompatible streams or inaccurate timestamps.
Can I always use -c copy with an MP4 playlist?
No. The .mp4 extension does not prove that the files have matching codecs, dimensions, time bases, stream layouts, or usable timing. Inspect the inputs and test the boundaries; if they differ, normalise the files or use the concat filter with re-encoding.
Why does my playlist work quickly but not at live speed?
A file input can be read faster than its natural playback rate unless it is paced. For a file-based playlist, -re applies real-time-style reading, while -stream_loop -1 controls repetition. Do not use the same pacing assumption for an input that is already a live capture or network stream.
Are YouTube HLS playlist rules required for this FFmpeg RTMP command?
No. HLS ingestion has its own segment and request requirements, while the example here is an RTMP-style FLV output. Confirm which protocol your YouTube Live setup uses, then follow the current official YouTube documentation for that protocol.