Last active
May 24, 2019 19:27
-
-
Save fitz123/e0e2921ae81b4b5136ec7b3b53079807 to your computer and use it in GitHub Desktop.
Supervisor ffmpeg transcoding job and HLS playlist generator
This file contains 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 | |
############################################################################### | |
# | |
# Description: | |
# Script generates Nimble session-friendly playlists | |
# (parent playlist with sub-playlists inside) and supervisor program/job | |
# of ffmpeg process which pulls from provided source address $ch_source and | |
# pushes to localhost nibmle-origin server as a name $ch_res for later HLS transmuxing | |
# | |
# To generate playlists and jobs - templates are used (playlist.template,*-job.template) | |
# | |
# As a result followed files will be generated: | |
# * $supervisor_confd/ffmpeg-$ch_name - supervisor job | |
# * $playlist_root/$ch_name-$ch_res.m3u8 - "parent" playlist for stream | |
# (if 3rd arg is 'abr' also playlist for each resolution will be created) | |
# * $playlist_root/$ch_name.m3u8 - symlink to parent playlist | |
# | |
# No output and 0 exit status means everything good, job is started! | |
# | |
# Usage example: | |
# sudo ./job_gen.sh rtmp://27.131.165.98:1935/dvrorigin1/hd-foxpremiumeng_1080 fox abr | |
# | |
# Parameters: | |
# $1) source to grab stream from | |
# $2) name to publish stream as. Also creates supervisor "program" with the same name | |
# $3) template to apply for job and playlist generation. | |
# Possibly values are: | |
# * 240p, 360p, 480p, 720p - each value generates single transcoding job and playlist | |
# * copy - re-publishes stream without transcoding and creates playlist | |
# * abr - generates transcoding job for multiple resolutions, | |
# creates combined playlist with all resolutions for ABR streaming and | |
# playlist for each resolution separatelly | |
# | |
# script: job_gen.sh | |
# ver: 0.1 | |
# author: [email protected] | |
# | |
############################################################################### | |
playlist_root='/srv/media-server/live' | |
supervisor_confd='/etc/supervisor/conf.d' | |
resolutions='720p 480p 360p 240p copy' | |
templates='240p-job.template 480p-job.template abr-job.template copy-job.template 360p-job.template 720p-job.template abr-playlist.template playlist.template' | |
bw_240p='500000' | |
bw_360p='1000000' | |
bw_480p='1500000' | |
bw_720p='3000000' | |
bw_copy='9999999' | |
ch_source="$1" | |
ch_name="$2" | |
ch_res="$3" | |
# fix resolution parameter if passed without trailing p | |
[ ! 'copy' == "$ch_res" -a ! 'abr' == "$ch_res" -a ! 'p' == "${ch_res:(-1)}" ] && ch_res=$3p | |
## | |
# checks | |
## | |
print_readme() { | |
printf ' | |
Usage example: | |
sudo ./job_gen.sh rtmp://27.131.165.98:1935/dvrorigin1/hd-foxpremiumeng_1080 fox abr | |
Parameters: | |
$1) source to grab stream from | |
$2) name to publish stream as. Also creates supervisor "program" with a such name | |
$3) template to apply for job and playlist generation. | |
Possibly values are: | |
* 240p, 360p, 480p, 720p - each value generates single transcoding job and playlist | |
* copy - generates "copy" and playlist | |
* abr - generates transcoding job for multiple resolutions, | |
creates combined playlist with all resolutions for ABR streaming and | |
playlist for each resolution separatelly | |
' | |
} | |
# check if run not as root | |
if [ "$EUID" -ne 0 ] | |
then echo "Please run as root" | |
exit 1 | |
fi | |
# check arguments number | |
if [ "$#" -ne 3 ]; then | |
echo "Error: Illegal number of parameters" | |
print_readme | |
exit 1 | |
fi | |
# check resolution | |
if [[ ! "$resolutions" =~ "$ch_res" ]]; then | |
if [ ! 'abr' == "$ch_res" ]; then | |
echo "Error: Illegal resolution $ch_res" | |
print_readme | |
exit 1 | |
fi | |
fi | |
# check supervisor config directory | |
[ -d "$supervisor_confd" ] || { echo Error: directory "$supervisor_confd" directory does not exist ; exit 1 ;} | |
# check playlist root | |
[ -d "$playlist_root" ] || { echo Error: directory "$playlist_root" directory does not exist ; exit 1 ;} | |
# check stream directories | |
for dir in $resolutions; do [ -d "$playlist_root/$dir" ] || { echo Error: directory "$playlist_root/$dir" directory does not exist ; exit 1 ;}; done | |
# check templates required for jobs and playlists generation | |
for tpl in $templates; do | |
if [ ! -e "$tpl" -o ! -f "$tpl" -o ! -s "$tpl" -o ! -r "$tpl" ]; then | |
echo Error: template "$tpl" does not exist, not a file, zero size or not readable | |
exit 1 | |
fi | |
done | |
# check ffmpeg/ffprobe installed | |
command -v ffmpeg >/dev/null 2>&1 || { echo >&2 "I require ffmpeg but it's not installed. Aborting."; exit 1; } | |
command -v ffprobe >/dev/null 2>&1 || { echo >&2 "I require ffprobe but it's not installed. Aborting."; exit 1; } | |
# check source | |
ffprobe "$ch_source" 2>&1 | egrep "^\s+Stream.+Video." >/dev/null 2>&1 || { echo Error: stream source $ch_source has no video or invalid ; exit 1 ;} | |
## | |
# generate playlists | |
## | |
if [ $ch_res == 'abr' ]; then | |
# playlist with all resolutions | |
sed -e "s;%channel_name%;$ch_name;g" $ch_res-playlist.template > $playlist_root/$ch_name-$ch_res.m3u8 | |
ln -f -s $playlist_root/$ch_name-$ch_res.m3u8 $playlist_root/$ch_name.m3u8 | |
for res in $resolutions; do | |
# playlist for nimble sessions compatibility for each resolution inside abr group | |
bw=bw_$res | |
sed -e "s;%channel_name%;$ch_name;g" -e "s;%resolution%;$res;g" -e "s;%bandwidth%;${!bw};g" playlist.template > $playlist_root/$ch_name-$res.m3u8 | |
done | |
else | |
# playlist for nimble sessions compatibility | |
bw=bw_$ch_res | |
sed -e "s;%channel_name%;$ch_name;g" -e "s;%resolution%;$ch_res;g" -e "s;%bandwidth%;${!bw};g" playlist.template > $playlist_root/$ch_name-$ch_res.m3u8 | |
ln -f -s $playlist_root/$ch_name-$ch_res.m3u8 $playlist_root/$ch_name.m3u8 | |
fi | |
## | |
# generate supervisor job | |
## | |
# detect if stream is http then apply additional parameters for input robustness | |
input_proto=$(echo "$ch_source" | cut -d: -f1) | |
if [ "$input_proto" == 'http' ]; then | |
stream_input_parameters='-reconnect_at_eof 1 -reconnect_streamed 1' | |
elif [ "$input_proto" == "$ch_source" ]; then | |
stream_input_parameters='-re' | |
else | |
stream_input_parameters='' | |
fi | |
sed -e "s;%channel_source%;$ch_source;g" -e "s;%channel_name%;$ch_name;g" -e "s;%stream_input_parameters%;$stream_input_parameters;g" $ch_res-job.template > $supervisor_confd/ffmpeg-$ch_name.conf | |
supervisorctl update && sleep 3 && \ | |
job_status=$(supervisorctl status $ch_name | awk '{print $2}') && \ | |
[ ! $job_status == 'RUNNING' ] && echo Job has been started but something went wrong. Job status is $job_status && exit 1 | |
exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
abr-playlist.template:
playlist.template:
abr-job.template:
copy-job.template: