Skip to content
streamneo.
Setup Guides15 min read

How to Set Up an Automatic Video Playlist for YouTube Live with FFmpeg

Build a looping YouTube Live playlist with FFmpeg, from a compatible file list to a private test and monitored RTMPS stream.

sn.
StreamNeoPublished 3 October 2026
Worth sharing?

A reliable FFmpeg playlist stream starts with compatible video files, a correctly formatted concat list, and a YouTube encoder stream. FFmpeg then reads the files in order, plays them at real-time speed, encodes the output, and sends it to YouTube over RTMPS.

The loop is not the same as a complete 24/7 service. You still need to test file transitions, protect the stream key, watch the encoder process and plan what happens if the computer, connection or YouTube ingest stops responding.

Prepare the video files first

FFmpeg's concat demuxer is intended to read a sequence of files as one input. It is not a general-purpose repair tool for clips that were made with different settings. The closer the files are to one another, the less work FFmpeg has to do at each boundary.

For a dependable playlist, use clips with matching:

  • video codec
  • audio codec
  • frame size
  • frame rate
  • pixel format
  • audio sample rate and channel layout
  • time base and sensible duration information

The FFmpeg documentation states that all files in a concat sequence must have the same streams, including codecs and time bases. Read the concat demuxer documentation before relying on a list made from unrelated downloads.

A useful example is a devotional channel with ten MP4 bhajan videos. If all ten were exported as H.264 video with AAC audio at the same frame size and frame rate, they are reasonable candidates for one list. If one file is a vertical phone recording, another is a 4K screen capture and a third has no audio stream, adding them together without normalisation may produce timestamp gaps, a broken transition or an output that YouTube rejects.

Put the media in a dedicated directory. Keep the playlist text file in that directory as well, unless you have a reason to use absolute paths. Relative paths make the list easier to move and reduce the need for special characters.

Before building the live command, play every file from beginning to end. Check that each has the intended audio, that the duration shown by your media player is plausible and that no clip ends with a long silent tail. A bad duration can affect when FFmpeg moves to the next item.

If the files do not match, transcode them to one consistent format before adding them. That takes time and may reduce quality, but it is usually easier to diagnose than asking the live command to handle every difference while it is also encoding and uploading.

This preparation is particularly important for channels that use long ambient videos. A transition that is barely noticeable in a local player can become a visible pause or audio pop after the files are joined and sent as one live feed. For broader planning, the practical considerations in how to make a YouTube playlist play continuously on a live stream are useful, but the method here uses FFmpeg rather than YouTube's normal playlist feature.

Create the concat playlist text file

Create a plain text file named playlist.txt in the media directory. Its first line identifies the format, and each following line names one file in the order you want it played:

ffconcat version 1.0
file 'video-01.mp4'
file 'video-02.mp4'
file 'video-03.mp4'

The names are relative to the location from which FFmpeg reads the list. If playlist.txt and the three MP4 files are in the same directory, the example is sufficient. The first file will play, followed by the second and third.

The concat demuxer reads the entries sequentially. It does not shuffle them, choose a random item or inspect the list for an editorially sensible order. If you want a different order, edit the file and restart FFmpeg.

Paths need care. Spaces and certain punctuation can have meaning in a text file or shell command. Single quotes around ordinary filenames are helpful, but a filename containing a single quote needs escaping according to FFmpeg's concat file syntax. The simplest operational rule is to use names such as morning-aarti-01.mp4, morning-aarti-02.mp4 and morning-aarti-03.mp4.

You may see examples using absolute paths and -safe 0. The concat demuxer uses safe path handling by default, which rejects some path forms. -safe 0 allows the paths in a controlled playlist, including paths that the default setting may reject. Use it only when you control the list. Do not accept playlist entries from an untrusted upload or generated form without validating them.

For absolute paths, a list might look like this:

ffconcat version 1.0
file '/media/channel/video-01.mp4'
file '/media/channel/video-02.mp4'

