Skip to content
streamneo.
Setup Guides12 min read

How to Use an FFmpeg Concat File for a Nonstop YouTube Stream on Hetzner

Build an FFmpeg concat playlist, loop compatible files to YouTube Live, and monitor a Hetzner-hosted stream for interruptions.

sn.
StreamNeoPublished 5 October 2026
Worth sharing?

To stream prerecorded videos continuously from a Hetzner server to YouTube Live, make an FFmpeg concat playlist, check that its files are compatible, and loop the playlist input with -stream_loop -1. Then send the output to the ingest URL and stream key for your YouTube Live event, and monitor both FFmpeg and YouTube for faults.

That command pattern can keep feeding a live event, but it cannot make mismatched files compatible or guarantee that a stream remains available. The host must sustain the file reads and outbound traffic, and the process needs a recovery plan if it exits or loses its connection.

What a concat playlist does

FFmpeg’s concat demuxer reads a text file containing an ordered list of media files and presents their streams as a sequence. Instead of starting a separate FFmpeg process for each clip, you give one input a playlist; FFmpeg reads the first file, then the next, in the listed order. The demuxer adjusts timestamps so each file follows the preceding one.

The key qualification is compatibility. The files need matching stream layouts, codecs and time bases for the demuxer to join them as intended. If one video has a different frame size, codec or audio arrangement, simply placing it next in the playlist does not convert it. When source files differ, prepare normalised copies or use a suitable re-encoding workflow before relying on the playlist.

A playlist is not a YouTube playlist URL. It is a local text file read by FFmpeg as an input. YouTube Live is the destination: FFmpeg sends the resulting broadcast to the event’s ingest endpoint. For other ways to assemble prerecorded videos into a continuous broadcast, the guide to adding multiple videos to a continuous YouTube Live stream covers the broader workflow.

Check and prepare your video files

Before writing the playlist, inspect every source file. Check the video and audio streams, codecs, time bases, dimensions and duration metadata. FFmpeg’s concat demuxer documentation describes the stream-matching requirement and the playlist directives. The FFmpeg build on your server should also be able to read the file formats you have.

Matching files make a stream-copy workflow more practical. With -c copy, FFmpeg passes the encoded audio and video through rather than decoding and encoding them again. That avoids the video re-encoding work, but it does not reconcile mismatches. If clips use incompatible codecs or time bases, stream copy is not a repair step; normalise the clips first or choose an appropriate conversion and filter workflow.

Pay attention to durations as well as codecs. The concat demuxer uses timing information to place files in sequence. Incorrect duration metadata can lead to timestamp problems or visible and audible artefacts, while streams within a file whose durations do not align can introduce gaps. A duration directive can override stored duration information, but use it only when you have a reliable duration to enter. It is better to correct the media or its timing deliberately than to guess.

Make a test playlist with representative clips before preparing a long rotation. Include the kinds of transitions your channel will actually use: for example, a devotional channel might have a song with vocals followed by a longer instrumental video, while a local news loop may alternate studio segments and title cards. Watch and listen across the joins. A command that starts successfully is not evidence that every transition is clean.

For more on choosing a playback approach for a continuous channel, compare this server-based workflow with the options in VLC vs OBS for 24/7 YouTube Live streaming in India. The tools differ, but the same checks on source material and event playback still matter.

Create the ffconcat playlist file

Create a plain-text file called playlist.ffconcat in a working directory alongside the media, or use paths that point clearly to where the files are stored. If you want automatic format recognition from the file contents, the first line must be exactly ffconcat version 1.0. The file entries then list the clips in the order you want them played:

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

Keep the marker as the first line, with no blank line or text ahead of it. In the command below, -f concat explicitly selects the concat demuxer, so the marker is not doing the only work of identifying the format, but retaining the exact header makes the file unambiguous and follows FFmpeg’s format convention.

Paths are interpreted by the process running FFmpeg. Relative paths are resolved in relation to the process’s working directory, not necessarily the directory you happened to be viewing in an interactive shell. If FFmpeg starts from a service manager, set its working directory deliberately or use absolute paths, then make sure the service account can read the playlist and every listed media file.

