Last active
June 3, 2024 18:55
-
-
Save ParkWardRR/9f0a5fd583e57f190ba8d538eefe02b1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# ============================= | |
# Script: YouTubeRelayService.sh | |
# Description: This script is designed to fetch and serve YouTube live streams, | |
# especially useful for bypassing YouTube geo-blocks by running on a lightweight VPS. | |
# It can be particularly effective for continuous streams such as 24-hour live streams. | |
# This script is intended to bootstrap an Ubuntu host. | |
# ============================= | |
# Dependencies and Installation Steps: | |
# - Update and upgrade system packages | |
# - Install necessary packages: python3-pip, ffmpeg, curl, pipx | |
# - Install yt-dlp using pipx if not already installed | |
# - Set up a public_html directory | |
# - Validate FFmpeg functionality | |
# - Install and configure the Caddy web server to serve the stream | |
# ============================= | |
# Server Configuration: | |
# CPU: 2B | |
# Memory: 4 GB | |
# ============================= | |
# ============================ | |
# User Configuration (Edit these variables as needed) | |
# WARNING: Do not use 0.0.0.0/0 for ALLOWED_IP for safety reasons | |
# ============================ | |
YOUTUBE_URL="https://www.youtube.com/live/lAcLSbWhVEs?si=vz398W-IQ62FM_6B" # The URL of the YouTube live stream | |
ALLOWED_IP="111.11.11.187/32" # IP address range allowed to access the stream | |
SEGMENTS_DURATION=10 # Duration of each HLS segment in seconds | |
SEGMENTS_COUNT=3 # Number of HLS segments to keep | |
# ===================== | |
# Script Execution Starts | |
# ===================== | |
# Function to output error message but continue (no exit) | |
function error_report { | |
echo "[ERROR] $1" 1>&2 | |
} | |
# Kill any existing ffmpeg processes to avoid conflicts | |
function kill_ffmpeg_processes { | |
echo "Killing any existing ffmpeg processes..." | |
pkill -f ffmpeg | |
} | |
# Trap function to kill ffmpeg processes on script exit | |
function on_exit { | |
echo "Cleaning up before exit..." | |
kill_ffmpeg_processes | |
echo "Exiting script." | |
exit 0 | |
} | |
trap on_exit SIGINT SIGTERM | |
kill_ffmpeg_processes # Ensure any existing ffmpeg processes are killed at the beginning | |
# Function to start ffmpeg process in a loop with logging | |
function start_ffmpeg { | |
while true; do | |
echo "Fetching and converting live stream..." | |
FFMPEG_URL=$(yt-dlp -g "$YOUTUBE_URL" 2>/dev/null) | |
if [ -z "$FFMPEG_URL" ]; then | |
echo "[ERROR] Could not retrieve FFmpeg URL. Retrying in 10 seconds..." | |
sleep 10 | |
continue | |
fi | |
ffmpeg -re -i "$FFMPEG_URL" -c copy -f hls -hls_time $SEGMENTS_DURATION -hls_list_size $SEGMENTS_COUNT -hls_flags delete_segments /home/$USER/public_html/stream.m3u8 &> /home/$USER/ffmpeg.log | |
if [ $? -ne 0 ]; then | |
error_report "FFmpeg encountered an error. Check /home/$USER/ffmpeg.log for details." | |
sleep 10 | |
else | |
echo "[INFO] FFmpeg process ended. Restarting in 10 seconds..." | |
sleep 10 | |
fi | |
done | |
} | |
# Update and upgrade the system packages | |
echo "Updating and upgrading the system..." | |
apt update -y && apt upgrade -y || error_report "Failed to update and upgrade the system." | |
# Install necessary packages including Python, ffmpeg, and curl if not already installed | |
echo "Checking and installing necessary packages..." | |
if ! dpkg -l | grep -qw python3-pip; then | |
apt install -y python3-pip || error_report "Failed to install python3-pip." | |
fi | |
if ! dpkg -l | grep -qw ffmpeg; then | |
apt install -y ffmpeg || error_report "Failed to install ffmpeg." | |
fi | |
if ! dpkg -l | grep -qw curl; then | |
apt install -y curl || error_report "Failed to install curl." | |
fi | |
# Install pipx if not already installed | |
if ! command -v pipx &> /dev/null; then | |
echo "pipx not found, installing..." | |
apt install -y pipx || error_report "Failed to install pipx." | |
pipx ensurepath | |
source ~/.bashrc | |
fi | |
# Install yt-dlp using pipx if not already installed | |
export PATH=$PATH:/root/.local/bin | |
if ! command -v yt-dlp &> /dev/null; then | |
echo "yt-dlp is not found in PATH, attempting reinstallation with pipx..." | |
# Remove any existing installation in pipx before reinstalling | |
pipx uninstall yt-dlp | |
pipx install yt-dlp | |
# Ensure the PATH is updated | |
export PATH=$PATH:/root/.local/bin | |
if ! command -v yt-dlp &> /dev/null; then | |
error_report "yt-dlp could not be installed or found in PATH." | |
fi | |
else | |
echo "yt-dlp is already installed." | |
fi | |
# Ensure yt-dlp is accessible from the current shell | |
export PATH=$PATH:~/.local/bin | |
# Create public_html directory if it doesn't exist | |
echo "Creating public_html directory..." | |
mkdir -p /home/$USER/public_html || error_report "Failed to create public_html directory." | |
chmod -R 755 /home/$USER/public_html # Ensure sufficient permissions | |
chown -R root:root /home/$USER/public_html | |
# Create a simple test HTML file to verify the directory | |
echo "<html><body><h1>Test Page</h1></body></html>" > /home/$USER/public_html/index.html | |
# Ensure FFmpeg is able to generate the .m3u8 file | |
echo "Testing FFmpeg output..." | |
start_ffmpeg & | |
sleep 20 | |
if [ ! -f /home/$USER/public_html/stream.m3u8 ]; then | |
error_report "FFmpeg did not generate the m3u8 file. Check ffmpeg.log for errors." | |
else | |
echo "[INFO] FFmpeg successfully generated the m3u8 file." | |
pkill ffmpeg # Stop running ffmpeg as the first test passed | |
fi | |
# Install Caddy web server if not already installed | |
if ! command -v caddy &> /dev/null; then | |
echo "Installing Caddy web server..." | |
apt install -y debian-keyring debian-archive-keyring apt-transport-https | |
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo apt-key add - | |
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee -a /etc/apt/sources.list.d/caddy-stable.list | |
apt update | |
apt install caddy || error_report "Failed to install Caddy." | |
else | |
echo "[INFO] Caddy is already installed." | |
fi | |
# Configure Caddy to serve the stream | |
echo "Configuring Caddy..." | |
cat > /etc/caddy/Caddyfile <<EOF | |
http://$(curl -s ifconfig.me) { | |
root * /home/$USER/public_html | |
file_server | |
encode gzip | |
@allowedIps not remote_ip $ALLOWED_IP | |
respond @allowedIps 403 { | |
close | |
body "Access denied" | |
} | |
} | |
EOF | |
# Restart Caddy to apply the new configuration | |
echo "Restarting Caddy to apply the configuration..." | |
systemctl restart caddy || error_report "Failed to restart Caddy." | |
# Check Caddy status silently | |
if systemctl is-active --quiet caddy; then | |
echo "[INFO] Caddy is running and serving the stream." | |
else | |
error_report "Caddy is not running. Please check Caddy logs for more details." | |
fi | |
# Verify that m3u8 file is accessible | |
ACCESS_URL="http://$(curl -s ifconfig.me)/stream.m3u8" | |
sleep 10 | |
RESPONSE=$(curl -I "$ACCESS_URL" 2>/dev/null | head -n 1 | cut -d' ' -f2) | |
if [ "$RESPONSE" == "200" ]; then | |
echo "========================================" | |
echo "The stream is accessible at: $ACCESS_URL" | |
echo "========================================" | |
else | |
error_report "Caddy is not serving the m3u8 file correctly. HTTP Response Code: $RESPONSE" | |
echo "Check ffmpeg is running correctly by examining the log file: /home/$USER/ffmpeg.log" | |
echo "Check Caddy error logs with: journalctl -u caddy" | |
fi | |
echo "Checking if ffmpeg and caddy processes are running..." | |
# Check if ffmpeg process is running | |
if pgrep -x "ffmpeg" > /dev/null | |
then | |
echo "[INFO] FFmpeg is running." | |
else | |
error_report "FFmpeg is not running." | |
fi | |
# Check if caddy process is running | |
if pgrep -x "caddy" > /dev/null | |
then | |
echo "[INFO] Caddy is running." | |
else | |
error_report "Caddy is not running." | |
fi | |
echo "The script has completed. Please try accessing the stream at the following URL to confirm it is working:" | |
echo "========================================" | |
echo "The stream is accessible at: $ACCESS_URL" | |
echo "========================================" | |
# Kill any remaining ffmpeg processes at the end | |
kill_ffmpeg_processes |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment