This guide walks you through setting up a continuous 24/7 livestream of devotional content (scripture, worship music, or sermon loops) using Docker and FFmpeg. You’ll create a container that runs FFmpeg to combine a video loop with an audio playlist, encode it, and push it to a streaming platform like YouTube or Twitch. By the end, you’ll have a reliable, always-on stream that restarts automatically if it crashes.
What You’ll Need
- A server or PC that stays on 24/7 (a cheap VPS or an old laptop works).
- Docker and Docker Compose installed (see Docker’s official docs).
- FFmpeg installed locally for testing (optional but helpful).
- A streaming platform account (YouTube, Twitch, Facebook Live) with a stream key and stream URL.
- Media files: a video loop (MP4) and an audio playlist (MP3 or M4A). You can use royalty-free sources like Pixabay or the Bible Project’s open content.
Step-by-Step
- Prepare your media files. Create a folder on your server, e.g.,
/opt/devotional-stream, and inside it create subfolders:video/andaudio/. Place your video loop (e.g.,background.mp4) and your audio files (e.g.,song1.mp3,song2.mp3) in the respective folders. Ensure the video loop is long enough (at least 30 seconds) and loops seamlessly (no abrupt cuts). - Create a playlist file for audio. In the
audio/folder, create a text file namedplaylist.txtwith the following content (one file per line, using relative paths):file 'song1.mp3' file 'song2.mp3'
FFmpeg will loop this playlist indefinitely.
- Write a Dockerfile. In the root folder (
/opt/devotional-stream), create a file namedDockerfilewith this content:FROM alpine:latest RUN apk add --no-cache ffmpeg WORKDIR /media COPY video/ video/ COPY audio/ audio/ CMD ["/bin/sh", "/media/stream.sh"]
This uses a minimal Alpine Linux image with FFmpeg installed. The
CMDwill run a script we’ll create next. - Create the streaming script. In the same folder, create a file named
stream.shwith the following content:#!/bin/sh while true; do ffmpeg -re -stream_loop -1 -i video/background.mp4 -f concat -safe 0 -i audio/playlist.txt -c:v libx264 -preset veryfast -b:v 2500k -maxrate 2500k -bufsize 5000k -pix_fmt yuv420p -g 60 -c:a aac -b:a 128k -ar 44100 -f flv rtmp://a.rtmp.youtube.com/live2/STREAM_KEY echo "Stream ended, restarting in 5 seconds..." sleep 5 done
Replace
STREAM_KEYwith your actual stream key (or the full RTMP URL if your platform uses a different format). The-reflag reads input at native speed,-stream_loop -1loops the video forever, and the concat demuxer reads the playlist. The output is encoded in H.264/AAC and sent via RTMP. - Make the script executable. Run
chmod +x stream.shin the folder. - Create a docker-compose.yml. In the same folder, create
docker-compose.ymlwith:services: stream: build: . container_name: devotional-stream restart: unless-stopped environment: - STREAM_KEY=your_key_here volumes: - ./media:/mediaThis sets the container to restart automatically unless it’s manually stopped, which is crucial for 24/7 operation. The
STREAM_KEYenvironment variable is passed to the script, but note that the script currently hardcodes the key; you can modify it to use$STREAM_KEYinstead. - Build and start the container. Run
docker-compose up -d --buildin the folder. This builds the image and starts the container in detached mode. - Verify the stream. Check the logs with
docker logs -f devotional-stream. You should see FFmpeg output showing the encoding process. If there are errors, see the Troubleshooting section below. Then check your streaming platform’s dashboard to confirm the stream is live.
Common Mistakes
- Using absolute paths in the playlist. The concat demuxer requires relative paths (or
-safe 0for absolute). Use relative paths to avoid issues. - Forgetting to loop the video. Without
-stream_loop -1, the video will end and the stream will stop. Make sure to include it. - Incorrect stream key or URL. Double-check your streaming platform’s RTMP URL and key. They are often long and easy to mistype.
- Not making the script executable. If you get a permission denied error, run
chmod +x stream.sh. - Using a video that is too short. A very short video (e.g., 2 seconds) may cause buffering or stuttering. Use a loop of at least 30 seconds.
Tips
- Test locally first. Run the FFmpeg command on your local machine (without Docker) to verify your media files and stream key work. Replace the RTMP URL with a local test server if needed.
- Use a higher bitrate for better quality. If your internet upload speed allows, increase
-b:vto 4500k or higher for 1080p. For 720p, 2500k is fine. - Add a fallback image. If your video fails, you can use
-loop 1 -i image.jpgas a fallback. But thewhile trueloop already restarts the stream, so this is optional. - Monitor your stream. Use a service like UptimeRobot to ping your stream’s URL and alert you if it goes down.
- Keep your media files organized. Use a separate volume for media so you can update songs without rebuilding the container.
Troubleshooting
- Stream won’t start: “Connection refused” or “Invalid key”. Check your RTMP URL and stream key. For YouTube, the URL is
rtmp://a.rtmp.youtube.com/live2and the key is in your live dashboard. For Twitch, usertmp://live.twitch.tv/app. - FFmpeg errors about codec or pixel format. Ensure your video is H.264 encoded (or let FFmpeg re-encode with
-c:v libx264). The-pix_fmt yuv420pflag ensures compatibility. - Stream drops after a few minutes. This is often due to network instability or the platform kicking the connection. Check your server’s bandwidth and try lowering the bitrate. Also, the
while trueloop will restart it, but you may see gaps. - Audio not playing. Make sure the playlist file uses relative paths and that the audio files exist. Also, ensure the audio codec is AAC (
-c:a aac). - Container exits immediately. Check the logs with
docker logs devotional-stream. It might be a missing file or a permission issue. Ensure the media folder is mounted correctly. - High CPU usage. The
veryfastpreset is a good balance. If you have a weak CPU, useultrafastbut lower the bitrate to avoid quality loss.
Frequently Asked Questions
Can I use this for a radio-style stream with just audio?
Yes. Remove the video input and use a still image or a black background video. For audio-only, you can use -f lavfi -i anullsrc as a placeholder, but a simple video loop is easier.
How do I update the playlist without restarting the container?
You can edit the playlist.txt file on the host, and the next time the stream loops (every 5 seconds after a crash), it will pick up the changes. To force an immediate restart, run docker restart devotional-stream.
What if my streaming platform requires a different protocol, like SRT?
FFmpeg supports SRT via -c copy -f mpegts 'srt://...'. You’ll need to adjust the output URL and possibly the codec settings. Consult your platform’s documentation.
Can I run multiple streams with this setup?
Yes, by creating multiple containers with different names and stream keys. Use separate folders for each stream’s media.
How do I schedule different content for different times of day?
You can use a cron job to swap the playlist file or video file at specific times. For example, a script that replaces playlist.txt with a morning or evening version.
Is it legal to stream copyrighted worship music?
You need proper licenses. Many churches use CCLI or similar licenses. For royalty-free music, use sources like the Free Music Archive or create your own. Always check the terms.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.
More cards in this drawer
- Increase Internal Memory Xiaomi Phones: How-To
- Nvidia Display Settings Are Not Available: Fixes
- Gmod Keeps Crashing? Fixes That Actually Work
- Cloudflare cf CLI: How Coding Agents Discover & Run Commands
- Protect AI from Model Extraction & Distillation
- Net Code Analysis Workflow: A Reliable Setup Guide