If FFmpeg exits while publishing a prerecorded video to YouTube Live from a Contabo VPS, systemd can start the process again according to a restart policy. That local restart does not guarantee that YouTube will continue the same live event, resume at the same media position, or show an uninterrupted broadcast.
There are two different recovery layers to consider: systemd can restart an exited FFmpeg process, while FFmpeg’s FIFO muxer can attempt to recover from some output errors without exiting. This guide shows how to set up and inspect a service, when FIFO recovery may help, and why you must check the result in YouTube Studio.
Understand the two recovery layers
A systemd service supervises a process. If FFmpeg exits in a way covered by the service’s Restart= setting, systemd can launch it again. It does not repair the command, make an unavailable input file readable, correct a bad stream key, or confirm that YouTube has accepted the new connection.
The FIFO muxer works at a different point. When configured for recovery, it can retry an output operation for certain errors while the FFmpeg process remains alive. That may avoid a process exit, but it cannot resolve every fault. A persistent network problem, invalid credentials, unsupported input, or a YouTube-side broadcast-state issue may remain after retries.
| Recovery approach | What triggers it | What happens to FFmpeg | What you still need to check |
|---|---|---|---|
| systemd restart policy | FFmpeg exits in a way matched by the policy | systemd may start a new process after the configured delay | Why the process exited, whether its input is valid, and whether YouTube is receiving the broadcast |
| FFmpeg FIFO recovery | An eligible output error occurs | FFmpeg may keep running and retry output | Whether retries are succeeding, whether content was lost or delayed, and whether YouTube shows the expected live state |
A restarted command may begin the file again, continue from a configured position, or behave differently depending on how the command and input are set up. Do not assume it resumes at the exact frame of failure. Likewise, reconnecting to YouTube does not by itself establish that the original event continues as intended. The key distinction is process recovery versus broadcast recovery.
Before changing anything, identify the layer that failed: FFmpeg process, media input, outbound network, YouTube ingest or broadcast state, or firewall. For context on network-side interruptions, see this guide to firewall rules that can close a YouTube publishing connection. Keep the stream key private while diagnosing; do not paste it into tickets, screenshots, or commands you share publicly.
Create a systemd unit for FFmpeg
A unit file gives systemd a persistent definition of the command, its working directory, restart behaviour, and log destination. The example below is a starting point to adapt, not a tested configuration. No VPS or stream was accessed for this guide, and you should check the directives supported by the systemd version installed on your server.
Create a service file, for example:
[Unit]
Description=FFmpeg YouTube live stream
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
User=stream
WorkingDirectory=/home/stream
ExecStart=/usr/bin/ffmpeg -re -stream_loop -1 -i /home/stream/loop.mp4 -c:v copy -c:a copy -f flv "rtmp://YOUR_INGEST_ENDPOINT/YOUR_STREAM_KEY"
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
Replace the user, paths, media, and output endpoint with values appropriate to your system and current YouTube setup. The example assumes FFmpeg is at /usr/bin/ffmpeg; check its location with command -v ffmpeg. Do not put a real stream key in a public article, screenshot, or shared diagnostic output. Restrict access to the service file if it contains a credential, or use a credential-management approach suitable for your system.
The sample loops a file, but the input and encoding options are not universal. Copying streams only works when the media already has compatible streams for the target. If FFmpeg needs to encode, choose settings based on the source material and current YouTube guidance rather than copying an arbitrary command. For a workflow that is based on prerecorded material rather than VPS administration, this explanation of streaming recorded lessons without leaving a computer on may help you compare approaches.
The Wants= and After= lines express an ordering relationship with network-online.target; they do not prove that the network can reach YouTube or that the remote ingest is available. Network readiness services vary between distributions. If you are unsure how your machine handles them, consult its distribution documentation and inspect its boot behaviour rather than treating these lines as a connectivity test.
Choose a restart policy and deliberate delay
Restart=on-failure is a common choice when you want an abnormal exit to be retried but an intentional clean stop to remain stopped. Restart=always is broader: it can also restart after a clean exit, which may be useful for a command that is meant to run continuously but can make a deliberate stop harder to maintain. Select the policy that matches the way you operate the channel; neither setting can determine whether an exit was caused by a correctable problem.
RestartSec=10 in the example inserts a pause before a restart. This is an example value, not a universal recommendation. A delay gives logs and dependent services a little breathing room and avoids an immediate tight loop, but a long delay means a longer period without FFmpeg running. A short delay can repeatedly retry a fault that needs human attention.
Also consider systemd start-rate limits. If the process repeatedly exits, systemd may eventually stop attempting to start it until the limit is cleared or the service is otherwise reset. The exact directives and behaviour can vary by systemd release and local configuration. Check the installed systemd.unit and systemd.service manual pages, and inspect the effective unit before relying on a specific limit or directive.
A restart policy is not a substitute for deciding what should happen after a persistent failure. If the input file has been moved, the stream key is invalid, or the command itself has an error, repeated starts can produce repeated failures. The useful sequence is to let a limited restart attempt expose the failure, inspect the reason, correct the cause, and then start the service deliberately.
Reload and start the service
After saving the unit file, tell systemd to reread unit definitions, enable the service at boot if that is what you intend, and start it:
sudo systemctl daemon-reload
sudo systemctl enable --now ffmpeg-youtube.service
Use the actual filename you created in place of ffmpeg-youtube.service. Enabling a service makes it eligible to start at boot; it is separate from starting it now. If you do not want it to launch automatically after reboot, omit enable and start it with sudo systemctl start ffmpeg-youtube.service.
If a command reports an error, do not keep repeating it without reading the message. A missing executable, inaccessible working directory, malformed unit, and permission failure need different fixes. Run sudo systemctl cat ffmpeg-youtube.service to inspect what systemd has loaded, then check the syntax and paths against the actual server. You can use sudo systemctl reset-failed ffmpeg-youtube.service after resolving a start-limit condition, but resetting the state does not fix the underlying fault.
On a Contabo VPS, distinguish the provider’s network-level firewall from the firewall running inside your operating system. Contabo describes its managed Firewall feature as a separate control: when assigned, it blocks inbound traffic by default until rules are configured, while outbound traffic is unrestricted. Its port-access guidance also distinguishes provider controls from OS-level rules. For an FFmpeg process publishing outward, do not assume the managed inbound default explains a failed connection; inspect the actual error and the host’s outbound route and OS firewall. Read Contabo’s Firewall guidance and port-access and OS firewall guidance for the current distinction.
Check service status and the journal
Start with the service status, which gives a concise view of whether systemd thinks the service is active, failed, or restarting:
sudo systemctl status ffmpeg-youtube.service
Then read the service journal. The -u filter selects the unit, and -n limits the output to recent entries:
sudo journalctl -u ffmpeg-youtube.service -n 100 --no-pager
To follow new entries while you make a controlled start or test, use:
sudo journalctl -u ffmpeg-youtube.service -f
Look for the last FFmpeg error before an exit, not just the fact that systemd attempted another start. Check whether the process is actually running, whether the input path is available to the configured user, and whether the output error points to a connection, authentication, or muxing problem. A service showing active (running) proves only that a process is running from systemd’s point of view; it does not prove that video is reaching YouTube.
If the journal includes a full command line, review it before sharing logs. A stream key embedded in an output URL can be exposed in journal output or process details. Redact credentials and rotate a key if you have disclosed it. Avoid repeatedly restarting a service as a diagnostic substitute: each new process can change the media position and create a different connection attempt.
Use a short diagnostic sequence: inspect service status and recent journal entries; decide whether FFmpeg exited or is still alive; check the reported input and output failure; confirm the configured endpoint and key without exposing them; then test whether the host can reach its intended destination. If the failure appears to be firewall-related, check both provider-level controls and the OS firewall. This is a more useful starting point than rebooting the whole VPS for one failed service.
For alternative ways to run prerecorded streams, the free tools overview for always-on streams in India sets out a different practical context. It does not replace diagnosis of a systemd service, but it can help if maintaining a VPS is more work than your channel needs.
Consider FIFO recovery for output errors
FFmpeg’s FIFO muxer can queue packets and attempt to recover from certain output errors. Its recovery controls are relevant when the process remains alive but the output operation encounters a recoverable fault. They are not a general restart mechanism, and they do not solve invalid input, a wrong stream key, or an ongoing network outage.
The FFmpeg documentation for the FIFO muxer describes controls including attempt_recovery, recovery_wait_time, max_recovery_attempts, and recover_any_error. The documented default for recovery_wait_time is five seconds, and max_recovery_attempts defaults to zero, meaning no fixed maximum. These are documentation defaults, not recommendations; confirm the options against your installed FFmpeg build with ffmpeg -h muxer=fifo before using them.
A FIFO output can be expressed as a muxer wrapper around a downstream format, but the exact command depends on the FFmpeg version and the rest of the output configuration. Do not paste an unfamiliar FIFO URL into a working production command without validating its syntax and testing with a non-critical stream. The purpose of the options is to tell FFmpeg how to handle eligible output failures, not to ensure that a YouTube event remains uninterrupted.
Recovery controls involve trade-offs. A finite maximum can prevent indefinite retrying but may leave the output unrecovered after the allowed attempts. A broader error setting can cause FFmpeg to retry errors that would otherwise be treated as permanent, delaying the point at which you notice a configuration fault. Queue overflow also forces a choice: dropping packets can help keep processing in real time but omits content; blocking rather than dropping can hold up processing. Consider what matters more for your channel, and verify how your particular build applies the options.
Use FIFO recovery when the failure is plausibly temporary and you have a reason to keep the existing FFmpeg process alive. Use systemd when the process exits and the command should be restarted. Some setups may use both layers, but avoid building a chain of retries that obscures the original error. For more on the broader always-on workload and operational trade-offs, see how to keep an FFmpeg YouTube stream running on a VPS without a desktop.
Verify the broadcast in YouTube Studio
After systemd reports the process running, open YouTube Studio and check the live control room for the expected channel and event. Confirm that YouTube shows an incoming stream and the broadcast is in the state you intend. A local process restart is not evidence that the ingest connection succeeded, and a successful connection does not guarantee that the event resumes at its prior position or continuity.
If Studio does not show the expected state, compare its status with the service journal and FFmpeg output. The service may be running while output is rejected or no longer arriving. The event may also need attention in Studio even after the encoder reconnects. Avoid assuming that a repeated systemd restart will repair a YouTube-side event state; consult YouTube Help for the current live-stream controls and guidance.
For a scheduled or ongoing event, check the specific event rather than only the channel page. Confirm the title and live state, and make a brief viewing check if practical. Do not infer uninterrupted playback from a green service status. Keep in mind that a restart may replay part of a file or begin elsewhere according to the input command, while an output recovery attempt may lose queued content or pause processing.
A full server reboot is broader than restarting the FFmpeg service and should not be the first response to a single process failure. If the operating system remains accessible, use its normal service and network diagnostics first. The church recorded-sermon streaming guide also highlights why the content and the live event should be considered separately when planning a continuous channel.
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 systemd guarantee that my YouTube live stream will continue?
No. systemd can restart a failed FFmpeg process when the configured policy applies, but it cannot guarantee that YouTube accepts the connection or preserves the same event, playback position, or continuity. Verify the result in YouTube Studio.
Should I use Restart=on-failure or Restart=always?
Use on-failure if abnormal exits should be retried but an intentional clean stop should stay stopped. Use always only when restarting after clean exits is genuinely intended. Check your installed systemd documentation because accepted directives and start-limit behaviour can vary.
Does FIFO recovery replace a systemd restart policy?
No. FIFO recovery attempts to handle some output errors while FFmpeg stays alive; systemd acts when the process exits under a matching restart policy. They address different failure points, and neither fixes every fault.
What should I check if the service is active but Studio shows no stream?
Read the service journal and FFmpeg’s output, then check the media input, output endpoint and key, and host network path without exposing the key. Confirm the event state in YouTube Studio and consult current YouTube guidance if the encoder appears connected but the event is not in the intended state.