Two Approaches: OBS vs FFmpeg
Streaming your radio station 24/7 to YouTube Live requires two things: a video signal (YouTube doesn't accept audio-only streams) and a process that runs continuously without human intervention. There are two practical methods to achieve this.
The first is OBS Studio — the popular free streaming software with a graphical interface. OBS is the easier option for stations running on a Windows machine and wanting a visual setup they can manage manually. The downside is that OBS needs a running desktop session, which means it can't run unattended on a headless Linux server, and it's prone to crashes that kill the stream without restarting automatically.
The second is FFmpeg on a VPS — a command-line tool that reads your radio stream URL, combines it with a static image or video loop, and pushes the result directly to YouTube's RTMP endpoint. This is the better option for reliable 24/7 operation because it runs as a background process on a Linux server and can be set to restart automatically on failure.
Method 1: OBS Studio Setup
Download and install OBS Studio from obsproject.com. On first launch, go through the Auto-Configuration Wizard — select "Optimize for streaming, recording is secondary" and choose YouTube as the service.
Go to Settings → Stream. Set Service to "YouTube - RTMP". Enter your Stream Key. Under Output settings, set Video Bitrate to 2500-4000 kbps (enough for 1080p video), Audio Bitrate to 192 kbps for decent audio quality.
Set your base resolution to 1920x1080 (or 1280x720 if your server/PC is modest). Set the output resolution the same. Frame rate: 30fps is standard — 24fps works fine for a static visual radio stream and reduces bandwidth by 20%.
In the main OBS window, add your sources: an Image source for your station logo/background, and a Browser source or Audio Input source for your radio stream. To pull audio from your existing radio stream URL, use VLC's virtual audio output as an audio input in OBS.
Creating a Visual for Your Radio Stream
YouTube requires a video signal. For radio stations, the visual is typically a static or animated background with the station logo. The simplest approach is a 1920x1080 PNG image as your entire OBS scene — design it in Canva, Photoshop, or GIMP with your station branding, frequency, and "Live 24/7" text.
For a more polished look, use a looping video (MP4) as a background — animated waveforms, a visualizer, or slow-motion B-roll of your studio. In OBS, add a Media Source, select your loop file, and check "Loop". This creates motion without requiring any real-time processing.
If you want a real-time audio visualizer showing the waveform of your stream, add a Browser source in OBS pointing to a local HTML visualizer file. There are free HTML5 audio visualizers on GitHub that hook into browser audio and render animated waveforms — these work well as OBS Browser sources and add visual interest at near-zero CPU cost.
Method 2: FFmpeg on VPS (Recommended for 24/7)
This is the robust, production-grade approach. Install FFmpeg on your Linux VPS:
apt update && apt install ffmpeg -y
ffmpeg -version # Confirm installation
The core FFmpeg command to stream your radio to YouTube takes your radio stream URL as audio input, a static image as video input, encodes them together, and pushes to YouTube's RTMP server:
ffmpeg \
-re -loop 1 -i /path/to/background.jpg \
-i http://yourserver:8000/stream \
-vf "scale=1920:1080" \
-c:v libx264 -preset veryfast -b:v 3000k \
-c:a aac -b:a 192k -ar 44100 \
-f flv rtmp://a.rtmp.youtube.com/live2/YOUR_STREAM_KEY
Break down of the key flags: -loop 1 tells FFmpeg to treat the image as an infinite loop, -re reads input at native frame rate (essential for streaming — without it FFmpeg processes the image as fast as possible and crashes), -preset veryfast balances quality vs CPU usage, and -f flv is YouTube's required container format.
For a looping video background instead of a static image, replace the image input with a video file and add -stream_loop -1 before the input:
ffmpeg \
-stream_loop -1 -i /path/to/loop.mp4 \
-i http://yourserver:8000/stream \
-c:v libx264 -preset veryfast -b:v 3000k \
-c:a aac -b:a 192k -ar 44100 \
-shortest -f flv rtmp://a.rtmp.youtube.com/live2/YOUR_STREAM_KEY
Need this fixed by an expert?
RadioTech Studio diagnoses and fixes radio issues fast — usually same day. Send us your details.
Auto-Restart Script for Uninterrupted Streaming
FFmpeg will occasionally crash — network glitches, YouTube API resets, or memory issues. The solution is a simple bash loop that restarts FFmpeg automatically when it exits. Save this as /home/radio/stream.sh:
#!/bin/bash
STREAM_KEY="YOUR_STREAM_KEY_HERE"
RADIO_URL="http://yourserver:8000/stream"
IMAGE="/home/radio/background.jpg"
while true; do
echo "[$(date)] Starting FFmpeg stream..."
ffmpeg \
-re -loop 1 -i "$IMAGE" \
-i "$RADIO_URL" \
-vf "scale=1920:1080" \
-c:v libx264 -preset veryfast -b:v 3000k \
-c:a aac -b:a 192k -ar 44100 \
-f flv "rtmp://a.rtmp.youtube.com/live2/$STREAM_KEY"
echo "[$(date)] FFmpeg exited. Restarting in 5 seconds..."
sleep 5
done
Make it executable and run it in a persistent screen or tmux session:
chmod +x /home/radio/stream.sh
apt install screen -y
screen -S youtube-stream
/home/radio/stream.sh
# Press Ctrl+A then D to detach from the screen session
For a more robust production setup, convert this to a systemd service so it survives VPS reboots automatically:
# /etc/systemd/system/youtube-stream.service
[Unit]
Description=YouTube 24/7 Radio Stream
After=network.target
[Service]
Type=simple
User=radio
ExecStart=/home/radio/stream.sh
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable youtube-stream
systemctl start youtube-stream
systemctl status youtube-stream
YouTube Live Settings That Matter
In YouTube Studio → Go Live → Manage, set your stream to "Persistent Stream" — this keeps the same stream URL active indefinitely so you don't need a new key after each session. Without this, YouTube assigns a new stream key each time you create a live event, which breaks your automation setup.
Set your stream's privacy to "Public" and enable DVR (allows viewers to rewind up to 4 hours). Set the stream latency to "Low latency" — for radio this doesn't matter much, but it reduces the delay for viewers from 30-60 seconds down to ~10 seconds.
YouTube will occasionally end streams that go inactive for more than 12 hours even with a persistent stream key. If this happens, your auto-restart script won't help because FFmpeg is still running — YouTube ended the stream on their end. The workaround is to have your script check the stream status via the YouTube Data API and restart the stream programmatically when YouTube kills it.
Common Problems and Fixes
FFmpeg exits immediately with "Connection refused" or "403 Forbidden": Your stream key is wrong or the YouTube persistent stream isn't active. Go to YouTube Studio and confirm the live stream is in "Ready" state before starting FFmpeg.
Video and audio out of sync after a few hours: This happens when the audio source (your radio stream) has a slightly different clock than FFmpeg's internal timer. Add -async 1 to the FFmpeg command to enable audio sync correction. For severe drift, add -fflags +genpts before your inputs.
High CPU usage on VPS: The libx264 -preset veryfast combination is chosen specifically for low CPU usage. If CPU is still high, drop the video bitrate to 1500k and scale the output to 1280x720 — most radio stream viewers don't need 1080p.
Stream shows "offline" on YouTube even though FFmpeg is running: YouTube requires a video signal within a certain time of the stream key being activated. If FFmpeg starts but YouTube shows offline, check for FFmpeg errors in the script output — a common cause is the radio stream URL being temporarily unavailable when FFmpeg starts, causing it to fail silently.