wip…
parent
3e9871d9a1
commit
fdaf3278ca
135
DivxPlusHD.sh
135
DivxPlusHD.sh
|
@ -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 program’s
|
||||
|
@ -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 )
|
||||
|
|
Loading…
Reference in New Issue