mirror of
https://github.com/levogevo/ffmpeg-builder.git
synced 2026-03-16 19:20:11 +00:00
692 lines
20 KiB
Bash
692 lines
20 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
DESIRED_SUB_LANG=eng
|
|
|
|
# sets UNMAP_STREAMS
|
|
set_unmap_streams() {
|
|
local file="$1"
|
|
local unmapFilter='bin_data|jpeg|png'
|
|
local streamsStr
|
|
UNMAP_STREAMS=()
|
|
streamsStr="$(get_num_streams "${file}")" || return 1
|
|
mapfile -t streams <<<"${streamsStr}" || return 1
|
|
for stream in "${streams[@]}"; do
|
|
if [[ "$(get_stream_codec "${file}" "${stream}")" =~ ${unmapFilter} ]]; then
|
|
UNMAP_STREAMS+=("-map" "-0:${stream}")
|
|
fi
|
|
done
|
|
}
|
|
|
|
# sets AUDIO_PARAMS
|
|
set_audio_params() {
|
|
local file="$1"
|
|
local videoLang
|
|
AUDIO_PARAMS=()
|
|
videoLang="$(get_stream_lang "${file}" 'v:0')" || return 1
|
|
for stream in $(get_num_streams "${file}" 'a'); do
|
|
local numChannels codec lang
|
|
numChannels="$(get_num_audio_channels "${file}" "${stream}")" || return 1
|
|
if [[ ${numChannels} == '' ]]; then
|
|
echo_fail "could not obtain channel count for stream ${stream}"
|
|
return 1
|
|
fi
|
|
local channelBitrate=$((numChannels * 64))
|
|
codec="$(get_stream_codec "${file}" "${stream}")" || return 1
|
|
lang="$(get_stream_lang "${file}" "${stream}")" || return 1
|
|
if [[ ${videoLang} != '' && ${videoLang} != "${lang}" ]]; then
|
|
AUDIO_PARAMS+=(
|
|
'-map'
|
|
"-0:${stream}"
|
|
)
|
|
elif [[ ${codec} == 'opus' ]]; then
|
|
AUDIO_PARAMS+=(
|
|
"-c:${OUTPUT_INDEX}"
|
|
"copy"
|
|
)
|
|
OUTPUT_INDEX=$((OUTPUT_INDEX + 1))
|
|
else
|
|
AUDIO_PARAMS+=(
|
|
"-filter:${OUTPUT_INDEX}"
|
|
"aformat=channel_layouts=7.1|5.1|stereo|mono"
|
|
"-c:${OUTPUT_INDEX}"
|
|
"libopus"
|
|
"-b:${OUTPUT_INDEX}"
|
|
"${channelBitrate}k"
|
|
)
|
|
OUTPUT_INDEX=$((OUTPUT_INDEX + 1))
|
|
fi
|
|
done
|
|
}
|
|
|
|
# sets SUBTITLE_PARAMS
|
|
set_subtitle_params() {
|
|
local file="$1"
|
|
local convertCodec='eia_608'
|
|
|
|
local defaultTextCodec
|
|
if [[ ${SAME_CONTAINER} == false && ${FILE_EXT} == 'mkv' ]]; then
|
|
defaultTextCodec='srt'
|
|
convertCodec+='|mov_text'
|
|
else
|
|
defaultTextCodec='mov_text'
|
|
convertCodec+='|srt'
|
|
fi
|
|
|
|
SUBTITLE_PARAMS=()
|
|
for stream in $(get_num_streams "${file}" 's'); do
|
|
local codec lang
|
|
codec="$(get_stream_codec "${file}" "${stream}")" || return 1
|
|
lang="$(get_stream_lang "${file}" "${stream}")" || return 1
|
|
if [[ ${lang} != '' && ${DESIRED_SUB_LANG} != "${lang}" ]]; then
|
|
SUBTITLE_PARAMS+=(
|
|
'-map'
|
|
"-0:${stream}"
|
|
)
|
|
elif [[ ${codec} =~ ${convertCodec} ]]; then
|
|
SUBTITLE_PARAMS+=("-c:${OUTPUT_INDEX}" "${defaultTextCodec}")
|
|
OUTPUT_INDEX=$((OUTPUT_INDEX + 1))
|
|
elif [[ ${codec} == 'hdmv_pgs_subtitle' ]]; then
|
|
PGS_SUB_STREAMS+=("${stream}")
|
|
SUBTITLE_PARAMS+=(
|
|
'-map'
|
|
"-0:${stream}"
|
|
)
|
|
else
|
|
# map -0 covers the stream but still want to increment the index
|
|
OUTPUT_INDEX=$((OUTPUT_INDEX + 1))
|
|
fi
|
|
done
|
|
}
|
|
|
|
get_encode_versions() {
|
|
action="${1:-}"
|
|
|
|
ENCODE_VERSION="encode=$(git -C "${REPO_DIR}" rev-parse --short HEAD)"
|
|
FFMPEG_VERSION=''
|
|
VIDEO_ENC_VERSION=''
|
|
AUDIO_ENC_VERSION=''
|
|
|
|
# shellcheck disable=SC2155
|
|
local output="$(ffmpeg -version 2>&1)"
|
|
while read -r line; do
|
|
if line_starts_with "${line}" 'ffmpeg='; then
|
|
FFMPEG_VERSION="${line}"
|
|
elif line_starts_with "${line}" 'libsvtav1'; then
|
|
VIDEO_ENC_VERSION="${line}"
|
|
elif line_starts_with "${line}" 'libopus='; then
|
|
AUDIO_ENC_VERSION="${line}"
|
|
fi
|
|
done <<<"${output}"
|
|
|
|
local version
|
|
if [[ ${FFMPEG_VERSION} == '' ]]; then
|
|
while read -r line; do
|
|
if line_starts_with "${line}" 'ffmpeg version '; then
|
|
read -r _ _ version _ <<<"${line}"
|
|
FFMPEG_VERSION="ffmpeg=${version}"
|
|
break
|
|
fi
|
|
done <<<"${output}"
|
|
fi
|
|
|
|
if [[ ${VIDEO_ENC_VERSION} == '' ]]; then
|
|
version="$(get_pkgconfig_version SvtAv1Enc)"
|
|
test "${version}" == '' && return 1
|
|
VIDEO_ENC_VERSION="libsvtav1=${version}"
|
|
fi
|
|
|
|
if [[ ${AUDIO_ENC_VERSION} == '' ]]; then
|
|
version="$(get_pkgconfig_version opus)"
|
|
test "${version}" == '' && return 1
|
|
AUDIO_ENC_VERSION="libopus=${version}"
|
|
fi
|
|
|
|
test "${FFMPEG_VERSION}" == '' && return 1
|
|
test "${VIDEO_ENC_VERSION}" == '' && return 1
|
|
test "${AUDIO_ENC_VERSION}" == '' && return 1
|
|
|
|
if [[ ${action} == 'print' ]]; then
|
|
echo "${ENCODE_VERSION}"
|
|
echo "${FFMPEG_VERSION}"
|
|
echo "${VIDEO_ENC_VERSION}"
|
|
echo "${AUDIO_ENC_VERSION}"
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
# given an input mkv/sup file,
|
|
# output a new mkv file with
|
|
# input metadata preserved
|
|
replace_mkv_sup() {
|
|
local mkvIn="$1"
|
|
local supIn="$2"
|
|
local mkvOut="$3"
|
|
local stream="${4:-0}"
|
|
|
|
local json
|
|
json="$(get_stream_json "${mkvIn}" "${stream}")" || return 1
|
|
|
|
# x:y
|
|
# x = stream json variable name
|
|
# y = mkvmerge option name
|
|
local optionMap=(
|
|
disposition.default:--default-track-flag
|
|
disposition.original:--original-flag
|
|
disposition.comment:--commentary-flag
|
|
disposition.forced:--forced-display-flag
|
|
disposition.hearing_impaired:--hearing-impaired-flag
|
|
tags.language:--language
|
|
tags.title:--track-name
|
|
)
|
|
|
|
# start building mkvmerge command
|
|
local mergeCmd=(
|
|
mkvmerge
|
|
-o "${mkvOut}"
|
|
)
|
|
for line in "${optionMap[@]}"; do
|
|
IFS=: read -r key option <<<"${line}"
|
|
local val
|
|
val="$(jq -r ".streams[].${key}" <<<"${json}")" || return 1
|
|
# skip undefined values
|
|
test "${val}" == null && continue
|
|
# always track 0 for single track
|
|
mergeCmd+=("${option}" "0:${val}")
|
|
done
|
|
mergeCmd+=("${supIn}")
|
|
|
|
"${mergeCmd[@]}"
|
|
}
|
|
|
|
# extract PGS_SUB_STREAMS from INPUT
|
|
# and crop using CROP_VALUE
|
|
setup_pgs_mkv() {
|
|
local pgsMkvOut="$1"
|
|
|
|
if [[ ${#PGS_SUB_STREAMS[@]} -eq 0 ]]; then
|
|
return
|
|
fi
|
|
|
|
check_for_supmover || return 1
|
|
|
|
# setup tempdir
|
|
local ogSup cropSup cropMkv tmpdir
|
|
tmpdir="${pgsMkvOut}-dir"
|
|
recreate_dir "${tmpdir}" || return 1
|
|
|
|
# get video resolution
|
|
local vidRes vidWidth vidHeight
|
|
vidRes="$(get_resolution "${INPUT}")"
|
|
IFS=x read -r vidWidth vidHeight <<<"${vidRes}"
|
|
|
|
for stream in "${PGS_SUB_STREAMS[@]}"; do
|
|
# extract sup from input
|
|
ogSup="${tmpdir}/${stream}.sup"
|
|
cropSup="${tmpdir}/${stream}-cropped.sup"
|
|
cropMkv="${tmpdir}/${stream}.mkv"
|
|
mkvextract "${INPUT}" tracks "${stream}:${ogSup}" || return 1
|
|
|
|
# check if PGS was uncropped
|
|
local supRes
|
|
supRes="$(get_sup_resolution "${ogSup}")" || return 1
|
|
# crop PGS if either initially cropping or "fixing"
|
|
# previously uncropped (relative to video) PGS subs
|
|
if [[ ${CROP_VALUE} != '' || ${supRes} != "${vidRes}" ]]; then
|
|
local supWidth supHeight
|
|
IFS=x read -r supWidth supHeight <<<"${supRes}"
|
|
local left top right bottom
|
|
|
|
# determine crop values
|
|
# if the supfile is smaller than the video stream
|
|
# crop using aspect ratio
|
|
if [[ ${vidWidth} -gt ${supWidth} || ${vidHeight} -gt ${supHeight} ]]; then
|
|
echo_warn "PGS sup (stream=${stream}) is somehow smaller than initial video stream"
|
|
echo_warn "cropping based off of aspect ratio instead of resolution"
|
|
left=0
|
|
# (supHeight - ((vidHeight/vidWidth) * supWidth)) / 2
|
|
top="$(awk '{ print int(($1 - ($2 / $3 * $4)) / 2) }' <<<"${supHeight} ${vidHeight} ${vidWidth} ${supWidth}")"
|
|
right=${left}
|
|
bottom=${top}
|
|
# otherwise crop using the crop value
|
|
elif [[ ${CROP_VALUE} != '' ]]; then
|
|
# determine supmover crop based off of crop
|
|
local res w h x y
|
|
# extract ffmpeg crop value ("crop=w:h:x:y")
|
|
IFS='=' read -r _ res <<<"${CROP_VALUE}"
|
|
IFS=':' read -r w h x y <<<"${res}"
|
|
|
|
# ffmpeg crop value
|
|
# is different than supmover crop inputs
|
|
left=${x}
|
|
top=${y}
|
|
right=$((supWidth - w - left))
|
|
bottom=$((supHeight - h - top))
|
|
# fallback to just the video resolution
|
|
else
|
|
left=$(((supWidth - vidWidth) / 2))
|
|
top=$(((supHeight - vidHeight) / 2))
|
|
right=${left}
|
|
bottom=${top}
|
|
fi
|
|
|
|
# only crop if actually required
|
|
if [[ "${left}${top}${right}${bottom}" != "0000" ]]; then
|
|
# crop sup
|
|
(
|
|
set -x
|
|
"${SUPMOVER}" \
|
|
"${ogSup}" \
|
|
"${cropSup}" \
|
|
--crop \
|
|
"${left}" "${top}" "${right}" "${bottom}" &>"${cropSup}.out" || return 1
|
|
)
|
|
local cropRet=$?
|
|
# supmover does not error for out-of-bounds subtitles
|
|
# so error only when there is most certainly an issue
|
|
if [[ "$(grep -c 'Window is outside new screen area' "${cropSup}.out")" -gt 5 ]]; then
|
|
echo_fail "check ${cropSup}.out for complete logs"
|
|
cropRet=1
|
|
fi
|
|
if [[ ${cropRet} -ne 0 ]]; then
|
|
rm -r "${tmpdir}" || return 1
|
|
return 1
|
|
fi
|
|
else
|
|
# create placeholder copy for replacement
|
|
cp "${ogSup}" "${cropSup}" || return 1
|
|
fi
|
|
else
|
|
# create placeholder copy for replacement
|
|
cp "${ogSup}" "${cropSup}" || return 1
|
|
fi
|
|
|
|
if ! replace_mkv_sup "${INPUT}" "${cropSup}" "${cropMkv}" "${stream}"; then
|
|
echo_fail "could not replace mkv sup for ${stream}"
|
|
rm -r "${tmpdir}" || return 1
|
|
fi
|
|
done
|
|
|
|
# merge all single mkv into one
|
|
mkvmerge -o "${pgsMkvOut}" "${tmpdir}/"*.mkv
|
|
local mergeRet=$?
|
|
rm -r "${tmpdir}" || return 1
|
|
return ${mergeRet}
|
|
}
|
|
|
|
encode_usage() {
|
|
echo "encode -i input [options] output"
|
|
echo -e "\t[-P NUM] set preset (default: ${PRESET})"
|
|
echo -e "\t[-C NUM] set CRF (default: ${CRF})"
|
|
echo -e "\t[-g NUM] set film grain for encode"
|
|
echo -e "\t[-p] print the command instead of executing it (default: ${PRINT_OUT})"
|
|
echo -e "\t[-c] use cropdetect (default: ${CROP})"
|
|
echo -e "\t[-d] enable dolby vision (default: ${DV_TOGGLE})"
|
|
echo -e "\t[-v] print relevant version info"
|
|
echo -e "\t[-s] use same container as input, default is convert to mkv"
|
|
echo -e "\n\t[output] if unset, defaults to \${PWD}/av1-input-file-name.mkv"
|
|
echo -e "\n\t[-u] update script (git pull ffmpeg-builder)"
|
|
echo -e "\t[-I] system install at ${ENCODE_INSTALL_PATH}"
|
|
echo -e "\t[-U] uninstall from ${ENCODE_INSTALL_PATH}"
|
|
return 0
|
|
}
|
|
|
|
encode_update() {
|
|
git -C "${REPO_DIR}" pull
|
|
}
|
|
|
|
set_encode_opts() {
|
|
local opts='vi:pcsdg:P:C:uIU'
|
|
local numOpts=${#opts}
|
|
# default values
|
|
PRESET=3
|
|
CRF=25
|
|
GRAIN=""
|
|
CROP=false
|
|
PRINT_OUT=false
|
|
DV_TOGGLE=false
|
|
ENCODE_INSTALL_PATH='/usr/local/bin/encode'
|
|
SAME_CONTAINER="false"
|
|
# only using -I/U
|
|
local minOpt=1
|
|
# using all + output name
|
|
local maxOpt=$((numOpts + 1))
|
|
test $# -lt ${minOpt} && encode_usage && return 1
|
|
test $# -gt ${maxOpt} && encode_usage && return 1
|
|
local optsUsed=0
|
|
local OPTARG OPTIND
|
|
while getopts "${opts}" flag; do
|
|
case "${flag}" in
|
|
u)
|
|
encode_update || return 1
|
|
return ${FUNC_EXIT_SUCCESS}
|
|
;;
|
|
I)
|
|
echo_warn "attempting install"
|
|
sudo ln -sf "${SCRIPT_DIR}/encode.sh" \
|
|
"${ENCODE_INSTALL_PATH}" || return 1
|
|
echo_pass "succesfull install"
|
|
return ${FUNC_EXIT_SUCCESS}
|
|
;;
|
|
U)
|
|
echo_warn "attempting uninstall"
|
|
sudo rm "${ENCODE_INSTALL_PATH}" || return 1
|
|
echo_pass "succesfull uninstall"
|
|
return ${FUNC_EXIT_SUCCESS}
|
|
;;
|
|
v)
|
|
get_encode_versions print || return 1
|
|
return ${FUNC_EXIT_SUCCESS}
|
|
;;
|
|
i)
|
|
if [[ $# -lt 2 ]]; then
|
|
echo_fail "wrong arguments given"
|
|
encode_usage
|
|
return 1
|
|
fi
|
|
INPUT="${OPTARG}"
|
|
optsUsed=$((optsUsed + 2))
|
|
;;
|
|
p)
|
|
PRINT_OUT=true
|
|
optsUsed=$((optsUsed + 1))
|
|
;;
|
|
c)
|
|
CROP=true
|
|
optsUsed=$((optsUsed + 1))
|
|
;;
|
|
d)
|
|
DV_TOGGLE=true
|
|
optsUsed=$((optsUsed + 1))
|
|
;;
|
|
s)
|
|
SAME_CONTAINER=true
|
|
optsUsed=$((optsUsed + 1))
|
|
;;
|
|
g)
|
|
if ! is_positive_integer "${OPTARG}"; then
|
|
encode_usage
|
|
return 1
|
|
fi
|
|
GRAIN="film-grain=${OPTARG}:film-grain-denoise=1:"
|
|
optsUsed=$((optsUsed + 2))
|
|
;;
|
|
P)
|
|
if ! is_positive_integer "${OPTARG}"; then
|
|
encode_usage
|
|
return 1
|
|
fi
|
|
PRESET="${OPTARG}"
|
|
optsUsed=$((optsUsed + 2))
|
|
;;
|
|
C)
|
|
if ! is_positive_integer "${OPTARG}" || test ${OPTARG} -gt 63; then
|
|
echo_fail "${OPTARG} is not a valid CRF value (0-63)"
|
|
encode_usage
|
|
return 1
|
|
fi
|
|
CRF="${OPTARG}"
|
|
OPTS_USED=$((OPTS_USED + 2))
|
|
;;
|
|
*)
|
|
echo_fail "wrong flags given"
|
|
encode_usage
|
|
return 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# allow optional output filename
|
|
if [[ $(($# - optsUsed)) == 1 ]]; then
|
|
OUTPUT="${*: -1}"
|
|
else
|
|
local basename="$(bash_basename "${INPUT}")"
|
|
OUTPUT="${PWD}/av1-${basename}"
|
|
fi
|
|
|
|
# use same container for output
|
|
if [[ $SAME_CONTAINER == "true" ]]; then
|
|
local fileFormat
|
|
fileFormat="$(get_file_format "${INPUT}")" || return 1
|
|
FILE_EXT=''
|
|
if [[ ${fileFormat} == 'MPEG-4' ]]; then
|
|
FILE_EXT='mp4'
|
|
elif [[ ${fileFormat} == 'Matroska' ]]; then
|
|
FILE_EXT='mkv'
|
|
else
|
|
echo "unrecognized input format"
|
|
return 1
|
|
fi
|
|
else
|
|
FILE_EXT="mkv"
|
|
fi
|
|
OUTPUT="${OUTPUT%.*}"
|
|
OUTPUT+=".${FILE_EXT}"
|
|
|
|
if [[ ! -f ${INPUT} ]]; then
|
|
echo "${INPUT} does not exist"
|
|
encode_usage
|
|
return 1
|
|
fi
|
|
|
|
if [[ ${PRINT_OUT} == false ]]; then
|
|
echo
|
|
echo_info "INPUT: ${INPUT}"
|
|
echo_info "GRAIN: ${GRAIN}"
|
|
echo_info "OUTPUT: ${OUTPUT}"
|
|
echo
|
|
fi
|
|
}
|
|
|
|
# shellcheck disable=SC2034
|
|
# shellcheck disable=SC2155
|
|
# shellcheck disable=SC2016
|
|
gen_encode_script() {
|
|
if missing_cmd mkvpropedit; then
|
|
echo_fail "use: ${REPO_DIR}/scripts/install_deps.sh"
|
|
return 1
|
|
fi
|
|
|
|
local outputBasename="$(bash_basename "${OUTPUT}")"
|
|
local genScript="${TMP_DIR}/${outputBasename}.sh"
|
|
|
|
# global output index number to increment
|
|
OUTPUT_INDEX=0
|
|
|
|
# single string params
|
|
local params=(
|
|
INPUT
|
|
OUTPUT
|
|
PRESET
|
|
CRF
|
|
CROP_VALUE
|
|
ENCODE_VERSION
|
|
FFMPEG_VERSION
|
|
VIDEO_ENC_VERSION
|
|
AUDIO_ENC_VERSION
|
|
svtAv1Params
|
|
pgsMkv
|
|
muxxedPgsMkv
|
|
)
|
|
|
|
svtAv1ParamsArr=(
|
|
"tune=0"
|
|
"complex-hvs=1"
|
|
"spy-rd=1"
|
|
"psy-rd=1"
|
|
"sharpness=3"
|
|
"enable-overlays=0"
|
|
"hbd-mds=1"
|
|
"scd=1"
|
|
"fast-decode=1"
|
|
"enable-variance-boost=1"
|
|
"enable-qm=1"
|
|
"chroma-qm-min=10"
|
|
"qm-min=4"
|
|
"qm-max=15"
|
|
)
|
|
IFS=':'
|
|
local svtAv1Params="${GRAIN}${svtAv1ParamsArr[*]}"
|
|
unset IFS
|
|
|
|
# arrays
|
|
local arrays=(
|
|
UNMAP_STREAMS
|
|
AUDIO_PARAMS
|
|
SUBTITLE_PARAMS
|
|
videoParams
|
|
metadata
|
|
ffmpegParams
|
|
PGS_SUB_STREAMS
|
|
)
|
|
local "${arrays[@]}"
|
|
|
|
local videoParams=(
|
|
"-crf" '${CRF}' "-preset" '${PRESET}' "-g" "240"
|
|
)
|
|
local ffmpegParams=(
|
|
'-hide_banner'
|
|
'-i' '${INPUT}'
|
|
'-y'
|
|
'-map' '0'
|
|
'-c:s' 'copy'
|
|
)
|
|
|
|
# set video params
|
|
get_encode_versions || return 1
|
|
local inputVideoCodec="$(get_stream_codec "${INPUT}" 'v:0')"
|
|
if [[ ${inputVideoCodec} == 'av1' ]]; then
|
|
ffmpegParams+=(
|
|
"-c:v:${OUTPUT_INDEX}" 'copy'
|
|
)
|
|
# can't crop if copying codec
|
|
CROP=false
|
|
else
|
|
ffmpegParams+=(
|
|
'-pix_fmt' 'yuv420p10le'
|
|
"-c:v:${OUTPUT_INDEX}" 'libsvtav1' '${videoParams[@]}'
|
|
'-svtav1-params' '${svtAv1Params}'
|
|
)
|
|
metadata+=(
|
|
'-metadata' '${VIDEO_ENC_VERSION}'
|
|
'-metadata' 'svtav1_params=${svtAv1Params}'
|
|
'-metadata' 'video_params=${videoParams[*]}'
|
|
)
|
|
fi
|
|
OUTPUT_INDEX=$((OUTPUT_INDEX + 1))
|
|
|
|
# these values may be empty
|
|
set_unmap_streams "${INPUT}" || return 1
|
|
set_audio_params "${INPUT}" || return 1
|
|
set_subtitle_params "${INPUT}" || return 1
|
|
|
|
if [[ ${UNMAP_STREAMS[*]} != '' ]]; then
|
|
ffmpegParams+=('${UNMAP_STREAMS[@]}')
|
|
fi
|
|
|
|
if [[ ${AUDIO_PARAMS[*]} != '' ]]; then
|
|
ffmpegParams+=('${AUDIO_PARAMS[@]}')
|
|
fi
|
|
|
|
if [[ ${SUBTITLE_PARAMS[*]} != '' ]]; then
|
|
ffmpegParams+=('${SUBTITLE_PARAMS[@]}')
|
|
fi
|
|
|
|
metadata+=(
|
|
'-metadata' '${ENCODE_VERSION}'
|
|
'-metadata' '${FFMPEG_VERSION}'
|
|
)
|
|
|
|
# in the case all audio streams are copied,
|
|
# don't add libopus metadata
|
|
if line_contains "${AUDIO_PARAMS[*]}" 'libopus'; then
|
|
metadata+=(
|
|
'-metadata' '${AUDIO_ENC_VERSION}')
|
|
fi
|
|
|
|
local CROP_VALUE
|
|
if [[ ${CROP} == true ]]; then
|
|
CROP_VALUE="$(get_crop "${INPUT}")" || return 1
|
|
ffmpegParams+=('-vf' '${CROP_VALUE}')
|
|
metadata+=(
|
|
'-metadata' '${CROP_VALUE}'
|
|
'-metadata' "og_res=$(get_resolution "${INPUT}")"
|
|
)
|
|
fi
|
|
|
|
# separate processing step for pkg subs
|
|
local pgsMkv="${TMP_DIR}/pgs-${outputBasename// /.}.mkv"
|
|
local muxxedPgsMkv='${OUTPUT}.muxxed'
|
|
setup_pgs_mkv "${pgsMkv}" 1>&2 || return 1
|
|
|
|
ffmpegParams+=('${metadata[@]}')
|
|
|
|
{
|
|
echo '#!/usr/bin/env bash'
|
|
echo
|
|
|
|
# add normal params
|
|
for param in "${params[@]}"; do
|
|
declare -n value="${param}"
|
|
if [[ ${value} != '' ]]; then
|
|
echo "${param}=\"${value[*]}\""
|
|
fi
|
|
done
|
|
for arrName in "${arrays[@]}"; do
|
|
declare -n arr="${arrName}"
|
|
if [[ -v arr ]]; then
|
|
echo "${arrName}=("
|
|
printf '\t"%s"\n' "${arr[@]}"
|
|
echo ')'
|
|
fi
|
|
done
|
|
|
|
# actually do ffmpeg commmand
|
|
echo
|
|
if [[ ${DV_TOGGLE} == true ]]; then
|
|
echo 'ffmpeg "${ffmpegParams[@]}" -dolbyvision 1 "${OUTPUT}" || \'
|
|
fi
|
|
echo 'ffmpeg "${ffmpegParams[@]}" -dolbyvision 0 "${OUTPUT}" || exit 1'
|
|
|
|
# track-stats and clear title
|
|
if [[ ${FILE_EXT} == 'mkv' ]]; then
|
|
{
|
|
# ffmpeg does not copy PGS subtitles without breaking them
|
|
# use mkvmerge to extract and supmover to crop
|
|
if [[ ${#PGS_SUB_STREAMS[@]} -gt 0 ]]; then
|
|
echo
|
|
echo 'mkvmerge -o "${muxxedPgsMkv}" "${pgsMkv}" "${OUTPUT}" || exit 1'
|
|
echo 'rm "${pgsMkv}" || exit 1'
|
|
echo 'mv "${muxxedPgsMkv}" "${OUTPUT}" || exit 1'
|
|
fi
|
|
|
|
echo 'mkvpropedit "${OUTPUT}" --add-track-statistics-tags || exit 1'
|
|
echo 'mkvpropedit "${OUTPUT}" --edit info --set "title=" || exit 1'
|
|
}
|
|
fi
|
|
|
|
echo
|
|
} >"${genScript}"
|
|
|
|
if [[ ${PRINT_OUT} == true ]]; then
|
|
echo_info "${genScript} contents:" 1>&2
|
|
echo "$(<"${genScript}")"
|
|
else
|
|
bash -x "${genScript}" || return 1
|
|
rm "${genScript}"
|
|
fi
|
|
}
|
|
|
|
FB_FUNC_NAMES+=('encode')
|
|
# shellcheck disable=SC2034
|
|
FB_FUNC_DESCS['encode']='encode a file using libsvtav1 and libopus'
|
|
encode() {
|
|
set_encode_opts "$@"
|
|
local ret=$?
|
|
if [[ ${ret} -eq ${FUNC_EXIT_SUCCESS} ]]; then
|
|
return 0
|
|
elif [[ ${ret} -ne 0 ]]; then
|
|
return ${ret}
|
|
fi
|
|
gen_encode_script || return 1
|
|
}
|