Nvidia GPU use FFmpeg
Nvidia GPU create VOD HLS
origin: http://docs.peer5.com/guides/production-ready-hls-vod/
Nvidia GPU use FFmpeg
Nvidia GPU create VOD HLS
origin: http://docs.peer5.com/guides/production-ready-hls-vod/
| #!/usr/bin/env bash | |
| set -e | |
| # 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 64k" | |
| "640x360 800k 96k" | |
| "842x480 1400k 128k" | |
| "1280x720 2800k 128k" | |
| "1920x1080 5000k 192k" | |
| ) | |
| segment_target_duration=10 # 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="-map 0:v:${3} -map 0:a:${4} -c:a libfdk_aac -ar 48000 -c:v h264_nvenc -profile:v main -preset:v fast -rc constqp -qp 30 -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="-vsync 0 -hwaccel cuvid -hwaccel_device ${5} -hwaccel_output_format cuda -c:v h264_cuvid -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_npp=w=${width}:h=${height}:force_original_aspect_ratio=decrease:format=yuv420p " | |
| 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:\nffmpeg ${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}/" |