Compare commits

...

1 Commits

Author SHA1 Message Date
Y fdaf3278ca wip… 2019-11-09 15:19:31 +01:00
1 changed files with 83 additions and 52 deletions

View File

@ -4,6 +4,7 @@
# Mandatory:
# -i <file> [-i <file> …] Input files
# Optional:
# -d Debug.
# -h Print this help, and information about the inputs.
# -n Do not actually run the commands (print them).
# -y Accept the default answers to this programs
@ -50,8 +51,9 @@ function usage() {
abort=true
}
while getopts i:o:t:A:SV:Q:P:T:W:H:Chny opt; do case $opt in
while getopts di:o:t:A:SV:Q:P:T:W:H:Chny opt; do case $opt in
h) usage ;;
d) debug=true ;;
n) fake=true ;;
y) defaults=true ;;
i) inputs[${#inputs[*]}]="$OPTARG" ;;
@ -85,16 +87,63 @@ if [[ "$x264qual" =~ pass ]]; then
x264qual="--stats $tmppfx.stats $x264qual"
fi
[ -n "$debug" ] && set -x
## SOME USEFUL FUNCTIONS
function split() {
# needed because `read` merges adjacent field separators
fields="$1"; shift
while IFS=$'\n' read field; do
[ $# -gt 0 ] && eval "${1}=\"$(sed 's/[\"$]/\\\0/g' <<<"$field")\""; shift
done < <(tr '\t' '\n' <<<"$fields")
}
function run() {
local err=0
for item in "$@"; do printf ' %q' "$item"; done; printf '\n'
if [ -z "$fake" ]; then
"$@"
err=$?
if [ $err -gt 1 ] || [ $err -gt 0 -a "$1" != mkvmerge ]; then
echo "ERROR: $1 exited with code ${err}." >&2
error=$((error+1))
fi
fi
}
function on_exit() {
if [ $error -eq 0 ]; then
run rm -f ${tmppfx}*
else
echo 'Errors were encountered. These files were not deleted:' >&2
printf '%s\n' ${tmppfx}* >&2
fi
}
trap on_exit EXIT
## ANALYSE INPUTS
# fields: str:file path, bool:use chapters, bool:use some subtitles,
# int:number of chapters
# int:number of chapters, string:original file path (≠file path if VOB)
exec 3>&1
IFS=$'\n' read -d '' -a f_info < <(
for f in "${inputs[@]}"; do
printf "$f\t0\t0\t"
ffprobe -loglevel error -show_chapters "$f" | grep -Fx '[CHAPTER]' | wc -l
for ((i=0; i<${#inputs[*]}; i++)); do
f="${inputs[$i]}"
realf="$f"
# Replace VOB files
# https://stackoverflow.com/questions/19200790/converting-dvd-image-with-subtitles-to-mkv-using-avconv
if [[ "$f" =~ \.vob$ ]] || [[ "$f" =~ \.VOB$ ]]; then
f=$tmppfx.$i.proxy.mkv
cmd=( ffmpeg -fflags +genpts -analyzeduration 3600M -probesize 4G
-i "$realf" -map 0:v -map 0:a -map 0:s -c copy "$f" )
echo "${cmd[*]}" >&3
"${cmd[@]}" >&2
fi
printf "%s\t0\t0\t%s\t%s\n" "$f" \
$(ffprobe -loglevel error -show_chapters "$f" | grep -Fx '[CHAPTER]' | wc -l) \
"$realf"
done
)
exec 3>&-
# fields: int:file index, int:stream index, str:codec, str:profile, int:width,
# int:height, [str:transformation], [int:new width], [int:new height],
@ -103,23 +152,25 @@ IFS=$'\n' read -d '' -a f_info < <(
exec 3>&1
IFS=$'\n' read -d '' -a v_info < <(
for ((i=0; i<${#inputs[*]}; i++)); do
ffprobe -loglevel error -show_streams -select_streams v "${inputs[$i]}" \
split "${f_info[$i]}" path usechap usesub nbchap origpath
ffprobe -loglevel error -show_streams -select_streams v "$path" \
| awk -F= -vfile=$i -vmw=$x264maxW -vmh=$x264maxH \
-vffcrop=$autocrop -vfffile="${inputs[$i]}" -vOFS=$'\t' '
-vffcrop=$autocrop -vfffile="$path" -vOFS=$'\t' '
BEGIN{
gsub(/["\$]/,"\\\\&",fffile)
fps=25
}
/^\[STREAM/ {
idx=0; codec=""; profile=""; fullw=768; fullh=432
sar="1:1"; fps=25; start=0; lang="und"; title=""
sar="1:1"; start=0; lang="und"; title=""
}
$1=="index" { idx=$2 }
$1=="codec_name" { codec=$2 }
$1=="profile" { profile=$2 }
$1=="width" { fullw=$2 }
$1=="height" { fullh=$2 }
$1=="width" { fullw=$2 }
$1=="height" { fullh=$2 }
$1=="sample_aspect_ratio" { sar=$2 }
$1=="avg_frame_rate" { fps=$2 }
$1=="avg_frame_rate" && $2!~"/0$" { fps=$2 }
$1=="start_time" { start=$2 }
$1=="TAG:language" { lang=$2 }
$1=="TAG:title" { title=$2 }
@ -177,7 +228,8 @@ exec 3>&-
# bool:use this stream as default audio, bool:force this audio stream
IFS=$'\n' read -d '' -a a_info < <(
for ((i=0; i<${#inputs[*]}; i++)); do
ffprobe -loglevel error -show_streams -select_streams a "${inputs[$i]}" \
split "${f_info[$i]}" path usechap usesub nbchap origpath
ffprobe -loglevel error -show_streams -select_streams a "$path" \
| awk -F= -vfile=$i -vabr=${akbps:-64} -vOFS=$'\t' '
/^\[STREAM/ {
idx=0; codec=""; profile=""; sampfreq=0; channels=2; layout="2.0"
@ -209,7 +261,8 @@ IFS=$'\n' read -d '' -a a_info < <(
# bool:force these subtitles
IFS=$'\n' read -d '' -a s_info < <(
for ((i=0; i<${#inputs[*]}; i++)); do
ffprobe -loglevel error -show_streams -select_streams s "${inputs[$i]}" \
split "${f_info[$i]}" path usechap usesub nbchap origpath
ffprobe -loglevel error -show_streams -select_streams s "$path" \
| awk -F= -vfile=$i -vOFS=$'\t' '
/^\[STREAM/ {
idx=0; codec=""; start=0; def=0; force=0; hearhelp=0; lang="und"; title=""
@ -233,6 +286,10 @@ IFS=$'\n' read -d '' -a s_info < <(
# $1:array, $2:list-program (awk)
function print_info() {
local -n arr=$1
if [ -n "$debug" ]; then
echo "= print_info $1 ="
for l in "${arr[@]}"; do tr '\t' '\n' <<<"$l" | nl -s: -w2 -ba | tr '\n' ' '; echo; done
fi
printf '%s\n' "${arr[@]}" | awk -F$'\t' -vOFS=$'\t' "$2"
}
@ -265,7 +322,7 @@ function set_flags() {
if [ ${#f_info[*]} -gt 0 ]; then
echo FILES:
print_info f_info '{ print NR-1, $1, $4==0?"":("(with " $4 " chapters)") }'
print_info f_info '{ print NR-1, $5, $4==0?"":("(with " $4 " chapters)") }'
if [ -z "$abort" ]; then
set_flags f_info 'File from which chapters should be read (if any): ' \
"$(printf '%s\n' "${f_info[@]}" \
@ -324,35 +381,6 @@ fi
## ENCODE
function split() {
# needed because `read` merges adjacent field separators
fields="$1"; shift
while IFS=$'\n' read field; do
[ $# -gt 0 ] && eval "${1}=\"$(sed 's/[\"$]/\\\0/g' <<<"$field")\""; shift
done < <(tr '\t' '\n' <<<"$fields")
}
function run() {
local err=0
for item in "$@"; do printf ' %q' "$item"; done; printf '\n'
if [ -z "$fake" ]; then
"$@"
err=$?
if [ $err -gt 1 ] || [ $err -gt 0 -a "$1" != mkvmerge ]; then
echo "ERROR: $1 exited with code ${err}." >&2
error=$((error+1))
fi
fi
}
function on_exit() {
if [ $error -eq 0 ]; then
run rm -f ${tmppfx}*
else
echo 'Errors were encountered. These files were not deleted:' >&2
printf '%s\n' ${tmppfx}* >&2
fi
}
trap on_exit EXIT
#⇒ Video
#⇒ http://labs.divx.com/node/16598
@ -361,6 +389,7 @@ for v in "${v_info[@]}"; do
file idx codec profile w h stdop cropL cropT cropR cropB stdw stdh \
sar fps start lang title use
[ $use -eq 1 ] || continue
split "${f_info[$file]}" path usechap usesub nbchap origpath
if [ $(bc <<<"$fps") -gt 25 ]; then
fps=25
fi
@ -372,12 +401,12 @@ for v in "${v_info[@]}"; do
if [[ "$x264qual" =~ pass ]]; then
run nice -n 10 x264 $vopt $vopt_divx $x264qual 1 \
${x264slow:+--slow-firstpass} -o $tmppfx.$file.$idx.mkv "${inputs[$file]}"
${x264slow:+--slow-firstpass} -o $tmppfx.$file.$idx.mkv "$path"
run nice -n 10 x264 $vopt $vopt_divx $x264qual 2 \
-o $tmppfx.$file.$idx.mkv "${inputs[$file]}"
-o $tmppfx.$file.$idx.mkv "$path"
else
run nice -n 10 x264 $vopt $vopt_divx $x264qual \
-o $tmppfx.$file.$idx.mkv "${inputs[$file]}"
-o $tmppfx.$file.$idx.mkv "$path"
fi
done
@ -389,12 +418,13 @@ for a in "${a_info[@]}"; do
file idx codec profile sampfreq channels kbps layout start def force \
seehelp lang title use setdef setforce
[ $use -eq 1 ] || continue
split "${f_info[$file]}" path usechap usesub nbchap origpath
if [ "$codec" == 'aac' ]; then
run ffmpeg -loglevel warning -i "${inputs[$file]}" -vn -map 0:$idx \
-movflags +faststart -c:a copy $tmppfx.$file.$idx.aac
run ffmpeg -loglevel warning -i "$path" -vn -sn -map 0:$idx \
-c:a copy $tmppfx.$file.$idx.aac
else
run ffmpeg -loglevel warning -i "${inputs[$file]}" -vn -map 0:$idx \
-movflags +faststart -c:a aac -b:a ${kbps}k $tmppfx.$file.$idx.aac
run ffmpeg -loglevel warning -i "$path" -vn -sn -map 0:$idx \
-c:a libfdk_aac -b:a ${kbps}k $tmppfx.$file.$idx.aac
fi
done
@ -409,8 +439,8 @@ mkvopt=(
# subtitles & chapters
for f in "${f_info[@]}"; do
split "$f" path usechap usesub nbchap
for ((i=0; i<${#f_info[*]}; i++)); do
split "${f_info[$i]}" path usechap usesub nbchap origpath
[ $usechap -eq 0 -a $usesub -eq 0 ] && continue
if [ $usesub -eq 1 ]; then
subs=
@ -419,6 +449,7 @@ for f in "${f_info[@]}"; do
split "$s" \
file idx codec start def force hearhelp lang title use setdef setforce
[ $use -eq 1 ] || continue
[ $file -eq $i ] || continue
subs=$subs,$idx
newopt=( "${newopt[@]}"
--default-track $idx:$setdef --forced-track $idx:$setforce )