To keep an FFmpeg YouTube stream running on an Azure VM, separate the media command, YouTube ingest settings, systemd supervision and host monitoring. systemd can start and supervise a process, but neither an active service nor a running FFmpeg process proves YouTube is receiving or displaying the stream.
Work through each layer independently. First establish that the FFmpeg command works with your source and current YouTube settings; then run it as a service, inspect its logs, and confirm the stream in YouTube Studio.
Check the source and FFmpeg command
Start by identifying what FFmpeg is meant to read. A local looping video, a network stream and a capture device do not use identical inputs. The input options belong before the relevant -i argument, while output options belong before the output destination. FFmpeg documents the general structure as global options, input options and inputs, followed by output options and outputs; the exact syntax and available encoders depend on the FFmpeg build installed on your VM. See the FFmpeg command-line documentation and check the documentation for the version you actually run.
Do not begin by copying a command without understanding its pieces. Record the absolute path to the input file or the actual network/device input, the required loop or real-time behaviour, any audio mapping, the output format and the destination. For a prerecorded file, confirm that the VM can read it under the account that will run the service. An SSH test as your own account does not establish that a dedicated service account can access the same path.
A useful first test is to run the command manually in a controlled session, using the same executable, input and output configuration intended for the service. Watch FFmpeg's output for errors opening the source, missing streams, unsupported codecs, or inability to reach the destination. Do not treat a command returning without an immediate error as a completed ingest check; the YouTube side needs its own confirmation.
Decide whether to copy compatible audio and video or transcode them only after checking the source and the needs of the output. Copying avoids re-encoding but preserves the source codecs and properties. Transcoding gives you a way to change them, but consumes compute and can introduce new failure points. There is no single bitrate, frame rate or codec setting that can be recommended without knowing your source and checking current YouTube guidance. For a file-based workflow, the discussion of preparing video files for a 24/7 YouTube stream on a low-end PC can help you think through the source before it becomes a cloud job.
Keep the working directory explicit if your command relies on relative paths. Under systemd, a process may not start from the directory you happened to use in an SSH shell. Prefer absolute paths for the FFmpeg executable and media where practical, and test file permissions as the service user. Save a known-good version of the command with credentials removed, so later changes to the input or encoding are not mixed up with changes to supervision.
Set YouTube's ingest address and stream key
Use the current ingest address and stream key shown for the channel's live setup, rather than a host copied from a generic example. These values are channel configuration, not properties to guess from an old command. Confirm that the stream is configured and available in YouTube Studio before diagnosing a failed connection as an Azure problem.
Where the selected FFmpeg build and endpoint support it, prefer YouTube's documented RTMPS connection. Google's YouTube Live Streaming API RTMPS ingestion documentation specifies port 443 and explains that the server hostname is required for SNI authentication during the TLS handshake. Preserve the hostname and application path supplied by the actual configuration; changing schemes, removing part of the address or substituting a guessed host can prevent the connection from working.
RTMPS protects the transport between the publisher and ingest endpoint. Plain RTMP may be required by a particular tool or configuration, but do not silently switch to it as a troubleshooting shortcut. Check the endpoint, protocol support in your FFmpeg build, DNS resolution and outbound access from the VM. If a connection fails, a transport change should be a deliberate test, not a substitute for reading the FFmpeg error and verifying the configured address.
Treat the stream key as a publishing credential. Do not place it in a public repository, a screenshot, an article example or a shell command that will be saved in history. A service configuration mechanism may keep it out of the main command file, but verify how that mechanism is parsed by your distribution and restrict access to any file that contains the key. Avoid making it world-readable merely to solve a permissions error. If the key is exposed, replace it through the channel's current live configuration and update the service accordingly.
Keep the destination settings distinct from the media command. If the stream stops appearing, check the active key and ingest address in YouTube's current setup, then compare them with the values used by the service. Never paste a real key into a support ticket or a log excerpt. If YouTube Live access itself is missing, that is a channel permissions issue rather than a systemd fault; see the guide to missing YouTube Live streaming access on a channel managed by another account.
Create a systemd service unit
A systemd service lets Linux start FFmpeg independently of an interactive SSH session and manage it as a named unit. Use a dedicated unprivileged account where appropriate, an explicit executable path, a deliberate working directory and only the permissions needed to read the source and connect out. The service unit should describe the process you have already tested, not conceal an unverified change to its command.
A unit commonly has a description, dependency/order settings, execution settings and an install section, but exact directives and their interactions must be checked against the systemd version installed on your VM. The authoritative local references are often available through commands such as man systemd.service and man systemd.exec. The examples below are a shape to reason about, not a ready-to-paste unit: the executable path, user, paths, options and policy need to match the actual VM.
[Unit]
Description=FFmpeg YouTube stream
[Service]
User=streamuser
WorkingDirectory=/srv/stream
ExecStart=/usr/bin/ffmpeg [your tested options and input] [your output destination]
[Install]
WantedBy=multi-user.target
The bracketed text is explanatory placeholder text, not valid FFmpeg syntax. Replace it with the tested command in the format your service requires. Do not assume shell features such as variable expansion, pipelines or quoting behave as they do in an interactive shell: systemd execution directives have their own parsing rules. If you need a wrapper script for more complex setup, make it readable only by the appropriate administrators, use explicit paths, and test it as the service account.
Before enabling a unit, ask systemd to verify the file with systemd-analyze verify on the target distribution, then inspect any warnings rather than ignoring them. This catches some unit-file problems but does not prove the FFmpeg command works, that the source is readable, or that YouTube accepts the output. Test those separately. Documentation for directives and environment-file handling can vary by local systemd release; use the installed man pages rather than assuming a copied snippet has identical semantics everywhere.
Keep secrets separate from ordinary logs and examples. If an environment file or another restricted mechanism is used, verify the exact syntax and access control locally, then inspect how the running command and logs expose values. Avoid printing the key as part of a diagnostic command. A permissions arrangement that prevents the service from reading its credential is a real failure, but broadening access to all users is not a good fix.
Configure boot startup and restart behaviour
Boot startup and restart after failure are separate choices. Enabling a service arranges for it to be started as part of the relevant boot target; a restart policy tells systemd what to do after the process exits. Confirm both against your distribution's local systemd documentation and the purpose of the stream. A deliberate stop for maintenance should not become an unexpected restart simply because the policy was chosen without considering operator actions.
Choose failure handling based on the job. A policy that restarts after abnormal exit can recover from a transient process failure, while broader restart behaviour may cover more exits but can also restart a job you intended to stop. Add a delay where appropriate, and check the local documentation for exact directive semantics and rate limiting. Do not rely on an unverified unit example as proof that a policy behaves as expected on your installed version.
A restart loop can repeatedly retry a permanent failure: an invalid command, inaccessible media file, rejected key or unavailable input will not be fixed by another process launch. If you see repeated starts, pause to diagnose the original exit rather than increasing the restart behaviour. Record the exit message and compare it with the command you tested manually. Once configuration is corrected, test a controlled failure and observe what the target system does before leaving the channel unattended.
After verifying the unit, enable it for the intended boot target using the distribution's documented workflow. Reboot testing is useful, but schedule it when a service interruption is acceptable and make sure you can regain access to the VM. After the reboot, check both whether the unit started and whether the stream appeared in YouTube. The two checks answer different questions.
Start and inspect the service
Use systemctl status <service> to inspect whether the unit is loaded and active, along with recent output and exit information. Replace <service> with the unit name you created. This tells you about systemd's view of the process; it is not a YouTube health check. An active state can coexist with an FFmpeg process that is waiting on an input, retrying a connection or sending output that YouTube has not accepted.
Read the service journal with journalctl -u <service>. To watch new system journal messages while testing, use journalctl -f and filter or select the unit as appropriate. Check the actual FFmpeg stderr output for source-open errors, authentication failures, protocol errors and encoder problems. Keep a short note of the time and the change you made before each test; it is much easier to distinguish a new error from old output when you make one change at a time.
If systemd reports that the unit cannot be found, check its name and where the unit file was placed, then reload the systemd manager configuration according to local guidance. If it reports an execution or permission error, verify the binary path, executable permission, account and access to every parent directory and source file. If the service starts and exits immediately, compare its exact arguments with the manual test and read the journal before altering restart settings.
You can also inspect process and connection evidence on the host. Tools such as ss can show sockets, while top and free -h help reveal CPU or memory pressure. Their output is a snapshot, not a statement that YouTube is displaying the stream. A process can be alive while using excessive CPU, and a socket can exist without proving that the intended live event has become available to viewers.
For content questions, check that the file has the expected video and audio tracks and that they remain in sync during playback. A looping source can have problems at transitions even if the process stays alive. The practical notes on keeping audio synced when looping video on YouTube Live are relevant when the process is healthy but the programme itself is not.
Check YouTube stream status separately
Open the current live control room in YouTube Studio and inspect the event's incoming stream status and preview. Confirm that the intended channel and live event are selected, and that the video and audio are actually arriving. Then consider whether the event is merely receiving an input or has been made visible to viewers; ingestion and public display are distinct stages in the YouTube workflow.
If FFmpeg is running but the preview is absent, do not conclude that systemd needs a different restart setting. Work across the boundary in order: inspect the FFmpeg journal for a connection or authentication error, compare the output address and key with the channel's current setup, check that the source is producing media, and confirm outbound network reachability from the VM. YouTube's status and FFmpeg's stderr provide different evidence, so preserve both when asking for help.
A successful connection message from a client is useful, but it is not a guarantee that the intended event is receiving or displaying a playable programme. Likewise, a preview in the control room does not show that the system will survive a later reboot or input failure. Keep a simple test record: unit status, a relevant journal excerpt with secrets removed, the YouTube event state and what you observed in the preview. This makes a later fault easier to localise.
If your channel uses a playlist of prerecorded content, check the event, source and loop as well as the connection. The guide to streaming a church prayer meeting playlist 24/7 on YouTube offers a useful content-planning perspective, but its workflow does not replace verification of this VM's service and ingest state.
Monitor Azure and Linux signals
Host-level monitoring helps answer whether the VM and its network path are behaving; it cannot establish YouTube-side display. On Azure, review the VM's current health and monitoring information in the portal, then compare it with Linux evidence such as service state, resource use and network configuration. Azure policy, routes, DNS, security rules and guest firewall settings vary by deployment, so verify them on the VM and in the actual network path rather than assuming a default.
For basic Linux network checks, networkctl can show interface state, ip addr shows addresses and ip route shows routes. Azure Linux documentation describes these tools and the host's networking service. Be cautious about changing or stopping networking components over SSH: disrupting the VM's network can cut off your session and leave recovery to another access path. Check the official Azure Linux networking guidance before making changes to its documented network configuration.
YouTube's RTMPS documentation identifies port 443 for the connection. Confirm that outbound traffic to the configured destination and port is allowed by the VM's firewall and Azure network controls. A general test to some other web address is not proof that the selected ingest hostname resolves or that the required route is open. Conversely, a network path that appears open does not prove that the key, event or media output is valid.
Plan for evidence to survive a reboot if you expect to diagnose one. Azure Linux documentation notes that journal data persists under /var/log/journal/ when that directory exists; otherwise journal entries remain in memory and are lost on reboot. Review your distribution's journal configuration, storage capacity and retention needs deliberately. Persistence helps with after-reboot diagnosis, but it also means log growth and secret exposure deserve attention.
Use a small, repeatable set of checks rather than treating one green indicator as a verdict: inspect the unit and recent journal, review CPU and memory, verify interface/address/route, and confirm the YouTube event state. When an outage occurs, note the time and whether the VM rebooted, the service restarted, the connection failed or the source ended. These observations narrow the layer at fault without implying that any one monitor can guarantee uninterrupted delivery.
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 keep YouTube live if FFmpeg is running?
No. systemd supervises a local process according to the unit and policy you configure. You must check FFmpeg's output and YouTube's live control room separately to establish whether the stream is arriving and displayed.
How do I make FFmpeg start after an Azure VM reboots?
Create and validate a service unit for the tested command, then enable that unit for the appropriate boot target using your distribution's systemd workflow. After a planned reboot, check the unit state, journal and YouTube event; boot startup alone confirms neither a good input nor accepted ingest.
Why does the service show active when YouTube has no stream?
An active process only describes local process state. The source may be unavailable, the ingest URL or key may be wrong, outbound connectivity may fail, or the live event may not be the one you are inspecting. Compare the journal with YouTube's current stream status and preview.
Will service logs still be there after a reboot?
That depends on journal configuration. On Azure Linux, journal data persists under /var/log/journal/ when that directory exists; otherwise it is held in memory and disappears on reboot. Check the actual VM's configuration and retention behaviour before relying on logs for post-reboot diagnosis.