Created
March 9, 2020 18:47
-
-
Save prochor666/d47cd8e1eb07255c248bcbe6614f5c02 to your computer and use it in GitHub Desktop.
Bash VOD/HLS media convertor
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 | |
# Sanatorium media convertor | |
# prochor, 2020 | |
# prochor666@gmail.com | |
clear | |
# Create new website | |
echo -e "\e[38;5;14m|------------------------------------------- \e[0m" | |
echo -e "\e[38;5;14m| Sanatorium VOD/HLS media convertor \e[0m" | |
echo -e "\e[38;5;14m|------------------------------------------- \e[0m" | |
echo -e "\e[38;5;14m| \e[0m" | |
echo -e "\e[38;5;14m| * ffmpeg HLS convertor \e[0m" | |
echo -e "\e[38;5;14m| \e[0m" | |
echo -e "\e[38;5;14m| prochor666@gmail.com \e[0m" | |
echo -e "\e[38;5;14m|------------------------------------------- \e[0m" | |
echo -e " " | |
#set -e | |
# Usage scrintname.sh SOURCE_FILE | |
[[ ! "${1}" ]] && echo "Usage: ${0} SOURCE_FILE" && exit 1 | |
ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )" | |
MEDIAFILE=$1 | |
SOURCEDIR="$ROOT/src" | |
TARGETDIR="$ROOT/vod/hs" | |
FILENAME=$(basename -- "$MEDIAFILE") | |
EXT="${FILENAME##*.}" | |
FNO="${FILENAME%.*}" | |
echo $SOURCEDIR/$MEDIAFILE | |
CHECK=$(md5sum "$SOURCEDIR/$MEDIAFILE" | awk '{ print $1 }') | |
NEWFILE="${CHECK[0]}" | |
WEBUSER=$(ls -ld "$ROOT/index.php" | awk '{print $3}') | |
WEBGROUP=$(ls -ld "$ROOT/index.php" | awk '{print $4}') | |
echo $NEWFILE | |
if [ ! -d "$TARGETDIR/$NEWFILE" ]; then | |
mkdir "$TARGETDIR/$NEWFILE" | |
chown -R $WEBUSER:$WEBGROUP "$TARGETDIR/$NEWFILE" | |
fi | |
# comment/add lines here to control which OUTPUTRESOLUTIONS would be created | |
OUTPUTRESOLUTIONS=( | |
# resolution bitrate audio-rate | |
"426x240 400k 64k" | |
"640x360 800k 96k" | |
"842x480 1400k 128k" | |
"1280x720 2800k 128k" | |
"1920x1080 5000k 192k" | |
) | |
SEGMENT_TARGET_DURATION=4 # try to create a new segment every X seconds | |
MAX_BITRATE_RATIO=1.07 # maximum accepted bitrate offset | |
RATE_MONITOR_BUFFER_RATIO=1.5 # maximum buffer size between bitrate conformance checks | |
######################################################################### | |
SOURCE="$SOURCEDIR/$MEDIAFILE" | |
TARGET="$TARGETDIR/$NEWFILE" | |
MAXHEIGHT="$(ffprobe -v error -select_streams v:0 -show_entries stream=height -of csv=p=0 ${SOURCE})" | |
KEY_FRAMES_INTERVAL="$(echo `ffprobe ${SOURCE} 2>&1 | grep -oE '[[:digit:]]+(.[[:digit:]]+)? fps' | grep -oE '[[:digit:]]+(.[[:digit:]]+)?'`*2 | bc || echo '')" | |
KEY_FRAMES_INTERVAL=${KEY_FRAMES_INTERVAL:-50} | |
KEY_FRAMES_INTERVAL=$(echo `printf "%.1f\n" $(bc -l <<<"$KEY_FRAMES_INTERVAL/10")`*10 | bc) # round | |
KEY_FRAMES_INTERVAL=${KEY_FRAMES_INTERVAL%.*} # truncate to integer | |
# static parameters that are similar for all OUTPUTRESOLUTIONS | |
STATIC_PARAMS="-c:a aac -ar 48000 -c:v h264 -profile:v main -crf 20 -sc_threshold 0" | |
STATIC_PARAMS+=" -g ${KEY_FRAMES_INTERVAL} -keyint_min ${KEY_FRAMES_INTERVAL} -hls_time ${SEGMENT_TARGET_DURATION}" | |
STATIC_PARAMS+=" -hls_playlist_type vod" | |
# misc params | |
MISC_PARAMS="-hide_banner -y" | |
CAN_START=0 | |
MASTER_PLAYLIST="#EXTM3U | |
#EXT-X-VERSION:3 | |
" | |
CMD="" | |
for OUTPUTRESOLUTION in "${OUTPUTRESOLUTIONS[@]}"; do | |
# drop extraneous spaces | |
OUTPUTRESOLUTION="${OUTPUTRESOLUTION/[[:space:]]+/ }" | |
# OUTPUTRESOLUTION fields | |
RESOLUTION="$(echo ${OUTPUTRESOLUTION} | cut -d ' ' -f 1)" | |
BITRATE="$(echo ${OUTPUTRESOLUTION} | cut -d ' ' -f 2)" | |
AUDIORATE="$(echo ${OUTPUTRESOLUTION} | cut -d ' ' -f 3)" | |
# calculated fields | |
WIDTH="$(echo ${RESOLUTION} | grep -oE '^[[:digit:]]+')" | |
HEIGHT="$(echo ${RESOLUTION} | grep -oE '[[:digit:]]+$')" | |
if [ "$MAXHEIGHT" -ge "$HEIGHT" ]; then | |
CAN_START=1 | |
MAXRATE="$(echo "`echo ${BITRATE} | grep -oE '[[:digit:]]+'`*${MAX_BITRATE_RATIO}" | bc)" | |
BUFSIZE="$(echo "`echo ${BITRATE} | grep -oE '[[:digit:]]+'`*${RATE_MONITOR_BUFFER_RATIO}" | bc)" | |
BANDWIDTH="$(echo ${BITRATE} | grep -oE '[[:digit:]]+')000" | |
NAME="${HEIGHT}p" | |
CMD+=" ${STATIC_PARAMS} -vf scale=w=${WIDTH}:h=${HEIGHT}:force_original_aspect_ratio=decrease" | |
CMD+=" -b:v ${BITRATE} -maxrate ${MAXRATE%.*}k -bufsize ${BUFSIZE%.*}k -b:a ${AUDIORATE}" | |
CMD+=" -hls_segment_filename ${TARGET}/seg${NAME}_%03d.ts ${TARGET}/${NAME}.m3u8" | |
# add OUTPUTRESOLUTION entry in the master playlist | |
MASTER_PLAYLIST+="#EXT-X-STREAM-INF:BANDWIDTH=${BANDWIDTH},RESOLUTION=${RESOLUTION}\n${NAME}.m3u8\n" | |
fi | |
done | |
# can not start | |
if [ "$CAN_START" -eq 0 ]; then | |
echo "Error setting up file $SOURCEDIR/$MEDIAFILE max height is $MAXHEIGHT" | |
fi | |
# start conversion | |
if [ "$CAN_START" -eq 1 ]; then | |
echo -e "Executing command:\nffmpeg ${MISC_PARAMS} -i ${SOURCE} ${CMD}" | |
ffmpeg ${MISC_PARAMS} -i ${SOURCE} ${CMD} | |
# create master playlist file | |
echo -e "${MASTER_PLAYLIST}" > ${TARGET}/playlist.m3u8 | |
chown -R $WEBUSER:$WEBGROUP "$TARGETDIR/$NEWFILE"/* | |
echo "Done setting up file $SOURCEDIR/$MEDIAFILE" | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment