255 lines
6.8 KiB
Bash
255 lines
6.8 KiB
Bash
## -*- mode:sh -*- #
|
|
################################################################################
|
|
## Shell -- Trancode function set.
|
|
## Date 2013-01-19
|
|
################################################################################
|
|
|
|
## Tool list: ffmpeg, recode
|
|
|
|
## Support:
|
|
# ffmpeg -codecs
|
|
# ffmpeg -formats
|
|
|
|
## Useful guide:
|
|
# http://ffmpeg.org/trac/ffmpeg/wiki/x264EncodingGuide
|
|
|
|
################################################################################
|
|
## Text
|
|
|
|
tc_text_scan ()
|
|
{
|
|
local IFS
|
|
IFS="
|
|
"
|
|
|
|
for i in $(find . -type f -size -50M -print); do
|
|
echo -n "# "
|
|
file "$i"
|
|
grep -m1 "\`" "$i"
|
|
grep -m1 "oe" "$i"
|
|
done
|
|
}
|
|
|
|
## Confert all 'bad' encoding to UTF-8/LF.
|
|
##
|
|
## WARNING: It will fail for encoding other than ISO-8859-1 and cp1252.
|
|
tc_text_2utf8 ()
|
|
{
|
|
local CODING
|
|
local IFS
|
|
IFS="
|
|
"
|
|
|
|
for i in $(find . -type f -size -50M -print); do
|
|
CODING=$(file "$i")
|
|
|
|
if [ -n "$(echo $CODING | grep 'ISO-8859')" ]; then
|
|
echo "ISO-8859: [$i]"
|
|
recode latin1..utf-8 "$i"
|
|
|
|
elif [ -n "$(echo $CODING | grep 'Non-ISO extended-ASCII')" ]; then
|
|
echo "cp1252: [$i]"
|
|
recode cp1252..utf-8 "$i"
|
|
|
|
elif [ -n "$(echo $CODING | grep 'UTF-16 Unicode text')" ]; then
|
|
echo "UTF-16: [$i]"
|
|
recode utf-16..utf-8 "$i"
|
|
|
|
elif [ -n "$(echo $CODING | grep 'UTF-8 Unicode (with BOM)')" ]; then
|
|
echo "UTF-8 BOM: [$i]"
|
|
sed -i '1s/^.//' "$i"
|
|
## The following commands work, but may be overkill.
|
|
# dd iflag=skip_bytes skip=3 if=file.srt of=temp.srt
|
|
# dd bs=1 skip=3 if=file.srt of=temp.srt
|
|
# tail -c +32 file.srt > temp.srt
|
|
fi
|
|
|
|
if [ -n "$(echo $CODING | grep 'CRLF')" ]; then
|
|
echo "CRLF: [$i]"
|
|
sed -i 's/\r//g' "$i"
|
|
fi
|
|
|
|
done
|
|
}
|
|
|
|
################################################################################
|
|
## Video
|
|
|
|
## TODO: audio quality. Copy if AAC or OGG <320k.
|
|
## TODO: chapters support. Already OK?
|
|
## TODO: crop options.
|
|
## TODO: custom mapping.
|
|
## TODO: handle srt encoding.
|
|
## TODO: option to replace original file.
|
|
## TODO: work with -threads option.
|
|
|
|
## Vars
|
|
TC_AUDIO_QUAL=192k
|
|
TC_OUTDIR="$HOME/temp"
|
|
|
|
## quality*size ~= 1/speed
|
|
# ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow, placebo
|
|
TC_VIDEO_PRESET=slow
|
|
|
|
## Overall quality. Logarithmic scale.
|
|
# 18 is near perfection.
|
|
# 22 is really good compression, while a bit more blurry than the original.
|
|
# 20 is a good compromise.
|
|
TC_VIDEO_QUAL=20
|
|
|
|
## x264 tuning (presets).
|
|
## Possible values: film, animation, grain, ...
|
|
## See x264 --fullhelp.
|
|
## No tuning by default.
|
|
# TC_VIDEO_TUNE="-tune film"
|
|
TC_VIDEO_TUNE=""
|
|
|
|
## x264 options.
|
|
## Possible values: hex, umh...
|
|
## me=umh is default.
|
|
# TC_VIDEO_OPTS="-x264opts me=hex"
|
|
TC_VIDEO_OPTS=""
|
|
|
|
tc_demux_audio()
|
|
{
|
|
ffmpeg $TC_OVERWRITE -i "$1" -vn -sn -c:a copy -map 0:1 "$2"
|
|
}
|
|
|
|
tc_audio()
|
|
{
|
|
echo "================================================================================"
|
|
ffmpeg -threads 4 $TC_OVERWRITE -i "$1" -vn -c:a libvorbis -b:a $TC_AUDIO_QUAL "${1%.*}-$(date "+%F-%H%M%S").ogg"
|
|
}
|
|
|
|
tc_transcode()
|
|
{
|
|
_printhelp()
|
|
{
|
|
echo "Synopsis:"
|
|
echo -e " $1 [-f|-h|-s] FILES"
|
|
echo
|
|
echo "Usage:"
|
|
echo -e " default:\tTranscode FILES to .mkv with x264 and ogg. Output files are the same as the original, with time appended. You can customize encoding with the TC_* variables."
|
|
echo -e " -f:\t\tOverwrite existing file if any."
|
|
echo -e " -h:\t\tDisplay this help."
|
|
echo -e " -s:\t\tSample of ten minutes."
|
|
}
|
|
|
|
## What to do if file exists:
|
|
# -y overwrite
|
|
# -n do not overwrite.
|
|
local TC_OVERWRITE
|
|
TC_OVERWRITE=-n
|
|
|
|
local TC_SAMPLE
|
|
TC_SAMPLE=""
|
|
|
|
while getopts ":fhs" opt; do
|
|
case $opt in
|
|
f)
|
|
TC_OVERWRITE=-y
|
|
;;
|
|
h)
|
|
_printhelp "$0"
|
|
return 1
|
|
;;
|
|
s)
|
|
TC_SAMPLE="-ss 60 -t 600 -i"
|
|
;;
|
|
?)
|
|
_printhelp "$0"
|
|
return 1
|
|
;;
|
|
:)
|
|
echo "Missing argument."
|
|
echo "Use $0 -h for help."
|
|
return 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
shift $(($OPTIND - 1))
|
|
|
|
|
|
## Zsh compatibility
|
|
local STATUS
|
|
STATUS="$(set -o | grep 'shwordsplit' | awk '{print $2}')"
|
|
if [ "$STATUS" = "off" ]; then
|
|
set -o shwordsplit
|
|
fi
|
|
|
|
|
|
if [ $# -eq 0 ]; then
|
|
tc_transcode .
|
|
return
|
|
fi
|
|
|
|
_tc_transcode()
|
|
{
|
|
echo "================================================================================"
|
|
ffmpeg $TC_OVERWRITE $TC_SAMPLE -i "$1" \
|
|
-c:v libx264 -preset $TC_VIDEO_PRESET -crf $TC_VIDEO_QUAL $TC_VIDEO_TUNE $TC_VIDEO_OPTS \
|
|
-c:a libvorbis -b:a $TC_AUDIO_QUAL \
|
|
-c:s copy \
|
|
-map 0 "${1%.*}-$(date "+%F-%H%M%S").mkv"
|
|
}
|
|
|
|
for i in "$@"; do
|
|
if [ -d "$i" ]; then
|
|
|
|
local IFS
|
|
IFS="
|
|
"
|
|
|
|
## TODO: provide max-depth as option.
|
|
for i in $(find "$i" \( \
|
|
-iname '*.mkv' -o \
|
|
-iname '*.mp4' -o \
|
|
-iname '*.avi' -o \
|
|
-iname '*.webm' -o \
|
|
-iname '*.flv' -o \
|
|
-iname '*.wmv' -o \
|
|
-iname '*.mpg' \) ); do
|
|
_tc_transcode $i
|
|
done
|
|
|
|
else
|
|
_tc_transcode "$i"
|
|
fi
|
|
|
|
done
|
|
|
|
|
|
## Restore Zsh previous options. This will not turn off shwordsplit if it
|
|
## was on before calling the function.
|
|
if [ "$STATUS" = "off" ]; then
|
|
set +o shwordsplit
|
|
fi
|
|
|
|
}
|
|
|
|
# tc_mux()
|
|
# {
|
|
# # ffmpeg -y -i "$1" -i "$2" -metadata:s:a:1 language=fre -c:v copy -c:a copy -map 0 -map 1 "final.mkv"
|
|
# }
|
|
|
|
|
|
################################################################################
|
|
## OLD
|
|
|
|
## High in Handbrake:
|
|
# b-adapt=2:rc-lookahead=50:me=umh
|
|
|
|
## Mine in Handbrake:
|
|
# ref=1:weightp=1:subq=2:rc-lookahead=10:trellis=0:8x8dct=0
|
|
|
|
## Mine with details:
|
|
# cabac=1:ref=1:deblock=1:0:0:analyse=0x1:0x111:me=hex:subme=2:psy=1:psy_rd=1.00:0.00:mixed_ref=0:me_range=16:chroma_me=1:trellis=0:8x8dct=0:cqm=0:deadzone=21,11:fast_pskip=1:chroma_qp_offset=0:threads=6:sliced_threads=0:nr=0:decimate=1:interlaced=0:bluray_compat=0:constrained_intra=0:bframes=3:b_pyramid=2:b_adapt=1:b_bias=0:direct=1:weightb=1:open_gop=0:weightp=1:keyint=240:keyint_min=24:scenecut=40:intra_refresh=0:rc_lookahead=10:rc=crf:mbtree=1:crf=20.0:qcomp=0.60:qpmin=3:qpmax=69:qpstep=4:ip_ratio=1.40:aq=1:1.00
|
|
|
|
## Mine diff with default:
|
|
# ref=1:analyse=0x1:0x111:me=hex:subme=2:trellis=0:8x8dct=0:chroma_qp_offset=0:b_adapt=1:direct=1:weightp=1:keyint=240:rc_lookahead=10
|
|
|
|
|
|
## Best for bad quality movies.
|
|
# me=hex
|