Skip to content
streamneo.
Setup Guides13 min read

How to Use Docker to Run a Continuous FFmpeg YouTube Stream

Run FFmpeg in Docker for a looping YouTube Live stream, with practical guidance on setup, stream keys, restart limits and testing.

sn.
StreamNeoPublished 4 October 2026
Worth sharing?

Docker can run FFmpeg as a container and send its output to a YouTube Live stream. For a continuous FFmpeg YouTube stream, the useful pattern is to keep FFmpeg in the foreground, mount the source media, and let Docker restart the container if that process exits; this does not prevent every interruption.

The container, the FFmpeg process, and YouTube’s ingest are separate parts of the setup. A restart policy can respond to some process failures, but it cannot repair a broken host, network, media file, stream key, or YouTube ingest path.

How Docker, FFmpeg and YouTube Live fit together

Docker packages a process and its runtime environment in a container. In this setup, FFmpeg is that process: it reads a file or other input, encodes or repackages audio and video, and sends the resulting stream to the ingest URL supplied by YouTube Live Control Room. YouTube receives that feed and makes the live broadcast available to viewers according to the stream’s settings.

These pieces have different responsibilities. The container provides a repeatable environment; FFmpeg handles media input and output; YouTube handles ingest and delivery. Docker does not decide whether your video is suitable for YouTube, and YouTube does not restart your local FFmpeg process when it exits.

For a prerecorded loop, FFmpeg can read a file repeatedly and pace it in real time. The input needs to be readable at the path visible inside the container. The output needs to use a protocol, video and audio codecs, keyframe interval, and bitrate appropriate to the current YouTube guidance and the connection you have measured. A command that starts successfully is not proof that the whole path remains healthy.

This distinction matters overnight. A Docker restart policy may bring FFmpeg back after a process exit, but it will simply repeat the same failure if the command is wrong, the media is unreadable, or the credentials are invalid. If you are comparing a container workflow with an encoder focused on 24/7 ambience, the practical distinctions in OBS and FFmpeg for an ambient stream can help you decide which process you are prepared to maintain.

Prepare media, Docker and YouTube stream details

Start with an always-on host that can run Docker Engine, or a hosted runtime that you have selected after considering its current costs, access and operating responsibilities. A local machine may be easier to inspect and troubleshoot, but it depends on that machine’s power and network. A hosted machine can be managed remotely, but it still depends on its provider, configuration and network path. Do not assume CPU, GPU or upload capacity will be sufficient without measuring the specific encode and stream.

Put a known-good media file in a dedicated host directory. For example, /srv/youtube-media can hold loop.mp4. Check that the file plays and has the intended duration, picture and sound before using it as the container’s input. If a playlist loops a large file, pay attention to read performance and the way FFmpeg reaches the end and returns to the beginning; troubleshooting notes on freezes when a large video repeats cover a related failure pattern.

Create or select a live stream in YouTube Studio’s Live Control Room. Copy the current ingest server URL and stream key from there rather than relying on an old value saved elsewhere. Treat the key like a password: do not place a real key in a public repository, an example script you share, or a public terminal recording. If it is exposed, reset it in Live Control Room and update the encoder configuration.

A read-only bind mount is a straightforward way to make source media visible without allowing the container to change it. Docker’s bind mount documentation describes how a host directory can be mounted into a container; the readonly option is useful when FFmpeg only needs to read input. This keeps the source file on the host rather than putting it in the container’s writable layer.

Before moving on, verify the Docker daemon is available, the media path is correct, and the Live Control Room values are current. If you are still deciding where to run an always-on channel in India, compare the administration and network trade-offs in this Google Cloud host setup guide. The figures and provider terms in any hosting comparison should be checked against the provider’s current site before you commit.

A repeatable Docker and FFmpeg launch pattern

The main process in the container should be FFmpeg, not a shell that exits while a detached encoder runs in the background. When FFmpeg stays in the foreground, Docker can observe its exit and apply the configured restart policy. If you use an entrypoint script, end it by executing FFmpeg with exec, so the process and its exit status are visible to Docker.

The following is an illustrative command for a local looping file. It assumes H.264 video, AAC audio and 30 frames per second, and is not a universal or tested preset for every file, host or channel:

ffmpeg -re -stream_loop -1 -i /media/loop.mp4 \\
  -c:v libx264 -preset veryfast -b:v 4500k -maxrate 4500k -bufsize 9000k \\
  -g 60 -r 30 -c:a aac -b:a 128k \\
  -f flv "$YOUTUBE_RTMP_URL/$YOUTUBE_STREAM_KEY"

Here, -stream_loop -1 requests repeated playback of the input and -re paces a file as though it is being read in real time. The output options are examples to explain the shape of the command, not a recommendation to use those exact values. Confirm that your FFmpeg build includes the requested encoder, check the locally installed ffmpeg -h output when options behave differently, and use the URL and protocol format shown in your current Live Control Room.

Wrap that command in an image whose entrypoint executes it, or pass an equivalent command when launching the container. A representative launch shape is:

docker run -d --name youtube-ffmpeg \\
  --restart unless-stopped \\
  --mount type=bind,src=/srv/youtube-media,dst=/media,readonly \\
  --env-file /etc/youtube-stream/stream.env \\
  your-ffmpeg-image:tag

This example assumes that the image already contains FFmpeg and knows how to use the environment variables to form the command. The environment file needs to exist on the host and contain the URL and key in the format your entrypoint expects. Do not paste a live key into a public image definition or commit the environment file to source control. Limit access to the file and its parent directory. Environment variables are not invisible to every privileged host administrator, so use an access-controlled secret mechanism where your deployment supports one.

Keep the image and command understandable enough to reproduce. Record which image tag you used, the input filename, the command options, and where the secret is supplied. If an image changes unexpectedly, or the command depends on an encoder missing from its FFmpeg build, that record narrows down what to check. Avoid treating an image label as a substitute for checking the actual FFmpeg version and available encoders.

Choose an image and mount the source media

There are two practical routes: choose an image that already contains a suitable FFmpeg build, or build an image from a base environment you can maintain. Either route needs an explicit FFmpeg command and an entrypoint that leaves it in the foreground. Check the image’s own documentation for its entrypoint behaviour, supported codecs and update process. Do not assume an image contains libx264 simply because it contains an ffmpeg executable.

Building your own image gives you control over the installed packages and version, but you become responsible for rebuilding and testing it when you change the base image or FFmpeg. Choosing an existing image can reduce initial setup work, but you still need to check who maintains it and what it contains. This is a maintenance choice, not a guarantee of better stream quality.

Mount the source directory read-only using the Docker command shown above. The source path before src= is on the host; /media after dst= is the path inside the container. FFmpeg must use the container path, such as /media/loop.mp4, not the host path. A path typo or an unreadable file will prevent the input from opening; Docker cannot correct either problem.

If the source changes, decide deliberately how it reaches the container. Replacing a file under the mounted directory may affect a running process in ways that depend on how it opened the input. For a controlled update, stop and restart the container after checking the replacement file. If you need a playlist rather than one looping file, test the list and its transitions separately; a playlist adds more paths and input boundaries that can fail.

Set FFmpeg output and protect the stream key

YouTube’s current encoder guidance supports RTMP or RTMPS, several video codecs, AAC or MP3 audio, and constant bitrate encoding. YouTube recommends RTMPS because it encrypts the feed in transit to Google’s servers. Check the current YouTube encoder settings for the full combination of codec, resolution, frame rate and bitrate that applies to your intended stream; the table can change, and a published recommendation is not a promise about your connection.

As one example of how specific the table is, YouTube Help’s encoder-settings table lists 1080p at 30 fps with H.264 as a 5 Mbps minimum and 14 Mbps recommended, accessed 3 October 2026. That is YouTube’s guidance for that format, not a measurement of what your host can sustain. Measure upstream capacity during the conditions in which the channel will run, then leave practical headroom instead of allocating all available upload capacity to the stream.

YouTube recommends a two-second keyframe frequency and says not to exceed four seconds. At 30 fps, -g 60 in the example corresponds to two seconds because it sets a group of 60 frames. If you change the frame rate, revisit the keyframe setting rather than keeping -g 60 automatically. Match audio and video settings to the media and the current YouTube table, then check the resulting stream health in Live Control Room.

The stream key is part of the destination, but it should not be visible in shared scripts or logs. Using variables keeps it out of the command text you distribute, though it does not remove the need to protect the environment file or restrict access to the host. If you accidentally publish the key, reset it in Live Control Room and replace the stored value before restarting the encoder. A key that has been revoked or copied by someone else cannot be repaired by a Docker restart.

Restart policies, logs and failure boundaries

Docker’s restart policy documentation explains how policies control whether containers start after they exit or after the Docker daemon restarts. For this example, unless-stopped asks Docker to restart the container after an exit and after a daemon restart, except where an operator has deliberately stopped it. always differs after a manual stop and subsequent daemon restart, so choose intentionally. Docker documents that restart policy activation occurs only after a container has been up successfully for at least 10 seconds.

