To stream a folder of videos to YouTube with FFmpeg on Ubuntu Server, first make an ordered playlist, check that its clips are compatible, then send that playlist to the current YouTube ingest URL and stream key. A folder by itself does not define playback order, and FFmpeg’s concat demuxer does not automatically repair files with different formats.
This is a reproducible workflow to adapt and validate on your own server, not a report of a command tested on a live channel or on a specific Ubuntu release. Plan to check the incoming preview, sound, playlist transitions and process behaviour before relying on it for an event or an unattended channel.
Inspect and organise the video folder
Start by deciding which files belong in the stream and the order in which they should play. A filesystem’s listing order is not a reliable editorial playlist: names such as clip1, clip10 and clip2 may sort differently from the order you intend. Use names with leading zeroes, such as clip-001.mp4, or enter the full intended sequence in a playlist file.
Keep the source folder separate from temporary files, logs and unrelated media. A working layout might contain a videos directory, a playlist.ffconcat file alongside it, and a separate protected configuration file for credentials. This makes it easier to review what is being sent and reduces the chance that an incidental file is included. For another practical consideration when choosing where source videos live, see streaming videos stored on an external drive.
Check that the Ubuntu account running FFmpeg can read every file and the playlist. If you edit the playlist as one user and run FFmpeg as another, permissions can cause a failure that looks like a media problem. Also consider storage availability: a long-running process still needs access to its input files throughout playback. Do not delete or move source material merely because YouTube may archive a broadcast; an archive is not a substitute for your own source copy.
The playlist is explicit rather than a request to scan the directory. That is useful operationally: adding a new video will not silently change the live sequence until you edit the list and validate it. It also means you should keep the playlist in step with the files, and remove or correct entries when a clip is renamed.
Check file compatibility and playback order
The FFmpeg concat demuxer joins inputs at the packet/stream level. Its inputs need matching stream layouts, codecs and time bases for reliable concatenation. A set of MP4 filenames does not establish that they share those properties: clips may differ in resolution, frame rate, audio presence, codecs or stream arrangement.
Inspect each file with a media probe such as ffprobe before treating it as ready. Compare the video and audio streams, dimensions, frame rates, codec names and durations. Check whether every file has the audio you expect; a silent clip can be a valid source but may produce a change in sound when it follows a clip with music. A file that lacks video or uses an unexpected stream layout may not behave as intended in a playlist designed for both audio and video.
Create a plain text file called playlist.ffconcat. Its first line must be exactly ffconcat version 1.0, followed by one file directive per source, in playback order. For example, the structure is:
ffconcat version 1.0
file 'videos/clip-001.mp4'
file 'videos/clip-002.mp4'
file 'videos/clip-003.mp4'
Use relative paths from the playlist’s working location, and take care with spaces and special characters. FFmpeg’s concat safe-path default accepts only relative paths with a restricted character set. Do not casually disable that check, particularly if a playlist could contain paths supplied by somebody else. The FFmpeg concat demuxer documentation describes the playlist format, compatibility expectations and timestamp handling.
For clips with matching streams, stream-copy can avoid re-encoding, using less processing and avoiding an additional generational quality loss. If their properties differ, normalise them to a consistent profile first, or use a decode/filter/re-encode workflow. Re-encoding can accommodate more differences but consumes more CPU and may affect picture or sound quality depending on the settings. It is a trade-off, not an automatic correction performed by concat.
The concat demuxer uses declared or estimated durations to place later files. If timing information is wrong, transitions can include gaps or timestamp artefacts. Test the actual playlist, especially at file boundaries, rather than assuming that a list which opens successfully will play seamlessly. If your use case is music or ambience, the advice on streaming wind sounds continuously is relevant to planning content, though the FFmpeg compatibility checks still apply.
Prepare FFmpeg on Ubuntu Server
Install FFmpeg using the package source you intend to maintain, then check that both ffmpeg and ffprobe are available to the account that will run the stream. Ubuntu package versions and build options can vary, so do not assume that a package on one release has exactly the same features as another. Confirm the installed build’s available protocols and encoders, including support for the selected RTMP or RTMPS output.
A basic local validation sequence is to list the FFmpeg version and inspect a source file with ffprobe, then test that the playlist can be opened and decoded before involving YouTube. A successful probe does not prove a continuous broadcast will work, but it can reveal missing files, unreadable paths, unsupported codecs or unexpected streams early. Review any errors before proceeding rather than hiding them in a long-running job.
Run the process in a way that remains attached to an observable service or session. An SSH terminal that closes unexpectedly should not be your only operational plan. A service manager or persistent terminal session can keep the process running after logout, but it does not by itself guarantee that the media is valid, that the network stays available or that FFmpeg will recover correctly after every failure. Plan how you will see process output and restart deliberately.
Keep configuration and secrets distinct from public scripts. Avoid putting the expanded ingest URL and key in a command that is saved in shell history or exposed in process listings, logs, screenshots or a shared repository. Restrict access to any environment file holding a key, and verify how your chosen service runner handles environment variables and logs. Treat the key as a password: anyone with it may be able to send a stream to that destination.
Build the continuous input workflow
At a high level, FFmpeg reads the ordered concat playlist, applies real-time pacing so stored files are sent at playback speed, selects the intended audio and video streams, encodes them to a compatible output when needed, and sends an FLV stream to the YouTube endpoint. The exact command depends on the source compatibility, desired output resolution and frame rate, installed FFmpeg build, and current YouTube ingest settings. There is no safe universal command to paste without checking those details.
For a single compatible file, FFmpeg documents -stream_loop -1 as an infinite input loop. For a folder playlist, validate loop behaviour at the playlist boundary with your installed build and actual media. The documented loop option does not promise gapless playback for every playlist, particularly when the clips differ. First test one pass, then observe more than one transition through the end and back to the start.
Use -re for stored media when the intention is to send it at normal playback rate rather than as fast as the server can read it. Map the expected streams explicitly if files may contain extra audio tracks, subtitles or other streams. Choose whether to stream-copy or re-encode based on the compatibility check; do not assume that a successful connection to YouTube proves the selected tracks and codecs are correct.
The output should use the current server URL and key shown in YouTube Live Control Room, with the key appended in the format expected by that endpoint. Do not put a real key in a sample command or an article, and do not echo a secret in diagnostic output. YouTube recommends RTMPS for encrypted ingest; confirm that the selected FFmpeg build supports the needed TLS/protocol combination. YouTube describes RTMPS as RTMP over TLS/SSL in its RTMPS guidance.
A single FFmpeg process can stop on a missing file, decoding error or network failure. For an always-on workflow, decide what will notice a stopped process and what action is appropriate: alert you, restart the process, or wait for manual investigation. A blind restart loop can repeatedly replay a fault without solving it. Keep logs useful but scrubbed of the stream key, and make sure the playlist and files are still available after a host restart.
Configure YouTube ingest settings
Before sending video, confirm that the channel can go live. YouTube’s current eligibility guidance requires a verified channel without a live-streaming restriction in the previous 90 days, and its getting-started guidance sets a minimum age of 16 for live streaming. Check YouTube’s live-streaming eligibility and getting-started instructions for current requirements; access and product rules can change.
Open YouTube Studio’s Live Control Room and create or select the stream. Copy the current server URL and stream key from the encoder settings into your protected configuration. YouTube says the key should be treated like a password. Use the key for the intended stream, and avoid sharing screenshots or logs that reveal it. If you rotate or replace it in Studio, update the configuration that the running process uses.
YouTube recommends RTMPS, H.264 video, CBR, AAC or MP3 audio and a two-second keyframe interval. The bitrate depends on resolution and frame rate, so use YouTube’s current encoder settings and bitrate table for your intended output rather than copying a single value from an unrelated setup. For context, YouTube’s listed H.264 recommendations include 10 Mbps for 1080p at 30 fps and 12 Mbps for 1080p at 60 fps; those are settings guidance, not a guarantee of quality on every source or connection.
Compare relevant output choices before settling on an encoding profile:
| Choice | What it changes | When it may fit |
|---|---|---|
| Stream-copy compatible inputs | Avoids re-encoding, with lower processing demand and no new encoding loss; requires matching stream properties | Clips already checked and aligned to a compatible profile |
| Decode and re-encode | Allows filtering and normalisation across more varied sources; uses more processing and can alter quality | Mixed clips that need a common resolution, frame rate, codec or audio layout |
| RTMPS ingest | Encrypts the RTMP connection in transit | Typical encoder output when supported by the build and available in Studio |
| HLS ingest | Uses a different ingest path and key configuration | Cases such as HDR or codecs that YouTube does not support over RTMP, when the channel is configured for HLS |
Do not select HLS simply as a presumed improvement. YouTube’s documentation positions it for particular codec or HDR requirements and calls for an HLS-configured stream key. For an ordinary compatible FFmpeg output, follow the settings shown for the stream in Live Control Room.
Upload bandwidth must support the total outgoing bitrate, including any simultaneous backup feed if you configured one. YouTube recommends keeping 20% spare upload capacity. Check upload rather than download speed, preferably under conditions resembling the planned stream, and account for other traffic sharing the connection. YouTube’s streaming tips provide further guidance; a speed test is a useful check, not a promise that the connection will remain steady overnight.
Preview and verify the output
Before a public event or unattended run, test with an unlisted stream or another suitable visibility setting. Start the encoder and wait for the incoming preview in Live Control Room. Confirm that the picture is moving, the expected audio is present and correctly balanced, and the displayed stream status is healthy before using any Go live control presented for a scheduled event. Starting an encoder and making a scheduled broadcast public are separate operator steps in YouTube’s workflow.
Check the first clip, a transition between clips, and the return to the beginning of the playlist. Look for a black picture, frozen frame, audio that disappears, sudden changes in loudness, long gaps or unexpected aspect-ratio changes. Leave the test running long enough to expose problems that do not occur at the first frame. Then confirm that the result on YouTube is consistent with the encoder output; a local decode test alone cannot verify ingest or the public playback path.
Also validate upload headroom while the stream is active and note whether the host is sharing the connection with backups, updates or other traffic. YouTube recommends setting up encoders at least two hours before an event and starting them at least 15 minutes before it. Treat those as event-readiness recommendations rather than technical prerequisites for every personal stream. For a broader approach to continuous YouTube music streams, plan the operational checks as well as the playlist itself.
Keep the test’s purpose narrow: confirm that this folder, on this host, with these settings, behaves as intended. If you change a file, playlist order, encoding profile, FFmpeg build or ingest settings, repeat the relevant checks. A prior test is evidence about the setup you tested, not a guarantee for a changed configuration.
Monitor the process and diagnose black screens or stops
If YouTube shows a black screen, start with the simplest distinction: is FFmpeg reading and decoding the intended video stream, and does the incoming preview show a picture? Check playlist paths, permissions, stream mapping and whether the source actually contains video. A file can exist yet contain a stream layout different from the others. Test the affected file independently and inspect its streams before changing multiple encoder settings at once.
If black video appears only between clips, focus on playlist boundaries and compatibility. Compare codecs, time bases and stream layouts, then check timestamps and reported durations. A playlist that opens does not demonstrate that every transition is clean. Normalising the sources or using a re-encode pipeline may address differences, but test the revised output; FFmpeg cannot infer your intended picture or repair every bad timestamp automatically.
If the stream stops, inspect the FFmpeg error output and YouTube Live Control Room status. Look for a missing or unreadable file, a network disconnect, rejected ingest credentials, unsupported protocol/TLS support, or an encoder process that exited. Confirm the key is current without printing it into logs. If the process is alive but the preview is not advancing, distinguish a stalled input from a connection issue before restarting.
Monitor both the process and the YouTube preview during initial operation. A service manager can help keep a process alive, but automatic restarting is not the same as resolving the underlying error. Use bounded, observable recovery: record why a restart happened, avoid exposing secrets, and make sure a repeated failure can reach a human. If you need an operating approach that does not depend on maintaining an Ubuntu host, StreamNeo can remove the task of keeping that server and FFmpeg process running by letting you upload the video and provide the YouTube key for a cloud-run broadcast.
When ending a stream, stop the encoder and follow the Live Control Room controls appropriate to the stream type. YouTube says streams shorter than 12 hours are automatically archived after the encoder stops, but keep original files independently if an archival copy matters. Check the current YouTube encoder instructions for stream-specific end steps and archive behaviour.
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
How do I make FFmpeg play videos from a folder in a loop?
Create an FFconcat playlist with ffconcat version 1.0 on its first line and one file entry per video in the order you want. Validate that the files have compatible streams, then test the looping behaviour at the final-to-first boundary on your installed build; a folder scan alone does not establish order or gapless playback.
Why does my YouTube stream show a black screen or stop between videos?
The playlist may point to a missing file, or the clips may differ in video streams, codecs, time bases or durations. Inspect the affected files and watch the incoming preview at the transition; normalising clips or re-encoding may help, but neither should be assumed to fix every source.
Does FFmpeg automatically make incompatible videos work together?
No. The concat demuxer expects compatible stream layouts, codecs and time bases. You need to check the inputs and either make them consistent or use an appropriate decode/filter/re-encode workflow, then test the result.
Can I leave the stream running after disconnecting from SSH?
A persistent session or service manager can keep FFmpeg running after you log out, but you still need a plan to observe failures and recover safely. Test what happens after a process exit, host restart and network interruption, and keep the stream key out of command history and logs.