A systemd service can start an encoder when your Linux host boots and relaunch it after the process exits. It cannot guarantee uninterrupted YouTube playback: the ingest connection, network, media, credentials and encoder configuration still have to work.
The key choice is whether a clean encoder exit should start another process. Use Restart=on-failure when a clean exit should leave the stream stopped; use Restart=always when any exit should trigger another attempt. In either case, run the encoder in the foreground and check the actual broadcast in YouTube Live Control Room.
What systemd can and cannot recover
systemd supervises a process. If its service process exits, systemd can apply a restart policy and launch it again after a configured delay. It can also start an enabled service as part of the host’s boot sequence. That is useful if an encoder crashes overnight or the host restarts, but it is only process recovery.
A service can appear active while the broadcast is not healthy. The encoder might be sending to a stale endpoint, failing to read its input, or producing a feed YouTube cannot accept. A network connection can degrade without causing the process to exit, in which case a basic restart policy has no failure signal to act on. YouTube’s streaming tips discuss connection capacity and the effect of connectivity problems; a service manager does not repair those conditions.
Think in layers: systemd starts and supervises the process; FFmpeg reads media and encodes it; the host’s network carries the output; YouTube receives and processes it; viewers receive playback. A recovery at one layer does not certify the others. For example, after a failed connection, a newly launched FFmpeg process may still be unable to reach the ingest endpoint.
This distinction matters for any always-on channel, whether you are looping a devotional programme, ambience video or local information. If you are deciding whether the content itself should repeat or move through a playlist, see how a 24/7 stream can play different videos automatically. Playlist behaviour belongs to the media workflow; it is separate from whether systemd relaunches an exited encoder.
A restart policy is therefore a recovery instruction, not a promise of continuous playback. Treat systemctl status as evidence about the local service, then inspect YouTube’s preview or stream health before assuming viewers can see a usable feed.
Run the encoder in the foreground
For systemd to supervise the encoder, the encoder should remain the service’s main process. In a unit using Type=simple, systemd starts the command in ExecStart= and tracks that process. If the command exits, systemd can observe the exit and apply the selected policy.
Do not wrap the command in a script that launches FFmpeg in the background and then exits. In that arrangement, systemd may be supervising the wrapper rather than the process doing the streaming. A wrapper can be useful when it performs necessary preparation, but it should normally replace itself with the encoder using exec, or otherwise manage child processes deliberately. Keep the design simple until you have a specific need for a wrapper.
Before creating a service, run the intended encoder command interactively and confirm that it can read the source and send a stream. Use the current endpoint and key from YouTube Live Control Room, not a copied example. YouTube describes stream keys as the encoder’s “password and address” in its live stream settings guidance. Keep the key out of public scripts, screenshots and logs; if it is exposed, reset it in the control room and update the service configuration.
An illustrative FFmpeg command might read a local file and loop it, but its codecs and rates must match the file, installed FFmpeg build, host capacity and chosen stream settings. YouTube recommends RTMPS where supported; use the current URL presented for your stream. Its encoder settings documentation gives platform guidance for codecs, resolutions and bitrates. A value in an example is not proof that your connection or machine can sustain it.
For a small host, test the workload before relying on it overnight. Hardware encoding may reduce CPU load if your device and FFmpeg build support it, while software encoding may be more portable but consume more CPU. Neither option removes the need to monitor output and upload capacity. If you are running a Pi-based host, the practical considerations in the Raspberry Pi FFmpeg guide are relevant to the host and headless operation, but the service lifecycle principles are the same.
Choose a restart policy
The two common policies express different intentions. Restart=on-failure restarts after an unsuccessful exit, a signal or a timeout, but allows a clean exit to remain stopped. Restart=always restarts after a clean exit as well as failures. The systemd service unit documentation defines the applicable policy; check the documentation installed on your distribution, because systemd versions and distribution configuration can differ.
| Setting | What happens after a clean encoder exit | Useful when | Main caution |
|---|---|---|---|
Restart=on-failure |
No automatic restart | A normal completion should be respected; unexpected failure should be retried | A clean exit caused by an encoder problem may look intentional to systemd |
Restart=always |
Another process is started | The stream should continue even if the encoder exits successfully | A command that repeatedly exits cleanly can create repeated attempts |
Restart=no |
No automatic restart | You want manual intervention after any exit | A crash or host-side process failure leaves the stream stopped until acted on |
For a loop intended to run continuously, on-failure is a reasonable starting point if clean exit should signal that the stream is finished or should be investigated. Choose always if any exit—including a clean one—should lead to another run. Do not select always simply because “always-on” is in the channel description. First decide what a clean encoder exit means for your particular command and content.
A stop request from the service manager is different from an unexpected process exit. An explicit systemctl stop is an operator instruction, and these restart policies do not undo it by immediately starting the service again. That lets you stop the stream for maintenance. A reboot or shutdown also has its own system lifecycle; do not confuse an enabled service at boot with a process that must ignore every deliberate stop.
Add a RestartSec= delay rather than allowing an immediate retry loop. For example, RestartSec=10s is a deliberate illustrative delay, not a universal recommendation. A longer delay may give a network or endpoint problem time to clear; a short delay can produce frequent retries and noisy logs. Repeated attempts can also be subject to systemd start-rate limiting, so a service may stop being restarted after failures occur too quickly. Check the local systemd.service and systemd.unit manuals for the rate settings and available directives on your host.
Create and enable the service
The following unit is a template, not a tested configuration. Replace the account, paths, media and destination. The FFmpeg options are illustrative; consult the current YouTube encoder guidance and test with your own source. In particular, do not publish the stream key or leave it in a location readable by people who should not control the broadcast.
# /etc/systemd/system/youtube-stream.service
[Unit]
Description=YouTube live stream encoder
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
User=streamer
WorkingDirectory=/srv/stream
ExecStart=/usr/bin/ffmpeg -re -stream_loop -1 -i /srv/stream/loop.mp4 -c:v libx264 -preset veryfast -b:v 4500k -maxrate 4500k -bufsize 9000k -c:a aac -b:a 128k -f flv rtmps://YOUR_INGEST_URL/YOUR_STREAM_KEY
Restart=on-failure
RestartSec=10s
[Install]
WantedBy=multi-user.target
The User= and WorkingDirectory= entries mean FFmpeg runs with the chosen account and from the specified directory. Confirm that account can read the media and access any required files. After=network-online.target orders the service after the relevant target, while Wants= requests that target. This ordering does not ensure that an external route or YouTube ingest is reachable, nor does it make a network connection stable.
The command shown assumes a local looping file and an FFmpeg build with the requested components. It does not establish that the sample bitrates suit your channel. YouTube’s published H.264 recommendations include 5 Mbps for 1080p at 30 fps and 14 Mbps for 4K at 30 fps, but those are platform recommendations, not guarantees about your host or upload connection. YouTube also advises leaving upload headroom in its streaming tips. For a deeper look at encoder values and keyframes, use the FFmpeg bitrate and keyframe guide.
Once the unit file is saved, tell systemd to reload its unit definitions and enable and start the service:
sudo systemctl daemon-reload
sudo systemctl enable --now youtube-stream.service
sudo systemctl status youtube-stream.service
enable arranges for the unit to start with its configured boot target; --now also requests an immediate start. The exact commands are common on systemd distributions, but consult your distribution’s local manuals if a command or unit option differs. If you change the unit later, reload definitions and restart the service for the changes to take effect. Keep key handling in mind when choosing how to supply credentials: do not paste secrets into an article, public repository or support message.
If your process stops cleanly because the media file ends, a looping input may be needed, or you may need Restart=always if a clean exit should relaunch it. Those are different solutions. A restart loop can hide a content or command issue rather than solve it, so understand why the process exits before deciding to retry indefinitely.
Inspect service status and logs
Start with systemctl status youtube-stream.service. It can show whether systemd considers the unit active, the main process identifier and a summary of recent events. It is a useful local check, but “active” is not equivalent to “YouTube is receiving a healthy stream”. Confirm the stream’s preview, ingest status or health indicators in Live Control Room after starting it.
Use the journal to see the encoder’s output and service events:
sudo journalctl -u youtube-stream.service -f
The -f option follows new messages, which is useful while starting or testing. To review earlier attempts, omit -f and inspect the recent journal entries. Look for FFmpeg messages about opening the input, resolving or connecting to the destination, authentication, codec setup and output errors. Messages can reveal the layer where the problem occurs, although a quiet log does not prove the stream is healthy.
When the service fails, note the exit status and the time it happened before changing several settings at once. Compare that moment with the YouTube control room and the host’s network conditions. If a stream is live in the control room but viewers report buffering, you may be facing a delivery or stability issue rather than a process exit; the discussion of latency versus stability settings can help distinguish playback choices from service supervision.
Keep logs useful and safe. FFmpeg output may include URLs or other details that should not be shared publicly, and credentials should never be exposed in logs. If you need to send diagnostic output to someone, inspect it for keys and account details first.
Diagnose repeated restarts
A service that repeatedly starts and exits is not necessarily recovering. It may be repeating the same failing command. Read the journal around each attempt and classify the failure before increasing retry frequency or changing the restart policy.
| Symptom in the service or logs | Likely area to check | Useful next step |
|---|---|---|
| Immediate exit before output begins | Missing executable, unreadable input, bad command option or permissions | Run the command as the configured service user and verify every path |
| Connection or publishing error | Endpoint, key, DNS, network route or ingest availability | Recheck the current control-room URL/key and test connectivity separately |
| Encoder reports overload or dropped frames | CPU/GPU capacity, selected codec, resolution or frame rate | Reduce workload or choose settings your host can sustain, then test again |
| Service is active but control room has no usable feed | Process is alive but output or ingest is not healthy | Inspect FFmpeg output and the YouTube preview/health indicators |
| Restarts stop after rapid failures | systemd start-rate limiting may have been reached | Inspect status and local unit/system configuration before retrying |
The table is a diagnostic map, not a list of guaranteed causes. For example, a rejected stream may be related to a key or endpoint, but it may also involve a malformed command or transient connection. YouTube says the stream key is credential-like; if it may have been exposed, reset it and update the service rather than repeatedly attempting with the same secret.
Network capacity deserves a separate check. The encoder can be configured correctly and still lose ingest if the upload path is weak, shared or unstable. Leave headroom for other traffic and consider the needs of both primary and backup streams if you use them. A host in a data centre may have a different network profile from a home connection, but neither category guarantees an uninterrupted route to YouTube.
A process can also hang without exiting. The restart policy is triggered by exits or other service events systemd recognises; it is not a universal application health monitor. If you need to detect a silent encoder hang, that requires a separate health-check design and a defined signal for failure. Do not add complexity until you can explain what condition the check detects and how it avoids restarting a stream that is actually healthy.
Test recovery without assuming continuity
Test the service deliberately before treating it as a dependable overnight setup. Start it, confirm that FFmpeg reads the intended source, and verify the live preview and health in YouTube Live Control Room. Then test a controlled process failure in a maintenance window and observe whether the selected restart policy behaves as expected. Avoid testing by exposing or invalidating a production key.
With on-failure, a command terminated abnormally should be eligible for restart, while a clean exit should not. With always, both clean and failed exits should lead to a new process, subject to configured delay and rate limiting. An explicit service-manager stop should remain stopped. Check the local journal after each test to see what systemd recorded and how long the next attempt took.
A successful process restart may still produce a visible gap. The encoder must reopen media, connect to the endpoint and resume sending; YouTube then has to receive and process the new feed. Viewers may need to reconnect or wait for playback to recover. Therefore, a test that proves the PID changed proves only that process supervision worked. It does not prove end-to-end stream continuity or that every viewer saw uninterrupted playback.
Also test ordinary host reboot behaviour if the service is meant to start after power or maintenance interruptions. Check that the service is enabled, that media is mounted before use, and that credentials and paths remain available after boot. network-online.target ordering can help express startup ordering but is not a connectivity guarantee. Check the service and the control room again after the reboot.
If repeated local maintenance, host availability or connection quality is not something you can manage, consider the operating model as well as the unit file. A dedicated host gives you control over the process and its settings but leaves you responsible for updates, power and network. A cloud-hosted workflow removes the need to keep your own computer switched on; StreamNeo removes that specific burden for a file-based YouTube stream by letting you upload once and leave your computer off, while you still need to confirm your channel, source file and broadcast are ready. It is YouTube-only, so it is not the right fit if you need a destination or hands-on control of a Linux process.
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 restart FFmpeg if it crashes?
Yes, if FFmpeg is the foreground process managed by the service and the unit uses a restart policy that covers the failure. Restart=on-failure is intended for unsuccessful exits, while Restart=always also covers a clean exit. Start-rate limiting and the chosen delay can affect when further attempts occur.
Should I use Restart=always or Restart=on-failure?
Use on-failure when a clean exit should leave the stream stopped and only an unexpected failure should be retried. Use always when even a clean encoder exit should launch another process. A deliberate systemctl stop is still an instruction to stop the service, not a failure to undo.
Does an active service prove that my YouTube stream is live?
No. It shows that systemd considers the local service active, not that the encoder has a valid input, can reach YouTube or is producing a healthy feed. Check the encoder logs and confirm the preview or health in YouTube Live Control Room.
Why has systemd stopped retrying my service?
Rapid repeated failures can run into systemd’s start-rate limit, and the exact settings depend on the installed systemd version and host configuration. Inspect systemctl status and the journal, then check the local systemd manuals before changing rate settings. Fix the cause of the repeated exit rather than simply making retries faster.