Relative paths are easier to test and back up. They also mean you can move the whole directory to another machine without editing every line. Whichever form you choose, run the command from the directory you expect, or provide the full path to playlist.txt.

A playlist is a source file, not a log of what has already played. If you add a new clip while FFmpeg is already running, do not assume it will be picked up safely. Finish editing the list, check its syntax and restart the process during a planned test window.

Set up YouTube Live and obtain the ingest details

In YouTube Studio, open Go Live and create or schedule an encoder stream. Live Control Room provides the stream URL and stream key that an external encoder needs. You can review the current YouTube encoder setup instructions if the Studio layout or stream creation options differ from what you see.

Treat the stream key like a password. Keep it out of public shell history where practical, out of screenshots and out of source-control repositories. If it is exposed, reset it in YouTube Studio and update the command that uses it. The YouTube live stream settings guide covers the settings available for visibility, scheduling and related stream choices.

Choose the visibility deliberately. Private is suitable when you are checking the feed yourself or with selected accounts. Unlisted is useful when a small test group needs a link. Public is for the channel's real audience, not for the first run of an untested concat file.

The output destination normally combines the RTMPS server address supplied by YouTube with the stream key. Do not copy a generic address from an old tutorial when Live Control Room gives you a different one. Use the exact ingest information shown for the stream.

RTMPS is YouTube's recommended encrypted RTMP option. The YouTube RTMPS guidance explains the relevant connection method. If your FFmpeg build or script uses a different protocol, check that it is supported by both your build and the current YouTube encoder guidance before depending on it.

YouTube's stream settings also determine how much encoding work is sensible. A small local machine sending a modest 720p channel has a different requirement from a high-resolution output with moving footage. Decide the output resolution and frame rate first, then use YouTube's current encoder table rather than copying a bitrate from an unrelated video.

Build the FFmpeg concat command

The following is a starting template for a controlled test. Replace the destination placeholder with the exact RTMPS URL and stream key from YouTube Studio:

ffmpeg -re -stream_loop -1 -f concat -safe 0 -i playlist.txt \\
  -c:v libx264 -preset veryfast -pix_fmt yuv420p -r 30 -g 60 \\
  -b:v 4500k -maxrate 4500k -bufsize 9000k \\
  -c:a aac -b:a 128k -ar 44100 \\
  -f flv "<RTMPS_URL>/<STREAM_KEY>"

This is an illustrative configuration, not a tested command for every FFmpeg build, source file or connection. The values should be checked against your media, encoder capacity, upload connection and YouTube's current requirements.

The important parts are easier to understand separately:

  • -re asks FFmpeg to read the input at its native real-time rate rather than consuming the files as quickly as the machine can decode them.
  • -stream_loop -1 requests that the input be repeated indefinitely.
  • -f concat selects the concat demuxer.
  • -safe 0 permits the controlled paths in the playlist, including path forms that safe mode might reject.
  • -i playlist.txt identifies the concat list.
  • -c:v libx264 encodes video as H.264 when that encoder is available in the FFmpeg build.
  • -pix_fmt yuv420p selects a widely supported pixel format.
  • -r 30 requests a 30-frame-per-second output.
  • -g 60 sets a 60-frame keyframe interval at 30 fps, which represents a nominal two seconds.
  • -c:a aac and -b:a 128k encode the audio as AAC at the shown target bitrate.
  • -f flv selects the container commonly used with RTMP-style live output.

FFmpeg options apply to the next input or output, so their position matters. Input-related options such as -re and -stream_loop belong before the input they affect. Output encoding options belong after -i playlist.txt and before the destination.

The command re-encodes the complete feed. That is deliberate when source clips need a common output format, but it uses more CPU than simply copying already-matching streams. Stream copying can be appropriate for files that genuinely match, yet it leaves less room to correct inconsistent frame rates, codecs or audio layouts. If your purpose is a stable live output from mixed material, consistent re-encoding is usually easier to reason about.

