Skip to content

Instantly share code, notes, and snippets.

@Ponywka
Last active April 15, 2022 12:46
Show Gist options
  • Save Ponywka/cfe6daf22646612b5c76f34f8edb01f0 to your computer and use it in GitHub Desktop.
Save Ponywka/cfe6daf22646612b5c76f34f8edb01f0 to your computer and use it in GitHub Desktop.
FFmpeg IceCast Stream
RADIO_URL=http://localhost/radio/8000/320.mp3
STREAM_URL=rtmp://a.rtmp.youtube.com/live2/xxxx-xxxx-xxxx-xxxx-xxxx
TITLE_FILE=/tmp/icy-yt-title
ARTIST_FILE=/tmp/icy-yt-artist

You can download RobotoCondensed-Regular.ttf here: https://fonts.google.com/specimen/Roboto+Condensed

You need to create bg.png file with 1280x720px image

You need have installed ffmpeg python3 python3-pip packages

Commands to install:

chmod +x install.sh
chmod +x start_stream.sh
chmod +x start_monitor.sh
./install.sh

Run stream:

./start_stream.sh
./start_monitor.sh
pip install virtualenv
virtualenv -p python3 venv
source venv/bin/activate
pip install -r requirements.txt
from __future__ import unicode_literals
import re
import requests
import sys
def icy_monitor(stream_url, callback=None):
r = requests.get(stream_url, headers={'Icy-MetaData': '1'}, stream=True)
if r.encoding is None:
r.encoding = 'utf-8'
metadata_size = int(r.headers.get('icy-metaint'))
bytecount = 0
state = 0
blocksize = 0
metadata_bytes = bytearray()
for chunk in r.iter_content(1):
bytecount += 1
# Skipping music data
if state == 0:
if bytecount == metadata_size:
# Clean data and go to next state
state = 1
bytecount = 0
# Getting metadata size (bytes / 16)
elif state == 1:
blocksize = int.from_bytes(chunk, byteorder='big', signed=False)
# Clean data and go to next state
bytecount = 0
if blocksize == 0:
state = 0
else:
state = 2
# Getting metadata
elif state == 2:
metadata_bytes += chunk
if bytecount == blocksize * 16:
m = re.search(br"StreamTitle='([^']*)';", metadata_bytes)
if m:
title = m.group(1).decode(r.encoding, errors='replace')
if callback:
callback(title)
# Clean data and go to next state
bytecount = 0
state = 0
blocksize = 0
metadata_bytes = bytearray()
def print_title(title):
print('Current track: {}'.format(title))
meta = re.search(r"^([\s\S]+?) - ([\s\S]+)$", title)
if meta:
file = open(sys.argv[2], 'w')
file.write(meta.group(2))
file.close()
file = open(sys.argv[3], 'w')
file.write(meta.group(1))
file.close()
else:
file = open(sys.argv[2], 'w')
file.write(title)
file.close()
file = open(sys.argv[3], 'w')
file.write('Unknown')
file.close()
if __name__ == '__main__':
stream_url = sys.argv[1]
icy_monitor(stream_url, callback=print_title)
pip install virtualenv
virtualenv -p python3 venv
source venv/bin/activate
pip install -r requirements.txt
requests
export $(grep -v '^#' .env | xargs)
source venv/bin/activate
while true;
do
echo "Monitor start...";
python monitor.py "$RADIO_URL" "$TITLE_FILE" "$ARTIST_FILE";
echo "Sleeping 5 seconds...";
sleep 5;
done
export $(grep -v '^#' .env | xargs)
if [ ! -e $TITLE_FILE ]; then
echo "" > $TITLE_FILE;
fi
if [ ! -e $ARTIST_FILE ]; then
echo "" > $ARTIST_FILE;
fi
while true;
do
echo "FFmpeg start...";
ffmpeg \
-loop 1 -y -i bg.png -r 1 \
-i "$RADIO_URL" \
-vf "drawtext=fontfile=RobotoCondensed-Regular.ttf:textfile=$TITLE_FILE:reload=1:x=12:y=593:fontsize=36:fontcolor=white,drawtext=fontfile=RobotoCondensed-Regular.ttf:textfile=$ARTIST_FILE:reload=1:x=12:y=635:fontsize=24:fontcolor=white" \
-af "volume=0.8" \
-c:a aac -b:a 192k \
-r 1 -c:v libx264 -x264-params keyint=5:scenecut=0 -f flv \
-shortest "$STREAM_URL";
echo "Sleeping 5 seconds...";
sleep 5;
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment