Skip to content
streamneo.
Setup Guides10 min read

YouTube 24/7 Stream Stops After FFmpeg Exits: systemd Restart Setup

Configure systemd to restart FFmpeg deliberately, handle retry limits and verify whether YouTube Live has actually recovered.

sn.
StreamNeoPublished 5 October 2026
Worth sharing?

When FFmpeg exits, systemd can start it again if the service is configured to supervise FFmpeg and the restart policy matches the exit. That is process recovery, not proof that YouTube has resumed a healthy public stream; check the Live Control Room after each recovery.

The useful setup is deliberate: run FFmpeg in the foreground as the service’s main process, choose whether clean exits should restart, set a pause between attempts, and understand the host’s start-rate limits. The command and unit below are patterns to adapt, not universal FFmpeg settings.

First establish that FFmpeg is exiting

A stream that appears to stop is not always an exited FFmpeg process. The encoder can remain alive while its input, network path, or connection to YouTube is failing. Conversely, an FFmpeg process can exit while the YouTube control page still shows a preview or a recent connection. These are separate observations, so check both the process and the broadcast.

On the Linux host, inspect the service state and recent journal entries. Substitute your unit name for youtube-stream.service:

sudo systemctl status youtube-stream.service
sudo journalctl -u youtube-stream.service

Look for the exit status, the time of the last exit, and whether systemd attempted a new start. The journal may also show a missing input file, an invalid option, a permission problem, or an output connection error. Those details matter: a restart policy repeats the command, but it cannot make an invalid command or unavailable source work.

If you currently launch FFmpeg from a terminal, first run the exact invocation interactively and note what happens when the stream stops. Keep credentials out of shell history and diagnostic output where possible. YouTube’s encoder setup instructions describe the server URL and stream key used by an encoder. Treat the key as a credential: do not put it in a public example, repository, or log.

Also distinguish a process exit from a stalled output. If FFmpeg is still running, systemd has no process exit to react to. Investigate the input and output behaviour before assuming a restart policy will solve it. A useful broader comparison is FFmpeg or OBS for a continuous channel, which helps frame what the encoder itself is responsible for.

Make FFmpeg the foreground ExecStart= process

Systemd needs to supervise the process whose exit should trigger the policy. Put the FFmpeg executable and its arguments directly in ExecStart=. Do not append &, send it into the background, or use a wrapper that exits while FFmpeg carries on. If the supervised shell ends normally, systemd may consider the service finished even though that is not the failure you intended to monitor.

A unit can have this shape:

[Unit]
Description=YouTube FFmpeg live stream

[Service]
Type=simple
ExecStart=/usr/bin/ffmpeg [input and encoding options] -f flv [YouTube Live output URL using a protected stream key]
Restart=on-failure
RestartSec=10s

[Install]
WantedBy=multi-user.target

Every bracketed item is a placeholder, not text to copy literally. Replace the executable path, input, encoding options, output URL, and credential handling for your host and stream. The example’s 10s delay is illustrative only. It is not a general recommendation, and this template does not establish a universal codec, bitrate, resolution, input, or output protocol. Confirm the FFmpeg invocation works for your material and consult the installed systemd documentation for the unit syntax your host supports.

If you use a shell script for setup or credential handling, make sure the process systemd tracks is still the long-running FFmpeg process. A script can use exec to replace itself with FFmpeg, but its behaviour depends on how you have written it. Avoid relying on a background child and a shell that exits. The point is not to avoid every wrapper; it is to make the supervised main process and its exit meaningful.

YouTube’s encoder guidance is the source for the server URL and key, while the actual encoding arguments depend on your content and setup. If you are deciding output dimensions as well as service supervision, use a separate resolution planning guide rather than treating the sample unit as encoding advice.

Choose what Restart= should mean

Restart= is a policy choice, not a generic “keep trying no matter what” switch. For many unattended stream services, Restart=on-failure is a sensible starting point because it asks systemd to retry after a qualifying failure. The systemd project’s systemd.service manual documents cases including a non-zero exit, certain signals, operation timeouts, and watchdog timeouts.

A clean exit is different. With on-failure, a process that ends successfully is not treated like a failed exit for restart purposes. Consider Restart=always only if a clean FFmpeg exit should also cause another run. That might fit a command expected never to finish, but it can also turn a deliberate end into an unwanted new stream attempt. Decide what a normal completion means for your channel before selecting the policy.

Policy What it is for Important trade-off
Restart=on-failure Retry after qualifying failures A clean exit does not call for a restart under this policy
Restart=always Restart after exits, including clean ones A command that was meant to finish can be started again
No automatic restart Leave recovery to an operator or another process An exit requires you to notice and act

The table is a practical summary, not a substitute for the installed manual. Systemd has specific rules and exceptions around exit status and signals. An intentional systemctl stop is an administrative stop; do not configure a loop designed to undo an operator’s decision to stop the service. If clean endings are part of your workflow, decide whether they indicate completion or failure and set policy accordingly.

For a 24/7 loop, it is tempting to equate “always restart” with “always live”. Resist that shortcut. A repeated bad key, missing media file, or unreachable network can produce repeated process starts without restoring the broadcast. Policy should make a recoverable exit less manual, not hide a persistent fault.

Set a deliberate RestartSec= pause

