Files
ffmpeg-builder/lib/ffmpeg.sh

213 lines
5.1 KiB
Bash

#!/usr/bin/env bash
_ffprobe_wrapper() {
local stderr="${TMP_DIR}/ffprobe-stderr"
if ! ffprobe "$@" 2>"${TMP_DIR}/ffprobe-stderr"; then
cat "${stderr}"
return 1
fi
return 0
}
get_duration() {
local file="$1"
_ffprobe_wrapper \
-v error \
-show_entries format=duration \
-of default=noprint_wrappers=1:nokey=1 \
"${file}"
}
get_avg_bitrate() {
local file="$1"
_ffprobe_wrapper \
-v error \
-select_streams v:0 \
-show_entries format=bit_rate \
-of default=noprint_wrappers=1:nokey=1 \
"${file}"
}
split_video() {
local file="$1"
local start="$2"
local time="$3"
local out="$4"
ffmpeg \
-ss "${start}" \
-i "${file}" \
-hide_banner \
-loglevel error \
-t "${time}" \
-map 0:v \
-reset_timestamps 1 \
-c copy \
"${out}"
}
get_crop() {
local file="$1"
local duration
duration="$(get_duration "${file}")" || return 1
# don't care about decimal points
IFS='.' read -r duration _ <<<"${duration}"
# get crop value for first half of input
local timeEnc=$((duration / 20))
ffmpeg \
-y \
-hide_banner \
-ss 0 \
-discard 'nokey' \
-i "${file}" \
-t "${timeEnc}" \
-map '0:v:0' \
-filter:v:0 'cropdetect=limit=100:round=16:skip=2:reset_count=0' \
-codec:v 'wrapped_avframe' \
-f 'null' '/dev/null' 2>&1 |
grep -o 'crop=.*' |
sort -bh |
uniq -c |
sort -bh |
tail -n1 |
grep -o "crop=.*"
}
# output '1920x1080'
get_resolution() {
local file="$1"
get_stream_json "${file}" 0 |
jq -r '.streams[0] | "\(.width)x\(.height)"'
}
# same as get_resolution
get_sup_resolution() {
local supfile="$1"
check_for_supmover || return 1
if [[ "$(get_file_format "${supfile}")" != 'sup' ]]; then
echo_fail "${supfile} is not a sup file"
return 1
fi
local trace res
trace="$("${SUPMOVER}" "${supfile}" --trace)" || return 1
res="$(grep 'Video size' <<<"${trace}" | sort -u | awk '{print $NF}')" || return 1
echo "${res}"
}
get_stream_codec() {
local file="$1"
local stream="$2"
_ffprobe_wrapper \
-v error \
-select_streams "${stream}" \
-show_entries stream=codec_name \
-of default=noprint_wrappers=1:nokey=1 \
"${file}"
}
get_stream_json() {
local file="$1"
local stream="$2"
_ffprobe_wrapper \
-v error \
-select_streams "${stream}" \
-show_entries stream \
-of json \
"${file}"
}
get_file_format() {
local file="$1"
local probe
probe="$(_ffprobe_wrapper \
-v error \
-show_entries format=format_name \
-of default=noprint_wrappers=1:nokey=1 \
"${file}")" || return 1
if line_contains "${probe}" 'matroska'; then
echo mkv
elif line_contains "${probe}" 'mp4'; then
echo mp4
else
echo "${probe}"
fi
}
get_num_streams() {
local file="$1"
local type="${2:-}"
local select=()
if [[ ${type} != '' ]]; then
select=("-select_streams" "${type}")
fi
_ffprobe_wrapper \
-v error "${select[@]}" \
-show_entries stream=index \
-of default=noprint_wrappers=1:nokey=1 \
"${file}"
}
get_num_audio_channels() {
local file="$1"
local stream="$2"
_ffprobe_wrapper \
-v error \
-select_streams "${stream}" \
-show_entries stream=channels \
-of default=noprint_wrappers=1:nokey=1 \
"${file}"
}
get_stream_lang() {
local file="$1"
local stream="$2"
_ffprobe_wrapper \
-v error \
-select_streams "${stream}" \
-show_entries stream_tags=language \
-of default=noprint_wrappers=1:nokey=1 \
"${file}"
}
gen_video() {
local outFile="$1"
local addFlags=()
shift
local vf="format=yuv420p10le"
for arg in "$@"; do
case "${arg}" in
'1080p') resolution='1920x1080' ;;
'2160p') resolution='3840x2160' ;;
'grain=yes') vf+=",noise=alls=15:allf=t+u" ;;
'hdr=yes')
local colorPrimaries='bt2020'
local colorTrc='smpte2084'
local colorspace='bt2020nc'
vf+=",setparams=color_primaries=${colorPrimaries}:color_trc=${colorTrc}:colorspace=${colorspace}"
addFlags+=(
-color_primaries "${colorPrimaries}"
-color_trc "${colorTrc}"
-colorspace "${colorspace}"
-metadata:s:v:0 "mastering_display_metadata=G(13250,34500)B(7500,3000)R(34000,16000)WP(15635,16450)L(10000000,1)"
-metadata:s:v:0 "content_light_level=1000,400"
)
;;
*) echo_fail "bad arg ${arg}" && return 1 ;;
esac
done
echo_if_fail ffmpeg -y \
-hide_banner \
-f lavfi \
-i "testsrc2=size=${resolution}:rate=24:duration=5" \
-vf "${vf}" \
-c:v ffv1 \
-level 3 \
-g 1 \
-color_range tv \
"${addFlags[@]}" \
"${outFile}"
}