Pace playback in real time and choose output settings

A file is not a live signal merely because it is sent to a live endpoint. Without real-time pacing, FFmpeg may read prerecorded input faster than its intended duration. -re is the option that tells FFmpeg to consume the input at a rate suitable for live use. It does not repair a damaged file or make a slow computer faster.

The loop option also needs a realistic interpretation. -stream_loop -1 requests repeated input, but it does not promise that the process will remain healthy forever. A failed encoder, full disk, interrupted network, operating-system restart or YouTube-side issue can still stop the broadcast.

Start with an output frame size and frame rate that your machine can encode comfortably. If the files already match the intended output, fewer conversions may be needed. If they do not, let the encoder normalise them rather than relying on a mixture of source properties at every boundary.

Do not treat 4500k as a universal YouTube value. The example's video bitrate is only a starting point. YouTube's current encoder settings and bitrate table varies its guidance by resolution, frame rate and codec. Select a suitable row, then confirm that the upload connection can sustain the total video and audio rate with some margin.

The keyframe setting deserves the same care. YouTube recommends a two-second keyframe interval and says not to exceed four seconds. At 30 fps, -g 60 is a two-second nominal interval. If you change the frame rate, recalculate the corresponding frame count or use the encoder settings that match your chosen output.

The -preset veryfast setting is a trade-off, not a quality guarantee. A faster preset generally reduces the work required per frame, while slower presets may use more processing for compression efficiency. If the machine cannot keep up, a sophisticated bitrate choice will not save the stream. Watch CPU use and FFmpeg's progress output during the test.

Audio needs checking as well. A silent source, an unusual sample rate or unequal audio and video durations can become obvious at a file boundary. Confirm that the selected audio bitrate and sample rate are accepted by the current YouTube guidance and that your playlist actually contains the audio you want viewers to hear.

Send the feed to YouTube and verify it

Run the command from a terminal where you can see FFmpeg's output. Do not close that terminal until you have confirmed that the process is behaving as expected. The progress line should advance rather than repeatedly reporting errors, and the input should move through the files in order.

The destination in the example is written as:

<RTMPS_URL>/<STREAM_KEY>

Use the exact format shown by YouTube for your encoder stream. Avoid publishing the completed command in a tutorial screenshot, issue tracker or public repository because it contains the credential-like key.

Once FFmpeg connects, open Live Control Room and check the preview. Confirm the picture is visible, the audio meter responds and the stream health indicators do not show a persistent problem. The local terminal can show that FFmpeg is sending data, but only YouTube can confirm how the ingest is being received and processed.

Watch at least one ordinary section of a clip and one transition between clips. A stream can look correct during the middle of a five-minute video and still fail when the concat demuxer moves to the next item. Check for a frozen frame, a burst of silence, a repeated frame, an aspect-ratio change or a sudden change in loudness.

If YouTube reports insufficient data, first check the upload connection and whether the computer is keeping up with encoding. If FFmpeg reports decode errors, inspect the source file named near the error. If the stream starts but fails at every boundary, compare the input streams and durations instead of changing random bitrate values.

For a channel intended to run after a reboot, the command also needs process supervision and restart planning. A separate guide on running FFmpeg as a systemd service for a 24/7 loop covers the service approach. It does not remove the need to inspect logs, test restarts and confirm that a restarted process reconnects to the intended YouTube stream.

Test the loop before using it publicly

Make the first run private or unlisted. This gives you a chance to inspect the complete path without presenting a broken transition to subscribers. Use representative material rather than a tiny test clip with no audio, because a simple test can hide the conditions that cause trouble in the real playlist.

Your test should cover four areas:

  1. Input order: confirm the first, second and third files appear in the intended order.
  2. Boundary behaviour: watch at least two transitions for picture freezes, missing audio, timestamp jumps and sudden changes in size or frame rate.
  3. Ingest health: check Live Control Room's preview and stream health while the local FFmpeg process is running.
  4. Failure recovery: stop and restart the process deliberately, then check whether the command reconnects as expected and whether the stream settings remain correct.

