12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 |
- #!/usr/bin/env bash
- # https://gist.github.com/mrbar42/ae111731906f958b396f30906004b3fa
- set -e
- # Usage create-vod-hls.sh SOURCE_FILE [OUTPUT_NAME]
- [[ ! "${1}" ]] && echo "Usage: create-vod-hls.sh SOURCE_FILE [OUTPUT_NAME]" && exit 1
- FFMPEG=ffmpeg
- # comment/add lines here to control which renditions would be created
- renditions=(
- # resolution bitrate audio-rate
- # "426x240 400k 64k"
- "640x360 800k 96k"
- # "842x480 1400k 128k"
- # "1280x720 2800k 128k"
- # "1920x1080 5000k 192k"
- )
- segment_target_duration=2 # 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}"
- if [[ ! "${target}" ]]; then
- target="${source##*/}" # leave only last component of path
- target="${target%.*}" # strip extension
- fi
- mkdir -p ${target}
- 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 renditions
- static_params="-c:a aac -ar 48000 -c:v h264 -profile:v main -crf 20 -sc_threshold 0 -strict -2"
- static_params+=" -g ${key_frames_interval} -keyint_min ${key_frames_interval} -force_key_frames expr:gte(t,n_forced*2) -hls_time ${segment_target_duration}"
- # not working w current
- #static_params+=" -hls_playlist_type vod"
- static_params+=" -hls_list_size 0"
- # misc params
- misc_params="-hide_banner -y"
- master_playlist="#EXTM3U
- #EXT-X-VERSION:3
- "
- cmd=""
- 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)"
- # 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"
- 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}/${name}_%03d.ts ${target}/${name}.m3u8"
- # add rendition entry in the master playlist
- master_playlist+="#EXT-X-STREAM-INF:BANDWIDTH=${bandwidth},RESOLUTION=${resolution}\n${name}.m3u8\n"
- done
- # start conversion
- echo -e "Executing command:\n${FFMPEG} ${misc_params} -i ${source} ${cmd}"
- $FFMPEG ${misc_params} -i ${source} ${cmd}
- # create master playlist file
- echo -e "${master_playlist}" > ${target}/playlist.m3u8
- echo "Done - encoded HLS is at ${target}/"
|