Skip to content
streamneo.
Troubleshooting13 min read

How to Use systemd to Restart an FFmpeg YouTube Stream Automatically

Configure systemd to restart FFmpeg after failures, handle start limits, inspect logs, and verify that YouTube has actually resumed.

sn.
StreamNeoPublished 4 October 2026
Worth sharing?

If you run FFmpeg on a Linux machine, systemd can restart it when the process exits unexpectedly. The usual starting point is Restart=on-failure, combined with a deliberate RestartSec= delay and a unit that runs FFmpeg directly.

That only supervises the local process. A restarted FFmpeg process does not prove that YouTube has resumed the public broadcast, so you must check both the service and the live viewing path.

Run FFmpeg as the service's main process

systemd works most reliably when FFmpeg is the service's main process. It starts the command, observes its exit status, and applies the restart policy when the process fails. You should avoid putting FFmpeg behind an unnecessary shell script, background operator, or second supervisor unless you have a specific reason to do so.

A command such as this is easier for systemd to supervise:

/usr/bin/ffmpeg [input and encoding options] -f flv rtmp://a.rtmp.youtube.com/live2/REDACTED_STREAM_KEY

The command above is an outline, not a complete streaming command. Replace the input and encoding options with those required by your file and your installed FFmpeg build. Do not publish a real stream key in an article, screenshot, shell history shared with others, or support request.

The binary may not be installed at /usr/bin/ffmpeg on your host. Check it with command -v ffmpeg, then use the resulting path in the unit. Also check the options supported by the installed release. FFmpeg's official documentation tracks the newest revision and notes that local documentation may be more appropriate for older installations.

Running FFmpeg directly matters because a shell can exit while a child process continues, or it can hide the exit code that systemd needs to classify the service result. Backgrounding FFmpeg with & is particularly unhelpful here: systemd may believe the command has finished even though another process is still attempting to stream.

You also need to decide what the service should do with its input. A finite video may finish cleanly, while a looped input should normally continue until you stop the service. That choice affects whether Restart=on-failure is appropriate. If the file reaches its natural end with exit code zero, systemd does not treat that as a failure under this policy.

For a channel based on prerecorded material, first confirm the overall workflow in how to stream prerecorded videos live on YouTube from India. systemd can supervise FFmpeg, but it cannot turn a one-time file into a deliberate continuous programme by itself.

Create and review the systemd unit

Create a service file such as /etc/systemd/system/youtube-ffmpeg.service with root permissions:

[Unit]
Description=FFmpeg YouTube livestream
Wants=network-online.target
After=network-online.target

[Service]
Type=simple
ExecStart=/usr/bin/ffmpeg [input and encoding options] -f flv rtmp://a.rtmp.youtube.com/live2/REDACTED_STREAM_KEY
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target

Type=simple tells systemd that the process started by ExecStart= is the service. That is a good fit for a foreground FFmpeg command. Wants=network-online.target and After=network-online.target express that the service should be started after the system's network-online target has been requested and ordered, although they do not repair a broken route, DNS problem, firewall rule, or remote ingest issue.

The five-second delay is an example rather than a universal setting. It gives a failed process a short pause before another attempt, but the right value depends on the reason for the failure. A connection that disappears briefly may benefit from a modest delay. A bad input path or invalid option will fail again regardless of the delay, and a very short delay can make the host repeatedly start and stop FFmpeg while producing a noisy journal.

Review the unit before starting it. Look for these common errors:

  • The ExecStart= path points to a file that does not exist.
  • The input path is relative, unavailable to the service account, or mounted only after boot.
  • The stream key is incomplete, copied with an extra space, or exposed in a file with unsuitable permissions.
  • FFmpeg has been placed in the background with &.
  • Options copied from another machine are not supported by the installed FFmpeg build.
  • The service account cannot read the video, access the network, or write any required temporary files.

Keep credentials in a protected configuration mechanism suitable for the host rather than embedding them in material you intend to publish. The unit shown here is a practical shape to adapt, not a tested universal command for every input, codec, or Linux distribution.

After editing the file, ask systemd to read the new definition:

sudo systemctl daemon-reload

If you change the unit later, run daemon-reload again. A reload makes systemd aware of the edited file; it does not necessarily replace an already running FFmpeg process with the new command. Use a service restart when you need the changed ExecStart= or policy to take effect.

Choose failure restarts and a sensible delay

For a long-running stream, Restart=on-failure is usually the clearest policy. It asks systemd to restart the service after a non-zero exit and after qualifying abnormal termination, operation timeouts, or watchdog failures. It does not restart a service that an administrator deliberately stops through systemd.

