Skip to content
streamneo.
Setup Guides11 min read

How to Stream a YouTube Live Loop with a Linux Shell Script

Use FFmpeg and YouTube Live Control Room to loop a file from Linux, protect your stream key, and test before going live.

sn.
StreamNeoPublished 5 October 2026
Worth sharing?

To loop a video on YouTube Live from a Linux shell script, use FFmpeg to send a local file repeatedly and use YouTube Live Control Room to provide the event’s server URL and stream key. The script can keep the encoder sending; it does not create or start the YouTube event, and scheduled streams may still need preview and a manual Go live action.

This approach suits a prepared video that can run from an always-on Linux computer or hosted Linux instance. It gives you control over the encoder command, but you remain responsible for the machine, network, credentials, event settings and monitoring. Test the whole path before relying on it overnight.

Check that your channel can stream

Before installing or configuring anything, confirm that the channel is eligible for live streaming. YouTube says a channel must be verified and must not have had live-streaming restrictions in the previous 90 days; the minimum age to livestream is 16. Check YouTube’s current live-streaming eligibility guidance for the account you intend to use, since platform rules can change.

Eligibility is separate from whether a particular event is public, unlisted or scheduled. Sign in to the correct channel in YouTube Studio and check that live streaming is available there. If the feature is unavailable, resolve that before debugging FFmpeg: an encoder can connect only when YouTube accepts the account and event.

Also decide what “24/7” means for your channel. A script can repeat a media file indefinitely while it is running, but this is not the same as a guarantee that the process, computer, internet connection or YouTube event will stay up. Think through who will notice a failure, how you will restart it, and whether the chosen content can be repeated without an awkward cut.

Create or select the YouTube event

In YouTube Studio, open Live Control Room and create a stream or select an existing event. Follow YouTube’s encoder setup instructions and copy the server URL and stream key shown for that event. Do not assume an old key or URL is the right one: use the values displayed for the stream you selected.

The URL and key are distinct pieces of connection information. YouTube Help describes stream keys as “like your YouTube stream’s password and address” in its page on managing live stream settings. Treat the key as a secret. Avoid pasting it into a public terminal recording, shared chat, shell history or source-control repository. If you believe it has been exposed, use YouTube’s controls to reset it and update the encoder’s configuration.

Keep the event’s title, visibility, latency and other settings in YouTube Studio. The shell script below only sends media to the ingest endpoint; it does not set the event’s public details or decide when the audience can watch. Scheduled event settings can affect whether YouTube waits for a preview and requires you to select Go live. Confirm that flow in Live Control Room rather than assuming that a successful encoder connection has made the event public.

Make the media path available

Choose a finished file with video and audio that you have the right to stream. Put it at a stable local path, such as /home/channel/media/loop.mp4, and make sure the account that runs the script can read it. A relative filename such as loop.mp4 is convenient during a test from the file’s directory, but it can fail if a scheduled job starts in a different working directory.

Install FFmpeg from a trusted source for your Linux distribution, then check the local build and available encoders. Distribution packages may differ, and a build without the libx264 encoder will not accept the example’s video setting unchanged. Use the package manager or distribution documentation you normally trust; there is no single installation command that applies safely to every Linux system.

Check the input itself before broadcasting. Play the file locally, confirm its duration and audio, and watch its end-to-start transition. If a bhajan recording ends with silence, for example, the silence will recur every time the file loops. The command does not crossfade, edit or repair the source; prepare the media first if the join needs work.

If you use more than one file or a playlist, that is a separate workflow with its own ordering and recovery questions. For a retail loop, the guide to rotating promo videos in a YouTube Live playlist discusses a different content arrangement. Here, keep the first test simple: one known-good file and one event.

Build an FFmpeg loop command

FFmpeg’s command documentation defines -stream_loop -1 as repeating the input indefinitely, and -re paces file reading at the media’s native rate. See the FFmpeg command documentation. For a local file, those options make the process behave as a live-paced encoder rather than sending the entire file as quickly as the computer can read it.