RestartSec= controls how long systemd waits before attempting a restart. Leaving no meaningful pause can produce a quick sequence of failures when the cause is persistent. A measured delay gives you time to observe attempts in the journal and avoids treating every failure as if the next immediate launch will fix it.

There is no single delay that fits every channel. A local file that is briefly unavailable, a transient network interruption, and a consistently invalid command have different causes and operational consequences. Choose a pause with the expected failure mode in mind, then watch what happens during a real test. The 10s in the earlier template is only an example of syntax, not a sourced value for your service.

Do not confuse the restart delay with recovery time. After the pause, FFmpeg still has to open its input, initialise encoding, and connect to YouTube. The stream may then need checking in the Live Control Room. If you need the channel to resume at a particular point in a programme, process restart alone may also be the wrong measure of continuity: it does not ensure that viewers see an uninterrupted segment.

Account for systemd start-rate limits

Systemd can limit how often a unit starts. The StartLimitIntervalSec= and StartLimitBurst= settings govern this behaviour on releases that support these names; the precise defaults and applicable options depend on the installed systemd version and configuration. A persistent fault can therefore lead to several failed attempts followed by rate limiting. Once that happens, the unit may stop trying until the limiting condition has cleared or an operator intervenes.

That behaviour is useful as a guard against a tight failure loop, but it can surprise someone who expects infinite retries. If FFmpeg repeatedly exits, inspect systemctl status and the journal for start-limit messages instead of repeatedly changing Restart=. Check the host’s installed systemd.service and systemd.unit manuals; the current upstream manual may document options that an older distribution release does not support or name differently.

The practical order is to identify the first failure, correct it, then decide whether your retry rate is appropriate. If the input path is wrong, allowing more rapid attempts only repeats the same error. If you are operating an always-on channel from a remote host, build a way to check its state and reach the logs; remote monitoring considerations for a 24/7 stream are relevant even when the encoder is not running on a desktop.

Install and activate the service carefully

Save the unit under a clear name, such as /etc/systemd/system/youtube-stream.service, after adapting the command and policy. Then ask systemd to read the unit and start it:

sudo systemctl daemon-reload
sudo systemctl enable --now youtube-stream.service

enable arranges for the service to start according to the unit’s install target when the system boots; --now also starts it immediately. If you intend a manually started service that should not return after reboot, do not enable it simply because the example includes an install section. The intended operation matters: a 24/7 channel on a host expected to reboot and come back differs from a test run you plan to stop yourself.

After changing a unit, run daemon-reload so systemd reads the updated configuration, then restart the service if it is already running. Confirm the loaded state with systemctl status and inspect the journal. Avoid putting a real stream key in the unit if your access controls or process visibility make that unsafe; use a protected configuration mechanism appropriate to your distribution and ensure it does not leak through logs or source control.

Test the service before relying on it overnight. YouTube recommends testing the encoder setup and monitoring stream health and messages during an event in its live encoder settings guidance. A brief supervised test can establish whether the command starts and whether systemd sees the expected process, but it cannot predict every later network or input failure.

Verify the broadcast, not only the process

A successful systemctl restart or an active (running) status tells you something about the local service. It does not tell you that the stream is healthy, visible to viewers, or public. After FFmpeg restarts, open YouTube Live Control Room and check the stream preview, health notices, encoder connection details, and messages. YouTube’s recommendations to test and monitor the event are a reason to include this check in your normal operating routine, not just during initial setup.

A useful recovery sequence is to compare timestamps. First note when FFmpeg exited in the journal. Then note whether systemd started it again and whether FFmpeg remained running. Finally check when the Live Control Room reports a connected encoder and whether its health indicators show a problem. These observations separate a supervision failure from an encoder, credential, input, or YouTube connection issue.

If the process is running but the preview is absent or unhealthy, do not keep restarting blindly. Check that the correct Live server URL and stream key are being used, that the output arguments match the channel configuration, and that the source is still available. If the process has exited repeatedly, use the first relevant error in journalctl -u youtube-stream.service to diagnose the cause rather than focusing only on the last retry.

A live stream can also be healthy in the encoder while the public viewing experience differs from what you expect. Confirm the intended event and visibility in YouTube as well as the incoming preview. For a channel built around prerecorded material, review the separate question of playing an event replay continuously; systemd supervises the command, not the programming decisions or YouTube event settings.

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

Will systemd restarting FFmpeg guarantee that my YouTube stream is live?

No. It can restart the local process when the selected policy applies, but the process can still fail to open its input or connect correctly. Verify the preview and health information in YouTube Live Control Room before treating the broadcast as recovered.

Should I use Restart=on-failure or Restart=always?

Use on-failure when you want retries for qualifying failures but not after a clean exit. Use always only when a clean exit should also lead to another run. Read the installed systemd manual and account for deliberate operator stops and the way your FFmpeg command ends.

Why did systemd stop retrying after FFmpeg exited several times?

The unit may have encountered a start-rate limit, or the service may not be configured for the exit condition you saw. Check systemctl status and journalctl -u <unit> for the reason, then consult your installed systemd.unit and systemd.service manuals before changing limit settings.

What should I check first when FFmpeg starts again but the stream does not?

Check the FFmpeg journal for input, option, authentication, or output errors, then inspect the YouTube preview, health notices, and encoder connection details. A running process and a recovered public stream are separate things.

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 ↗