Restart=always is different. It also retries after a clean exit. That can be useful when every exit should lead to another launch, but it can conceal a clean end that you wanted to investigate. An FFmpeg command that reaches the end of a file normally is not the same diagnostic event as one that fails to open its input or loses its output connection.

Policy Clean FFmpeg exit Abnormal failure Deliberate systemctl stop Suitable when
on-failure Remains stopped Restarts Remains stopped A clean end should be visible and investigated
always Restarts Restarts Remains stopped Every process exit should normally be followed by another launch

Neither policy confirms that YouTube has published the stream again. They govern the local service process. The delay and the rate limit govern how often systemd attempts to launch it; neither one validates the remote broadcast.

RestartSec= is the pause before an automatic restart. Select it deliberately rather than treating an immediate retry as proof of resilience. If the first failure is caused by a temporarily unavailable network, a delay gives the connection and dependent services time to settle. If the failure is caused by a typo in the command, repeated attempts only make the same error appear more often.

The systemd service documentation describes the restart settings and the conditions under which they apply. Read the documentation for the systemd version installed on the target machine, especially if you are copying additional service options from a different distribution.

A restart policy also does not detect every kind of stream failure. If FFmpeg remains alive but its output is stalled, systemd may see a healthy process and do nothing. Detecting that condition requires a separate health check or watchdog design based on the actual command and the behaviour you need to measure. Test such a check carefully before making it responsible for stopping a live service.

Understand start-rate limits and the failed state

A service that fails immediately should not be launched without restraint. systemd applies start-rate limiting, so repeated failures within the configured interval can eventually cause further starts to be refused. This protects the host from a tight restart loop, but it can surprise you when Restart=on-failure appears to have stopped working.

The relevant settings include StartLimitIntervalSec= and StartLimitBurst=. Their accepted form and default behaviour can depend on the installed systemd release and the unit configuration. Check man systemd.unit on the target host instead of blindly copying values from a guide written for another distribution.

Rate limiting is not a fix for the underlying fault. If FFmpeg exits because the input file is missing, the stream key is wrong, the encoder options are invalid, or the network is unavailable, changing the limit only changes how long systemd keeps attempting the same unsuccessful operation. Inspect the first useful FFmpeg error before deciding to increase retry activity.

When the limit has been reached, systemctl status may show a failed state and a message indicating that start requests were repeated too quickly. The journal usually provides the more useful sequence: when FFmpeg started, why it exited, when systemd attempted the next start, and when the rate limit prevented another attempt.

systemctl reset-failed clears the unit's failed state and its start-rate counter. It does not repair a credential, input, route, or encoding problem. Use it only after you have reviewed the cause and decided that another start is appropriate:

sudo systemctl reset-failed youtube-ffmpeg.service
sudo systemctl start youtube-ffmpeg.service

The systemctl reset-failed documentation explains this reset operation. Resetting the counter is a recovery step, not a way to create unlimited retries. A service that fails immediately can hit the limit again.

Enable and start the service

Once the unit has been reviewed, start it manually first. This separates configuration errors from boot-time behaviour:

sudo systemctl start youtube-ffmpeg.service
systemctl status youtube-ffmpeg.service

Read the status output for the active state, the main process identifier, recent exit information, and the latest journal lines. If the service fails, do not repeatedly start it before reading the error. Rapid manual starts can also contribute to the unit's start-rate limit.

For a service that should start when the machine boots, enable it and start it together:

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

enable creates the boot-time relationship described by [Install]; --now starts the service immediately as well. Enabling a unit does not mean FFmpeg is currently running, and an active service does not mean it will automatically start at the next boot unless it has been enabled.

After the first start, check the exact command systemd is using and the account under which it runs. A command that works in your interactive shell can fail as a service because its environment, home directory, permissions, PATH, mounted storage, or network readiness differs. Use absolute paths and explicit file locations in the unit rather than relying on shell customisation.

If you normally keep an FFmpeg process alive with tmux, understand the difference before changing supervisors. The practical trade-offs are covered in how to keep an FFmpeg YouTube stream alive with tmux on a VPS. tmux preserves an interactive session; systemd provides service lifecycle and restart semantics. Do not run both supervisors against the same stream unless you have deliberately designed for that arrangement.

Verify the YouTube broadcast, not just the process

The most important check is the distinction between local process recovery and public broadcast recovery. systemctl status youtube-ffmpeg.service can show an active FFmpeg process while YouTube is still not presenting the intended broadcast to viewers. Conversely, a process may have just restarted while the platform is still processing the new ingest connection.