The following is a starting template, not a universal configuration. It assumes an installed FFmpeg build with libx264, a conventional video input, and a YouTube-provided URL and key. The example’s video and audio settings are illustrative; check YouTube’s current encoder recommendations and choose quality that fits both the source and your reliable upload capacity.

ffmpeg -re -stream_loop -1 -i "/home/channel/media/loop.mp4" \\
  -c:v libx264 -preset veryfast -pix_fmt yuv420p \\
  -r 30 -g 60 -keyint_min 60 -sc_threshold 0 \\
  -b:v 2500k -maxrate 2500k -bufsize 5000k \\
  -c:a aac -b:a 128k -ar 44100 \\
  -f flv "${YOUTUBE_RTMPS_URL%/}/${YOUTUBE_STREAM_KEY}"

The two environment variables are placeholders, not values to copy literally. Set them to the exact server URL and key shown for the chosen event. The expression removes a trailing slash from the URL before joining the key, but you must check the format shown in your own Live Control Room; do not assume every account or ingest endpoint uses an identical URL structure.

YouTube recommends RTMPS, which carries RTMP over a secure connection. Its encoder guidance includes H.264 for RTMP/RTMPS, constant bitrate, a keyframe interval of two seconds with a maximum of four seconds, and AAC or MP3 audio; for stereo audio it lists 128 Kbps and a 44.1 kHz sample rate. Those are platform recommendations, not a promise that the sample video bitrate suits every file or connection. A higher-quality source cannot be made better merely by choosing a larger output bitrate, and an upload link that cannot sustain the selected rate may produce a poor stream.

The example sets a 30-frame-per-second output and a 60-frame GOP, which corresponds to a two-second keyframe interval at that output rate. Adapt frame rate and bitrate to the actual source and test results. If your file is lower resolution or has a different frame rate, consider whether transcoding it this way is worthwhile; unnecessary conversion adds work for the computer and can change the image or sound.

Put the command in a shell script

Once the direct command is understandable, save it in a script file. This makes the path and options repeatable and lets you add basic checks, but a shell script is not a supervisor or a YouTube event controller. It will not create an event, approve a preview, or ensure that a process recovers from every network interruption.

For example, save this as send-loop.sh and change the default input path to your own file:

#./usr/bin/env bash
set -euo pipefail

: "${YOUTUBE_RTMPS_URL:?Set the stream URL from YouTube Live Control Room}"
: "${YOUTUBE_STREAM_KEY:?Set the stream key privately}"
INPUT=${1:-/home/channel/media/loop.mp4}

if [[ . -r "$INPUT" ]]; then
  printf 'Input is missing or unreadable: %s\\n' "$INPUT" >&2
  exit 1
fi

exec ffmpeg -re -stream_loop -1 -i "$INPUT" \\
  -c:v libx264 -preset veryfast -pix_fmt yuv420p \\
  -r 30 -g 60 -keyint_min 60 -sc_threshold 0 \\
  -b:v 2500k -maxrate 2500k -bufsize 5000k \\
  -c:a aac -b:a 128k -ar 44100 \\
  -f flv "${YOUTUBE_RTMPS_URL%/}/${YOUTUBE_STREAM_KEY}"

The shebang selects Bash, and set -euo pipefail makes common script errors less easy to overlook. The input check catches a missing or unreadable file before FFmpeg starts. exec replaces the shell with FFmpeg, so the process you monitor is the encoder itself. This small amount of checking does not validate the stream key, event state, network route or media quality.

Keep credentials out of the script and repository. For a manual test, you can export the two variables in a private terminal session before running the script, taking care that terminal history and process inspection may expose environment values depending on how you launch it and who can access the machine. For a longer-running deployment, use a permissions-restricted environment file or an appropriate secret-management method available in your environment. Do not make a world-readable configuration file merely to simplify startup.