A restart policy is useful when FFmpeg exits unexpectedly and the container’s command is otherwise valid. It does not provide end-to-end high availability. It will not restore power to a failed host, fix a broken network, recreate missing or corrupt source media, correct a malformed command, make an invalid key valid, or force YouTube’s ingest to accept a feed. If FFmpeg repeatedly exits for the same reason, automatic restart can repeat the failure rather than resolve it.

Use a deliberate recovery design. For a simple process exit, begin with Docker’s policy and inspect the resulting logs. If you add a wrapper that retries output after a disconnect, make its delays and stopping conditions explicit and observe its behaviour under test. Avoid a busy loop that launches repeated attempts without pause. HTTP input reconnect options documented by FFmpeg apply to HTTP input behaviour; they are not a magic recovery switch for RTMP output to YouTube.

Inspect container status with docker ps, follow output with docker logs -f youtube-ffmpeg, and view its restart count with docker inspect -f '{{.RestartCount}}' youtube-ffmpeg. Logs can reveal an unreadable input, missing encoder or failed connection, but the stream key should not be printed there. If FFmpeg reports a destination error, verify the current URL and key in Live Control Room before changing unrelated encoding options.

For a more specific process-exit workflow, see how to restart a YouTube live stream after FFmpeg exits. The important limit remains the same: successful process recovery is not proof that viewers are receiving a healthy picture and sound.

Test the broadcast and monitor it

Test the complete path before you make the channel public or rely on it overnight. YouTube Help’s official encoder guidance says, “Make sure to test before you start your live stream.” Use audio and movement similar to the real programme, not just a static desktop or short silent clip. Monitor stream health and messages in Live Control Room while the encoder is running.

Check that the intended stream appears, the picture is correct, audio is present and synchronised, and the bitrate is compatible with the capacity you measured. Watch beyond the first successful connection. For a loop, observe the transition at the file boundary, when FFmpeg returns to the beginning. The goal is to discover what happens in your actual setup, not to infer reliability from a command that has only run for a few minutes.

Exercise the failure cases you can control. Stop the container manually and confirm what the selected policy does; then test a process exit in a safe setting and check whether Docker starts it again. A deliberate network interruption can show whether FFmpeg exits, stays stuck, or reports an error, but it cannot prove the network will recover the next time. Check the logs and restart count after each test so you know what evidence to look for during a real fault.

Also confirm what happens when the source ends or becomes unavailable. -stream_loop -1 requests repetition, but a corrupt file or missing mount is a different condition. A restart cannot make an absent source readable. YouTube’s encoder setup guidance says streams under 12 hours are automatically archived; if you need an archive, plan around that stated limit and check the current official guidance before relying on it for a long-running broadcast.

A practical handover note should include the container name, image tag, input path, where the key is stored, the restart policy, and the commands used to inspect logs and status. Keep a copy somewhere available if the host itself fails. For channels that cannot be watched continuously, that note makes it easier for another person to distinguish a process restart from a YouTube-side or host-side problem.

If maintaining the host, image, secret file and failure checks is more work than your channel needs, consider a managed workflow instead. StreamNeo addresses the specific burden of keeping your own computer on to carry the broadcast: you upload the video once, provide the YouTube stream key, and the broadcast runs with your computer off, with monitoring and automatic restart if it drops. It remains YouTube-only, and you should still test your content and confirm the live result in YouTube Studio.

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 Docker keep a YouTube stream live if my computer or host fails?

No. A restart policy can restart a container after certain process exits, but it cannot recover a powered-off host, repair its network, or guarantee that YouTube will accept a new connection. If host failure is a concern, assess the host and network separately and test the recovery path you choose.

Should FFmpeg run as the container’s main process?

Yes. Keeping FFmpeg in the foreground lets Docker observe its exit and apply the container’s restart policy. If an entrypoint script launches it, use exec so FFmpeg replaces the shell and its exit status reaches Docker.

Can I use the example bitrate and keyframe value unchanged?

Treat them as illustrative values, not a universal preset. Check YouTube’s current encoder table for the intended codec, resolution and frame rate, measure your upload capacity, and adjust the command to fit both. At 30 fps, -g 60 represents a two-second interval; changing the frame rate changes that relationship.

What should I check if the container restarts but the stream does not return?

Read the FFmpeg logs, confirm that the input file is readable, and check that the current ingest URL and key still match Live Control Room. Then inspect whether YouTube reports a stream-health issue and whether the host still has connectivity. A restart count shows that Docker restarted a container; it does not show that the stream reached viewers.

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 ↗