Spaces and special characters in paths need correct escaping or quoting according to the concat file syntax. For a first test, use simple filenames without spaces or apostrophes. That avoids confusing a playlist parsing issue with a media compatibility issue. If you do need complex paths, consult the concat demuxer documentation and test a short playlist with the exact filenames before leaving a process running unattended.

The example command uses -safe 0. This relaxes the demuxer’s default restrictions on paths, which can be useful when your playlist uses paths the default rules reject. It is not a general security setting to apply without thought: only use it with a playlist and paths you control and trust. Do not point an unrestricted playlist at files supplied by an untrusted source.

Loop the concat input continuously

The concat demuxer reads each listed file in sequence once. To repeat that sequence, place -stream_loop -1 among the input options, before the -i it applies to. The value -1 asks FFmpeg to loop the input indefinitely. The placement matters because FFmpeg options are order-sensitive: an input option after an input may apply somewhere else or fail to affect the intended input.

A representative command shape for compatible files is:

ffmpeg -re -stream_loop -1 -f concat -safe 0 -i playlist.ffconcat \
  -c copy -f flv 'rtmps://<youtube-ingest-endpoint>/<stream-key>'

Treat this as a pattern to adapt and test, not a recipe verified against your particular files, FFmpeg build, or YouTube event. -re reads the input at its native rate rather than sending prerecorded content as quickly as the process can read it. The loop option belongs before -i playlist.ffconcat; -c copy requests stream copy; -f flv selects the output container used by this command shape. Confirm that your actual output streams and current YouTube encoder requirements are compatible with that setup.

Looping the input does not guarantee uninterrupted availability. FFmpeg can stop because of a file read error, a full disk, a process termination, a network interruption or an ingest-side problem. A loop also cannot fill a gap created by bad timestamps, repair an incompatible file or make a stopped process restart. Test the end of the playlist returning to its beginning as carefully as the joins between individual clips.

If a channel is made from different sources or needs text overlays, transitions or audio processing, stream copy may no longer be the right output path. A filter or re-encoding workflow can offer control over the resulting format, but it adds configuration and uses more CPU. Prepare a short test output and inspect it before moving the process to a long-running event.

Add the YouTube Live ingest URL and key

In YouTube Studio’s Live Control Room, create or select the event and retrieve the stream URL and stream key shown for it. Use the exact endpoint and key provided there; do not substitute a URL copied from an unrelated example. YouTube’s live encoder settings guidance covers supported encoder settings and recommendations, while its RTMPS instructions explain the encrypted ingest connection.

The placeholder in the command must be replaced with the endpoint and key in the form expected by YouTube’s current event settings. Keep the key secret: YouTube treats it like a password. Avoid putting it in a public script, a shared repository, a support screenshot or logs that others can read. Restrict access to the account or configuration that contains it, and rotate the key through YouTube Studio if it is exposed.

The command’s -c copy leaves the source encoding unchanged. That is only appropriate when the resulting streams meet the requirements for the event and YouTube’s current encoder guidance. YouTube lists encoder options and recommended settings that vary by codec, resolution and frame rate; do not treat one bitrate as universally correct. Choose the applicable current guidance, and verify that the source files match what the output will actually send.

YouTube recommends keeping spare upload bandwidth above the stream bitrate; its streaming tips specify 20% headroom. That is guidance, not proof that a particular Hetzner server can sustain the load. Measure the outbound capacity available to your chosen host and account for other traffic. A plan’s headline network figure alone does not confirm the actual sustained throughput for your location and workload, so check current Hetzner details rather than assuming a particular plan is suitable.

For a first run, test privately or unlisted and inspect YouTube’s preview and stream-health messages before making the event public. Use sample content you are entitled to broadcast and check the current official YouTube pages for settings, account eligibility and event requirements. A successful FFmpeg connection does not itself establish that every YouTube event setting is correct.

Run on Hetzner with a recovery plan