Make the script executable with the file permissions tool available on your system, or invoke it explicitly with Bash. The exact command for changing permissions is widely used, but this article does not assume a particular Linux distribution or account layout. The important point is that the file must be readable and the chosen invocation must run Bash, since the script uses Bash syntax.

Run and monitor the process

Begin with a short, controlled test event, not an unattended overnight broadcast. Set the environment variables securely, run the script with the media path if needed, and watch FFmpeg’s output for connection errors, missing codecs, input warnings or repeated reconnect behaviour. A process that prints output is not proof that viewers receive healthy video and audio; use Live Control Room’s stream health and preview as well.

A local Linux desktop can work if it stays powered on, connected and not suspended. A server or hosted Linux machine may be more suitable where local power or broadband is unreliable, but it introduces administration, access control and recurring hosting costs. No particular provider is required by this method. Compare the operating trade-offs before moving a channel to a hosted setup; the article on cloud service options for looping YouTube videos is relevant if you are weighing that change.

Avoid treating automatic restart as a substitute for monitoring. A process may stop on a bad input, expired credentials, host restart, network outage or ingest rejection. You can build a supervisor or use facilities available on your system, but service managers and their configuration differ across Linux distributions and installations. Verify the local documentation, run a controlled failure test, and make sure a restart will not create duplicate or confusing live events.

For a long-running channel, define a human check routine: confirm that the event is still live, video is moving, audio is present, and FFmpeg has not exited. YouTube’s live streaming tips recommend testing and monitoring. If your channel is primarily music or radio, consider the separate operational issues described in running an online radio station on YouTube, including content planning as well as sending a signal.

Stopping is also part of the workflow. Interrupt FFmpeg deliberately when you mean to end transmission, then check Live Control Room and end the event there when appropriate. YouTube states that streams under 12 hours are automatically archived; do not plan on a single archive for a longer continuous loop. If the archive matters, verify the current policy and arrange a recording or archive plan that suits the intended duration.

Preview, then start the event if needed

Encoder transmission and event activation are related but distinct. After FFmpeg connects, open the selected event in Live Control Room and inspect the preview, picture, audio and stream health. If the event’s settings require it, use the available Go live control. Do not assume the script’s successful connection starts a scheduled stream for viewers; auto-start behaviour depends on the event settings you deliberately selected.

Use a private or unlisted test event when appropriate, and confirm what viewers will see before using a public event. Check for a frozen frame, clipped audio, silence at the loop boundary, unexpected aspect ratio or a delay that makes sense for your use. YouTube’s stream health can identify problems that are not obvious from the terminal. If you make a configuration change, test again rather than assuming it helped.

RTMPS is the simple default for the command shown. YouTube also supports HLS for cases such as HDR or codecs not supported over RTMP, but HLS has higher latency because it delivers segmented media. That trade-off may matter for a use case that needs a particular codec or picture format; it is not a reason to switch protocols without a requirement. The shell example is built around RTMPS and should not be copied as an HLS command.

Before committing to a longer-running workflow, compare the operating options on the pricing page. When the file and channel are ready, start free — 24-hour trial, no card.

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 the script create the YouTube Live event?

No. You create or select the event in YouTube Live Control Room and take its server URL and stream key from there. The script sends media to the configured ingest address; it does not create an event or set its title, privacy or schedule.

Why does FFmpeg connect but the event is not live to viewers?

The event may still be waiting for preview or a manual Go live action. Check the event’s settings and the Live Control Room flow for that event; do not infer viewer-visible status from the encoder process alone.

Can I leave this running indefinitely?

-stream_loop -1 asks FFmpeg to repeat the input indefinitely, but it cannot guarantee continuous operation. The computer, connection, process and event all need attention, and YouTube says automatic archiving applies to streams under 12 hours, so plan monitoring and recording separately.

Is the example bitrate right for my channel?

It is only an illustrative starting point, not a universal YouTube requirement. Match encoding settings to your source and dependable upload capacity, check YouTube’s current encoder recommendations, then test the result in Live Control Room.

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 ↗