ambevar-dotfiles/.scripts/tc-video-generic

160 lines
3.9 KiB
Bash
Executable File

#!/bin/sh
## TODO: option to replace original file.
## TODO: audio quality. Copy if AAC or OGG <320k.
## TODO: crop options.
## TODO: handle srt encoding.
if [ -z "$(command -v ffmpeg)" ]; then
echo "ffmpeg required."
exit
fi
_printhelp()
{
cat <<EOF
Usage: ${1##*/} [OPTIONS] FILES|FOLDERS
Transcode FILES or files found in FOLDERS 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.
-c: Copy streams (no reencoding).
-f: Overwrite existing file if any.
-h: Display this help.
-o OPT: Additional options.
-s: Sample of 5 minutes.
-S MIN: Sample of MIN minutes.
-t: Remove all "title" metadata.
Examples:
* Exchange stream 1 an 2 by first removing them, then reading them in the
desired order.
${1##*/} -o '-map -0:1 -map -0:2 -map 0:2 -map 0:1' input.mkv
* Change audio stream 1 title and remove audio stream 2 title:
${1##*/} -o '-metadata:s:a:0 title="FR: OGG Stereo" -metadata:s:a:1 title=' input.mkv
EOF
}
TC_SAMPLE=""
TC_USER_OPT=""
TC_REMOVE_TITLE=false
TC_VIDEO_CODEC="libx264"
TC_AUDIO_CODEC="libvorbis"
TC_VIDEO_OPT="-preset slow -crf 20"
## What to do if file exists:
# -y overwrite
# -n do not overwrite.
TC_OVERWRITE="-n"
## WARNING: we mix down audio to 2 channels with '-ac 2'. This greatly reduce
## file size and avoid any confusion for playback, which is often the case when
## converting DTS to any other format because DTS has embedded channel
## description which is not available in other formats.
TC_AUDIO_OPT="-b:a 192k -ac 2"
while getopts ":cfho:sS:t" opt; do
case $opt in
c)
TC_VIDEO_OPT=""
TC_AUDIO_OPT=""
TC_VIDEO_CODEC="copy"
TC_AUDIO_CODEC="copy" ;;
f)
TC_OVERWRITE="-y" ;;
h)
_printhelp "$0"
exit 1 ;;
o)
TC_USER_OPT="$OPTARG" ;;
s)
TC_SAMPLE="-ss 60 -t 360" ;;
S)
TC_SAMPLE="-ss 60 -t $((60*$OPTARG))" ;;
t)
TC_REMOVE_TITLE=true ;;
?)
_printhelp "$0"
exit 1 ;;
:)
echo "Missing argument."
_printhelp "$0"
exit 1 ;;
esac
done
shift $(($OPTIND - 1))
if [ $# -eq 0 ]; then
_printhelp "$0"
exit
fi
## Zsh compatibility. We need it otherwise word splitting of parameter like
## TC_SAMPLE will not work.
STATUS="$(set -o | grep 'shwordsplit' | awk '{print $2}')"
[ "$STATUS" = "off" ] && set -o shwordsplit
_tc_transcode()
{
cat<<EOF
================================================================================
User options: ${TC_USER_OPT:-None}
Sample: ${TC_SAMPLE:-No}
Clear 'Title': $TC_REMOVE_TITLE
================================================================================
EOF
STREAM_TITLE=""
if $TC_REMOVE_TITLE; then
STREAM_NUM=$(ffmpeg -i "$1" 2>&1 | grep -c 'Stream')
for i in $(seq 0 $STREAM_NUM); do
STREAM_TITLE="${STREAM_TITLE}-metadata:s:$i title= "
done
fi
ffmpeg $TC_OVERWRITE -i "$1" \
-c:v $TC_VIDEO_CODEC $TC_VIDEO_OPT \
-c:a $TC_AUDIO_CODEC $TC_AUDIO_OPT \
-c:s copy \
-map 0 $STREAM_TITLE \
$TC_SAMPLE $TC_USER_OPT "${1%.*}-$(date '+%F-%H%M%S').mkv"
}
for i in "$@"; do
## Argument is a folder. We search for all video files in there.
if [ -d "$i" ]; then
## TODO: provide max-depth as option.
while read -r j; do
_tc_transcode $j
done <<EOF
$(find "$i" \( \
-iname '*.mkv' -o \
-iname '*.mp4' -o \
-iname '*.avi' -o \
-iname '*.webm' -o \
-iname '*.flv' -o \
-iname '*.wmv' -o \
-iname '*.mpg' \) )
EOF
else
## Argument is a regular file.
_tc_transcode "$i"
fi
done
## Restore Zsh previous options. This will not turn off shwordsplit if it
## was on before calling the function.
[ "$STATUS" = "off" ] && set +o shwordsplit