Use two separate checks:

  1. Confirm that systemd has a current FFmpeg main process and that the journal shows a successful connection attempt rather than another immediate exit.
  2. Open the relevant YouTube Studio view and the actual viewer endpoint, then confirm that the intended public broadcast is live and showing current content.

The second check matters because the public result is the thing your viewers experience. A process identifier changing only proves that systemd launched another process. It does not prove that the stream key was accepted, that the intended broadcast was selected, that frames are arriving as expected, or that the public page is showing the current programme.

Do not infer success from one green status indicator. Watch the output long enough to distinguish a connection that stays established from a connection that repeatedly opens and drops. Check the content itself as well: a frozen frame, an old segment, or silence can be a delivery problem even when FFmpeg remains active.

YouTube's current interface and broadcast behaviour can change, so use the relevant YouTube Help guidance for the account and broadcast controls you see. This article does not promise that systemd can restore a public broadcast after every failure. If the broadcast has ended, been made private, or requires a new action in YouTube Studio, restarting FFmpeg alone may not restore it.

For a channel intended to run while you are away, also consider what viewers see during recovery. A devotional loop, study room, shop promotion, or local news sequence needs a known starting point after FFmpeg restarts. The planning considerations for a continuous study channel are discussed in how to stream a 24/7 virtual library study room on YouTube. Treat that editorial plan separately from the Linux process policy.

If maintaining a Linux host, its storage, updates, permissions, and logs is more work than you want to operate overnight, StreamNeo removes the need to keep your own computer running for this upload-once-to-YouTube workflow, with automatic monitoring and restart handling for the stream. It remains a YouTube-only option, and you should still verify the resulting public broadcast rather than assuming that any automated process guarantees publication.

Recover from repeated failures and inspect logs

Start recovery with evidence. Follow the service journal while making one controlled start attempt:

journalctl -u youtube-ffmpeg.service -f

For a bounded review of recent entries, use a command such as:

journalctl -u youtube-ffmpeg.service --since "15 minutes ago"

The time expression is only a viewing choice; use a period that covers the failure. Look for the first FFmpeg error, not just the final systemd message. The final message may say that the process exited, while the earlier lines explain whether the input could not be opened, an option was rejected, authentication failed, or the network connection was lost.

A useful recovery sequence is:

  1. Stop repeated attempts if they are creating noise or competing with manual testing.
  2. Read the journal from the first failure.
  3. Check the input file, permissions, binary path, command syntax, network route, and protected credentials.
  4. Confirm whether the YouTube broadcast still exists and is the intended one.
  5. Correct the underlying problem.
  6. Run daemon-reload if the unit changed.
  7. Use reset-failed only when the rate limit or failed state is blocking an otherwise appropriate restart.
  8. Start the service and verify both the process and the public viewer endpoint.

A clean service restart is not always the right response. If the file is corrupt, the network is unavailable, or the stream has been stopped in YouTube Studio, repeatedly launching FFmpeg can obscure the real issue. If the process stays alive but the output stops, investigate a health check rather than simply increasing Restart= activity.

When you change restart settings, test the policy with a controlled failure on a non-public or low-risk setup. Confirm what happens after a non-zero exit, after a clean exit, after an administrator stop, and after repeated rapid failures. Then test a genuine viewer check. A service can behave exactly as configured and still fail the broader goal of restoring the public stream.

For the same reason, keep a written runbook beside the host. Record the unit name, the safe way to reload it, the journal command, the location of protected configuration, and the YouTube Studio check. Do not record the real stream key in the runbook. A short recovery procedure is more useful at dawn than a unit file whose behaviour nobody can explain.

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 Restart=on-failure restart FFmpeg after every stream problem?

It restarts after qualifying process failures, timeouts, and similar service-level failures. It does not necessarily detect a stalled output while FFmpeg remains running, and it does not override a deliberate systemd stop. It also does not guarantee that YouTube resumes the public broadcast.

Why did systemd stop retrying my service?

The unit may have reached its start-rate limit after repeated failures. Read the journal and fix the first FFmpeg error, then use sudo systemctl reset-failed youtube-ffmpeg.service when another start is appropriate. Resetting the state clears the counter but does not fix the cause.

Should I use Restart=always instead?

Use always only when a clean FFmpeg exit should also cause a new launch. on-failure is clearer when a normal end should remain visible for investigation. Neither policy is better for every command, and neither confirms YouTube delivery.

How do I know the stream really came back?

Check the systemd status and journal, then check YouTube Studio and the public viewer endpoint. A new FFmpeg process is only local evidence. The final test is whether the intended broadcast is live and showing current content to 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 Troubleshooting guides ↗ · All topics ↗