If your videos already sit on a remote server, you can play them in a chosen order, send them to YouTube Live with FFmpeg, and repeat the sequence. The reliable workflow is to make an explicit concat playlist, check whether the files are compatible, then either stream-copy them or re-encode them into a consistent YouTube-friendly output.
The important qualification is that a folder is not automatically a working playlist. Different codecs, resolutions, frame rates, audio layouts and timestamps can cause failed transitions or unusable output, so treat every command below as a starting pattern rather than a command tested against your media.
Check that the channel can go live
Before working on the server, check the channel in YouTube Studio. YouTube says live streaming requires a verified channel and no live-streaming restriction during the previous 90 days. The current requirements are described in YouTube's live streaming help, and you should check that page again if the channel has never streamed before.
Open YouTube Studio and go to Live Control Room. Create or schedule an encoder stream, then note the stream URL and stream key shown there. The exact values and available controls belong to the channel, so do not copy an old URL from a tutorial and assume it is still correct.
Treat the stream key as a password. Keep it out of public shell scripts, screenshots, repositories and shared chat messages. Store it in a protected environment variable or a file readable only by the account running FFmpeg. YouTube also documents how to reset a compromised key, so reset it if it has been exposed rather than trying to keep using it.
Check the privacy setting before starting. For the first run, Unlisted is usually easier to inspect than Public. Also check auto-start and auto-stop behaviour in Live Control Room. An unattended process can be running while the YouTube event is private, waiting for a scheduled start, or stopped by an account setting.
If this is a new channel, make the first test deliberately small. A short unlisted broadcast lets you confirm that YouTube accepts the feed before you spend time debugging a night-long run.
Inventory the folder before making a playlist
Do not begin with “all files in this directory”. Decide which files belong in the channel and what order viewers should see. For a devotional channel, that might be a morning sequence followed by an evening sequence. For a study channel, it could be lessons numbered 01, 02 and 03. A filesystem’s enumeration order is not a programming for your schedule.
Make a table or text list containing, at minimum, the filename, duration, video codec, resolution, frame rate, pixel format, audio codec, sample rate and number of audio channels. FFmpeg’s ffprobe can help inspect these values. A starting pattern for one file is:
ffprobe -v error -show_streams -show_format \
-of json "/media/channel/lesson-01.mp4"
This does not decide whether files will concatenate cleanly. It gives you evidence to compare. Look especially for differences such as one file using H.264 and another using HEVC, one video being 25 fps and another 30 fps, or one file having stereo AAC while another has no audio. Variable frame rate, unusual time bases and inaccurate duration metadata also deserve attention.
Open representative files, not only the first file. Watch the end of one item and the beginning of the next, listen for silence or a sudden volume change, and check whether any file has a damaged section. A file that plays in a desktop player can still expose timestamp or stream-layout problems when placed in a concat demuxer.
The YouTube Live bitrate settings for 24/7 bhajans are useful when choosing an output target, but they do not make unsuitable inputs compatible. First understand the material, then choose the encoder settings.
Create an ordered concat playlist
FFmpeg’s concat demuxer reads a text file containing media paths sequentially. The playlist should be created deliberately, with one entry per file and the order written out. A basic playlist looks like this:
file '/media/channel/01-opening.mp4'
file '/media/channel/02-main-programme.mp4'
file '/media/channel/03-closing.mp4'
Use paths that the FFmpeg process can read. If a filename contains an apostrophe, newline or other special character, follow the escaping rules in the FFmpeg concat demuxer documentation rather than copying the example unchanged. Keep the playlist in a directory with suitable permissions and avoid allowing an upload process to alter it while FFmpeg is reading it.
For a small, fixed schedule, writing the file by hand is often safer than relying on a shell glob. If you generate it automatically, sort by the naming convention you chose and inspect the resulting text file before starting the stream. “Sort by filename” only works if the names are padded consistently, such as 01, 02 and 10 rather than 1, 2 and 10.
A starting pattern for a playlist entry is:
file '/srv/videos/morning/01-intro.mp4'
The -safe 0 option is commonly used when the playlist contains absolute paths, but it does not fix invalid paths or unsafe file contents. A useful preflight step is to open each entry with ffprobe, record failures, and remove or repair those files before the live test. The exact preflight script depends on the server operating system and the FFmpeg build.
The concat demuxer has an important constraint: the files are expected to have the same streams, including compatible codecs and time bases. The official documentation also warns that inaccurate duration information can create artefacts. Therefore, a playlist is an ordered input description, not a promise that arbitrary videos can be joined without processing.
Choose stream copy or re-encoding
Stream copy means FFmpeg passes the encoded audio and video packets through without decoding and encoding them again. It uses little processing power and preserves the existing encoding, but it is demanding about compatibility. If the files differ in stream layout, codec, dimensions, frame rate or timestamps, -c copy may fail, produce warnings, or create a bad transition.
Re-encoding decodes the inputs and produces a new, consistent output. It uses more CPU, but it gives you control over resolution, frame rate, pixel format, video codec, audio codec, bitrate and keyframe interval. For a remote server, that trade-off is often easier to operate when the folder contains material collected from several sources.
Use the decision table as a practical guide rather than a guarantee:
| Situation | First approach | Main trade-off |
|---|---|---|
| Files have matching streams and encoding parameters | Try stream copy | Low CPU use, but transitions still need testing |
| Resolution, frame rate or codecs differ | Re-encode to one profile | More CPU use and a new generation of the video |
| Audio is missing or has different channel layouts | Normalise audio while encoding | More predictable output, but silent or altered sections need review |
| The server has limited CPU but consistent source files | Test stream copy first | Less processing, with stricter input requirements |
| The server has stable CPU capacity and mixed media | Use a consistent re-encoding profile | Higher processing demand, usually simpler output control |
A stream-copy starting pattern is:
ffmpeg -re -stream_loop -1 \
-f concat -safe 0 -i /srv/playlists/channel.txt \
-c copy -f flv "${YOUTUBE_URL}/${YOUTUBE_KEY}"
This is not a universal command. The position of the loop option, concat input options, output URL format and supported protocols can vary with the FFmpeg build. More importantly, -c copy only makes sense after you have inspected the files and tested the transitions.
A re-encoding starting pattern for a consistent SDR output is:
ffmpeg -re -stream_loop -1 \
-f concat -safe 0 -i /srv/playlists/channel.txt \
-vf "scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2" \
-r 30 -pix_fmt yuv420p \
-c:v libx264 -preset medium -b:v 14M -maxrate 14M -bufsize 28M \
-g 60 -keyint_min 60 \
-c:a aac -b:a 128k -ar 48000 -ac 2 \
-f flv "${YOUTUBE_URL}/${YOUTUBE_KEY}"
This example targets a 1080p30-style output and is still only a starting pattern. The scaling filter may crop or pad differently from what you want, and your FFmpeg build may not include libx264. The chosen bitrate should follow YouTube’s current encoder table and the content you are sending. YouTube currently lists 14 Mbps as the recommended H.264 bitrate for 1080p30 and 17 Mbps for 1080p60 in its encoder guidance, but those figures do not replace a test of your server’s actual upload path.
Do not add HDR settings to an ordinary SDR workflow without understanding the source and destination requirements. If the folder contains HDR material, decide whether to preserve it through a workflow that meets YouTube’s current HDR requirements or convert it deliberately to SDR.
Loop the input with FFmpeg
The concat playlist describes one pass. To repeat it, FFmpeg’s input stream loop option can reopen the input after the playlist ends. In the patterns above, -stream_loop -1 appears before the concat input. Keep the option associated with the input rather than treating it as a general instruction to repeat every output operation.
Before looping, run one finite pass. Remove the loop option and send the result to a local file or a short test output. This makes it easier to see whether the second file starts correctly, whether the final file ends cleanly, and whether an audio stream disappears at a transition.
A local output test might begin like this:
ffmpeg -re \
-f concat -safe 0 -i /srv/playlists/channel.txt \
-c:v libx264 -c:a aac -f matroska /srv/tests/playlist-test.mkv
Again, this is a starting pattern, not a tested recipe for your media. Add the same normalisation settings you intend to use for YouTube, then inspect the output. If FFmpeg reports non-monotonic timestamps, missing streams, invalid durations or decoder errors, stop and resolve those issues rather than hiding them in a long-running process.
An infinite loop also does not repair a bad final transition. If the last file has a different format from the first, the problem will appear every time the sequence wraps. A practical approach is to make the first and last items compatible with the rest of the normalised profile, or add a short prepared transition file that matches the chosen output.
For an unattended channel, decide what should happen when FFmpeg exits. A process supervisor or scheduled restart can relaunch it, but an automatic restart can also repeat a damaged input or repeatedly expose a bad stream key. Record the exit code and recent log lines, and alert on repeated failures rather than restarting without a limit.
Configure YouTube ingest and the key
YouTube accepts encoder feeds through the stream URL and key displayed in Live Control Room. Prefer RTMPS when the current FFmpeg build supports it, because YouTube recommends the encrypted extension of RTMP. Use the current URL shown in Studio rather than assuming that every account uses the same endpoint.
Keep the values separate from the command history where possible. One starting pattern is to set protected environment variables before running FFmpeg:
export YOUTUBE_URL='rtmps://the-url-shown-in-live-control-room'
export YOUTUBE_KEY='the-key-shown-in-live-control-room'
Do not paste a real key into a public systemd unit, issue tracker or tutorial. Be aware that command-line arguments can be visible to other users through process listings, depending on the server operating system. A protected environment file or secret-management method may be preferable, but its exact configuration is platform-specific.
Your output must use a format YouTube accepts. YouTube’s current encoder settings guidance covers supported video and audio codecs, constant bitrate guidance, frame rates and keyframe intervals. The page lists H.264, H.265 and AV1 video, AAC or MP3 audio, and recommends a two-second keyframe interval that does not exceed four seconds. Confirm the current table before choosing a profile.
Plan network capacity around the encoded output, not the source file size. YouTube recommends about 20% upload headroom above the stream bitrate. Measure the outbound path from the remote server itself, because a speed test from your home or office does not describe the server’s connection. A server that can briefly reach the target rate may still be unsuitable if its sustained upload varies or competes with backups and other jobs.
For example, a 14 Mbps video target is not the whole network requirement once audio, protocol overhead and headroom are considered. Do not interpret the recommended headroom as a guarantee of delivery or uptime. It is a planning recommendation from YouTube, and the remote host still needs to be tested under its normal workload.
Test transitions and monitor the output
Start with an Unlisted event and wait for the preview in Live Control Room. Check the first transition, a transition between two ordinary files, and the transition where the playlist loops back to its first item. Watch for a frozen frame, black video, a burst of noise, silence, aspect-ratio changes, frame-rate judder and delayed audio.
Check the stream health panel and the public or unlisted watch page. Confirm that the selected resolution appears, audio meters move when they should, and the output bitrate is stable. A local FFmpeg log can show encoder warnings, reconnect attempts and input errors that are not obvious from the picture alone.
The OBS cloud-server setup guide is useful if you prefer to inspect scenes through a graphical encoder. FFmpeg is more direct for a fixed folder workflow, but a graphical tool can be easier when you need overlays, manual scene changes or visible status controls.
For an always-on channel, monitor more than whether the process exists. Check that the playlist files remain available, disk space is not being consumed by logs or temporary files, the server still has outbound connectivity, and the broadcast remains visible in Live Control Room. If the source folder is mounted remotely, test what happens when that mount becomes unavailable.
YouTube recommends testing encoder failover and continuously monitoring audio and video quality. A backup process or second server can reduce recovery time, but it introduces another stream-control decision. Test which process is allowed to publish, how the key is protected, and whether restarting creates a new event or reconnects to the existing one.
Do not assume one live session can remain open indefinitely or that every long session will archive in the same way. YouTube’s encoder guidance says streams under 12 hours are automatically archived. That does not establish a single-session archive outcome beyond 12 hours, so an always-on channel needs a tested rotation or restart policy and should confirm current behaviour in Studio. The article How long can a YouTube live stream run covers this operational question in more detail.
If the channel includes music, devotional recordings or reused programme material, review rights and platform policies separately. A technically stable feed can still receive a claim, restriction or interruption. The guide on copyright, Content ID and live streams explains why this should be considered before relying on a continuous broadcast.
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 stream every video in a server folder without creating a playlist?
You can generate a playlist from the folder, but relying directly on directory enumeration makes the order unclear and can include files you did not intend to broadcast. An explicit concat file gives you a reviewable schedule and lets you remove a damaged or unsuitable item before starting. Generate it from a controlled selection rather than blindly including every extension in the directory.
Will -c copy work with mixed MP4 files?
Not necessarily. The container extension does not tell you whether the video codecs, time bases, frame rates, resolutions and audio streams match. Inspect the files and test the transitions; if the streams are not compatible, normalise them through a consistent re-encoding workflow instead of assuming stream copy will succeed.
How do I keep the stream key out of my FFmpeg command?
Use a protected environment variable or a permissions-restricted configuration file, and check whether your operating system exposes command arguments to other users. Do not commit the key to a repository or print it in logs. If it is exposed, reset it in YouTube Studio and update the encoder configuration.
Does looping FFmpeg guarantee a 24/7 broadcast?
No. Looping only repeats the input while FFmpeg, the files, the server and the network continue working. You still need to test transitions, monitor the remote process, allow for network headroom, plan recovery, and confirm how YouTube handles long sessions and archive rotation.