Do not assume that one successful start proves an overnight run will work. Let the test cover enough of the playlist to reach an actual loop boundary. If the list contains several hours of files, you can also make a shorter duplicate list for transition testing, then repeat the check with the full list before going public.

If a boundary produces an artefact, normalise the files. Match the frame size, frame rate, codecs, pixel format, audio layout and time bases. Check durations with a media-inspection tool, replace damaged files and remove clips that have unexpected variable behaviour. Changing -g, -b:v or the YouTube visibility setting will not fix a source file with a missing stream.

Keep a copy of the working playlist and command configuration, but store the stream key separately and securely. If you change the key, update the protected configuration rather than pasting the new value into several old scripts. Record which files were included and when you last checked them, so a later edit can be traced.

If you do not want to maintain a machine, terminal session, restart policy and connection for this workflow, a managed option can remove that specific operational burden. StreamNeo turns an uploaded video into a YouTube-only live stream after you provide the file and YouTube stream key, so your own computer does not have to stay switched on; it still makes sense to test the content and visibility before sharing it.

A locally managed FFmpeg setup can be the better fit when you need custom filters, several outputs, local hardware encoding or complete control of the process. A managed workflow can be simpler when the requirement is one uploaded file running as a YouTube channel, but it is not a substitute for checking copyright, content suitability or YouTube's current rules.

Know what the loop does not guarantee

This workflow automates file selection and delivery. It does not guarantee uninterrupted operation, indefinite availability, automatic recovery from every failure or one continuous archive for an always-on channel.

The computer must remain powered, the operating system must keep the process alive, the source files must remain readable and the upload connection must continue to send data. YouTube must also accept the ingest. A command that loops correctly can still be interrupted by a power cut, network change, encoder crash or stream-side event.

YouTube says streams shorter than 12 hours are automatically archived. That rule should not be turned into a promise that a 24/7 loop will produce one automatically archived recording. If an archive matters, check the current YouTube guidance and plan recordings or shorter sessions around the behaviour you need.

Before making the stream public, decide who will notice a failure and how quickly they can act. For a small business, that might mean checking the Live Control Room each morning. For a devotional or study channel, it may mean monitoring alerts and keeping a known-good playlist ready. The appropriate plan depends on how much interruption your audience can tolerate.

Also check the rights for every video, image, voice recording and music track. A private test can validate the technical path, but it does not establish that you may broadcast the material publicly. You remain responsible for checking the current YouTube policies and any rights that apply to your content.

If you want to compare a local process with other operating arrangements, free versus paid 24/7 streaming and what “free” actually costs is a useful planning read. The relevant question is not only whether FFmpeg is free to download, but whether you can reliably provide the machine, connection, supervision and recovery work around it.

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 FFmpeg loop several videos for YouTube Live?

Yes. Put the files in a concat demuxer list, use -f concat to read it and add -stream_loop -1 to request repeated playback. The files still need compatible streams and accurate enough timing for clean transitions.

Why is -re important in this command?

-re makes FFmpeg read the prerecorded input at approximately real-time speed, which is appropriate when sending it as a live feed. Without real-time pacing, the encoder may consume the source faster than its intended duration rather than behaving like a live channel.

Should the first YouTube test be public?

No. Use private or unlisted visibility while checking the preview, audio, stream health and file boundaries. Change the visibility only after you have tested representative content and know how you will respond if the process stops.

Does -stream_loop -1 guarantee a 24/7 broadcast?

No. It requests indefinite input looping, but it cannot prevent computer, process, network or YouTube ingest failures. A dependable operation needs testing, monitoring and a recovery plan as well as the FFmpeg command.

YOU’VE REACHED THE END

Keep the ideas coming.

More guides, useful tools and a little help for your next broadcast.

Back to the journal ↗
YOUR NEXT READ

A little more to explore.

More Setup Guides guides ↗ · All topics ↗