On Hetzner, the server is where FFmpeg reads the files and maintains the outbound connection to YouTube. Put the media and playlist where the process can access them reliably, and check that the chosen host has enough disk space for the files and enough capacity to sustain the broadcast. This does not require assuming a specific Hetzner plan: suitability depends on your files, output bitrate, CPU needs and actual network conditions, so verify the current provider information and test your workload.

Keep the command and configuration in a place that the process can use after you disconnect from an SSH session. A foreground command in a terminal is easy to test but is not a recovery plan: closing the session or losing the connection may terminate the process. For a longer broadcast, use a process supervisor or service arrangement that can detect an exit and restart FFmpeg, and make sure its logs remain available for diagnosis.

A restart can restore a process, but it cannot make every failure invisible to viewers. If FFmpeg has stopped, YouTube may show a disconnected or unhealthy input until the encoder reconnects, and the live event itself may need attention. Decide who will receive an alert and who can act if the process repeatedly fails. Supervision should make recovery possible, not become a reason to stop checking the channel.

For some readers, maintaining a remote host, playlist paths, a protected key and process supervision is more operational work than they want. StreamNeo removes the need to keep a personal computer running for a file-based broadcast: you upload the video and connect your YouTube stream key, while the broadcast runs with monitoring and automatic restart if it drops. It is YouTube-only, so it does not replace a workflow that depends on direct FFmpeg control or a different destination.

Monitor FFmpeg logs and YouTube playback

Check the process logs from the start of the test, not only after a viewer reports a problem. Look for file-open errors, invalid data, timestamp warnings, connection failures and FFmpeg exit status. Save enough context to identify which file was playing and when the process stopped, but do not log the stream key. A repeating warning may be harmless in one test and significant in another, so compare it with what you hear and see in the YouTube preview.

Monitor YouTube’s Live Control Room during the test and while the channel is operating. Confirm the preview appears, audio is present, and stream-health indicators do not report a sustained issue. Keep a test viewer or a trusted person available to check playback from the audience side as well: the encoder’s local logs and YouTube’s ingest status do not prove that the final viewing experience is correct on every device.

If the preview freezes, first separate the possible causes. Check whether FFmpeg is still running and advancing through the playlist; check whether it can read the files and whether the server has disk and network capacity; then check the Live Control Room for ingest or event warnings. A single restart may restore a transient interruption, but repeated restarts without finding the cause can hide a bad file, a network bottleneck or a misconfigured output.

Plan for alerts on FFmpeg exit, repeated reconnects, low disk space and YouTube stream-health warnings. Also decide how to reach the host if remote access is interrupted. For longer events, understand YouTube’s archive behaviour: its guidance says streams under 12 hours are automatically archived, so do not assume an uninterrupted archive for longer streams. Check the current official event guidance if the recording matters to you.

A stable test should include the entire playlist cycle, including the last clip returning to the first. Leave the test running long enough to exercise the likely failure points, and check it from YouTube rather than relying only on a process that appears active. The guide to enabling live streaming in YouTube Studio can help if you need to check the channel-side setup, while the stream-key recovery guide is relevant if credentials are accidentally exposed.

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 loop an FFmpeg concat playlist forever?

Use -stream_loop -1 before the concat input it applies to, for example before -i playlist.ffconcat. The playlist still needs compatible files, and looping does not guarantee that FFmpeg, the server or the YouTube connection will remain available.

How do I stream prerecorded videos continuously to YouTube Live?

List compatible media files in a concat playlist, loop that input, then send the output to the exact ingest URL and stream key for the YouTube Live event. Test the whole sequence privately or unlisted, check YouTube’s current encoder guidance, and monitor both the process and Live Control Room.

Can I run FFmpeg nonstop on a Hetzner server?

You can run FFmpeg on a Hetzner server, but uninterrupted output depends on the files, process, host capacity and network connection. Check current Hetzner specifications for your workload, use supervision and alerts, and plan for recovery rather than treating a running command as a guarantee.

Does -c copy make different video files compatible?

No. It avoids re-encoding when the streams are already suitable, but does not reconcile mismatched codecs, time bases or stream layouts. Normalise the source files or use an appropriate conversion workflow, then inspect transitions before streaming publicly.

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 ↗