diff --git a/add-ownership.sh b/add-ownership.sh new file mode 100644 index 0000000..cfbb1e9 --- /dev/null +++ b/add-ownership.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +set -e + +source="${1}" +target="${2}" +_title="${3}" +_author="${4}" +_date="$(date +%F-%T)" +_copyright="Web-Micros; ${APPNAME}/${APPVERSION} - $(date +%Y)" +_watermark=${HLS_WATERMARK_SOURCE} + +sourceResolution="$(ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=s=x:p=0 ${source})" +arrIN=(${sourceResolution//x/ }) +sourceWidth="${arrIN[0]}" +sourceHeight="${arrIN[1]}" +watermarkWidth="$(echo "scale=3; ($sourceWidth / 1920) * 65" | bc)" +watermarkWidth=${watermarkWidth%.*} + +echo $watermarkWidth +if [ $((watermarkWidth % 2)) -ne 0 ];then + echo "width is odd." + watermarkWidth=$((watermarkWidth - 1)) +fi +echo $watermarkWidth + +# Add Metadata and Watermark to the video source +ffmpeg -hide_banner -y -i ${source} -i ${_watermark} -metadata title="${_title}" -metadata author="${_author}" -metadata date="${_date}" -metadata copyright="${_copyright}" -filter_complex "[1:v]scale=${watermarkWidth}:-1[wm];[0:v][wm]overlay=15:15" -crf ${HLS_CRF} ${target} \ No newline at end of file diff --git a/create-vod-hls.sh b/create-vod-hls.sh new file mode 100644 index 0000000..1a39b60 --- /dev/null +++ b/create-vod-hls.sh @@ -0,0 +1,154 @@ +#!/usr/bin/env bash +START_TIME=$SECONDS +set -e + +echo "-----START GENERATING HLS STREAM-----" +# Usage create-vod-hls.sh SOURCE_FILE [OUTPUT_NAME] +[[ ! "${1}" ]] && echo "Usage: create-vod-hls.sh SOURCE_FILE [OUTPUT_NAME]" && exit 1 + +# comment/add lines here to control which renditions would be created +renditions=( +# resolution bitrate audio-rate + "426x240 400k 128k" + "640x360 800k 192k" + "842x480 1400k 256k" + "1280x720 2800k 256k" + "1920x1080 5000k 320k" +) +# "2560x1440 5000k 320k" +# "3840x2160 5000k 320k" + +segment_target_duration=${HLS_SEGMENT_TARGET_DURATION} # try to create a new segment every X seconds +max_bitrate_ratio=1.07 # maximum accepted bitrate fluctuations +rate_monitor_buffer_ratio=1.5 # maximum buffer size between bitrate conformance checks + +######################################################################### + +source="${1}" +target="${2}" +_title="${3}" +_author="${4}" +_date="$(date +%F-%T)" +_copyright="Web-Micros; ${APPNAME}/${APPVERSION} - $(date +%Y)" + + +if [[ ! "${target}" ]]; then + target="${source##*/}" # leave only last component of path + target="${target%.*}" # strip extension +fi +mkdir -p ${target} + +# ----CUSTOM---- +sourceResolution="$(ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=s=x:p=0 ${source})" +# echo ${sourceResolution} +arrIN=(${sourceResolution//x/ }) +sourceWidth="${arrIN[0]}" +sourceHeight="${arrIN[1]}" + +echo ${sourceWidth} +echo ${sourceHeight} + +sourceAudioBitRate="$(ffprobe -v error -select_streams a:0 -show_entries stream=bit_rate -of csv=s=x:p=0 ${source})" +sourceAudioBitRateFormatted=$((sourceAudioBitRate / 1000)) +# ----END CUSTOM---- + +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 + +# Specify whether to create MPEG-TS or FMP4 segments +segmentType=${HLS_SEGMENT_TYPE} +hlsSegmentType="mpegts" +hlsSegmentExtension="ts" + +if [ $segmentType == 'FMP4' ]; then + hlsSegmentType="fmp4" + hlsSegmentExtension='m4s' +fi + +# static parameters that are similar for all renditions +static_params="-c:a aac -ar 48000 -c:v h264 -profile:v main -crf ${HLS_CRF} -sc_threshold 0" +static_params+=" -g ${key_frames_interval} -keyint_min ${key_frames_interval}" +static_params+=" -hls_time ${segment_target_duration} -hls_playlist_type vod -hls_segment_type ${hlsSegmentType}" + +# misc params +misc_params="-hide_banner -y" + +master_playlist="#EXTM3U +#EXT-X-VERSION:3 +" +cmd="" +resolutionValid=0 +prevHeight=0 +for rendition in "${renditions[@]}"; do + # drop extraneous spaces + rendition="${rendition/[[:space:]]+/ }" + + # rendition fields + resolution="$(echo ${rendition} | cut -d ' ' -f 1)" + bitrate="$(echo ${rendition} | cut -d ' ' -f 2)" + audiorate="$(echo ${rendition} | cut -d ' ' -f 3)" + + audioBitRateFormatted=${audiorate%?} # remove "k" at the last index + + # take highest possible audio bit rate + if [ $audioBitRateFormatted -gt $sourceAudioBitRateFormatted ]; then + audiorate=${sourceAudioBitRateFormatted}k + fi + + # calculated fields + width="$(echo ${resolution} | grep -oE '^[[:digit:]]+')" + height="$(echo ${resolution} | grep -oE '[[:digit:]]+$')" + 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" + + # ENABLE THIS IN PRODUCTION + # require video source has to have height greater or equal than the target height + # middle=$(( (prevHeight + height) / 2 )) + # echo "${middle}----MIDDLE" + if [ $sourceHeight -le $prevHeight ]; then + echo "video source has height smaller than output height (${height})" + break + fi + + widthParam=0 + heightParam=0 + + if [ $(((width / sourceWidth) * sourceHeight)) -gt $height ]; then + widthParam=-2 + heightParam=$height + else + widthParam=$width + heightParam=-2 + fi + + cmd+=" ${static_params} -vf scale=w=${widthParam}:h=${heightParam}" + cmd+=" -b:v ${bitrate} -maxrate ${maxrate%.*}k -bufsize ${bufsize%.*}k -b:a ${audiorate}" + cmd+=" -hls_segment_filename ${target}/${name}_%03d.${hlsSegmentExtension} ${target}/${name}.m3u8" + + # add rendition entry in the master playlist + master_playlist+="#EXT-X-STREAM-INF:BANDWIDTH=${bandwidth},RESOLUTION=${resolution}\n${name}.m3u8\n" + + resolutionValid=1 + prevHeight=${height} +done + +if [ $resolutionValid -eq 1 ]; then + # start conversion + echo -e "Executing command:\nffmpeg ${misc_params} -i ${source} ${cmd}\n" + ffmpeg ${misc_params} -i ${source} -metadata title="${_title}" -metadata author="${_author}" -metadata date="${_date}" -metadata copyright="${_copyright}" ${cmd} + # create master playlist file + echo -e "${master_playlist}" > ${target}/index.m3u8 + echo "Done - encoded HLS is at ${target}/" +else + echo "Video source is too small" + exit 1 +fi + +ELAPSED_TIME=$(($SECONDS - $START_TIME)) + +echo "Elapsed time: ${ELAPSED_TIME}" +echo "-----FINISH GENERATING HLS STREAM-----" \ No newline at end of file diff --git a/extract-assets.sh b/extract-assets.sh new file mode 100644 index 0000000..7a3c988 --- /dev/null +++ b/extract-assets.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +START_TIME=$SECONDS +set -e + +echo "-----START EXTRACTING ASSETS-----" +# Usage extract-assets.sh SOURCE_FILE [OUTPUT_NAME] +[[ ! "${1}" ]] && echo "Usage: extract-assets.sh SOURCE_FILE [OUTPUT_NAME]" && exit 1 + +source="${1}" +target="${2}" +_title="${3}" +_author="${4}" +_date="$(date +%F-%T)" +_copyright="Web-Micros; ${APPNAME}/${APPVERSION} - $(date +%Y)" + +sourceDuration="$(ffprobe -v error -select_streams v:0 -show_entries stream=duration -of csv=s=x:p=0 ${source})" +toInt=${sourceDuration%.*} +echo -e "Duration: ${toInt}" + +# Number of thumbnail to extract +tbVars="[screen0]" + +# timemark as each thumbnail extraction +timemarkUnit=$((${toInt} / 6)) +timemark=0 + +# concat extraction command +vFrameCmd="-vframes 1 -map ${tbVars} ${target}/poster-1.jpg" + +for i in {1..5}; do + timemark=$((${timemark} + ${timemarkUnit})) + tbVars+="[screen$i]" + vFrameCmd+=" -vframes 1 -map [screen$i] -ss ${timemark} ${target}/poster-$(($i + 1)).jpg" +done + +# Misc params +misc_params="-filter_complex scale=w=640:h=360[size0];[size0]split=6${tbVars}" + +# Create output directory (target) if not exists +mkdir -p ${target} +# Start extraction +echo -e "Executing command:\nffmpeg -i ${source} ${misc_params} ${metadata_params} -aq 5 -vn ${target}/audio.ogg -crf ${HLS_CRF} ${vFrameCmd}\n" +ffmpeg -hide_banner -y -i ${source} ${misc_params} -metadata title="${_title}" -metadata author="${_author}" -metadata date="${_date}" -metadata copyright="${_copyright}" -aq 5 -vn ${target}/audio.ogg -crf ${HLS_CRF} ${vFrameCmd} + +ELAPSED_TIME=$(($SECONDS - $START_TIME)) + +echo "Elapsed time: ${ELAPSED_TIME}" +echo "-----FINISH EXTRACTING ASSETS-----" \ No newline at end of file