Shell/Scripts: moved transcoding functions to separate scripts.

Shell: included FreeBSD and Pacman aliases in main alias file.
master
Pierre Neidhardt 2013-03-03 00:01:20 +01:00
parent 9db5273018
commit 524aaf9042
14 changed files with 741 additions and 763 deletions

31
.scripts/tc-audio-batch Executable file
View File

@ -0,0 +1,31 @@
#!/bin/sh
if [ -z "$(command -v ffmpeg)" ]; then
echo "ffmpeg required."
exit
fi
if [ ! -f "$HOME/.shell.d/titlecase.awk" ]; then
echo "AWK titlecase script required."
exit
fi
if [ ! -f "${0%/*}/tc-audio-transcode" ]; then
echo "tc-audio-transcode script required."
exit
fi
## This will convert all tracks in current folder and subfolders.
while read -r i; do
"${0%/*}/tc_audio_transcode" "$@" $i
done <<EOF
$(find "." \( \
-iname '*.mp3' -o \
-iname '*.flac' -o \
-iname '*.wv' -o \
-iname '*.aac' -o \
-iname '*.wav' -o \
-iname '*.ape' -o \
-iname '*.mpc' \) )
EOF

32
.scripts/tc-audio-scan Executable file
View File

@ -0,0 +1,32 @@
#!/bin/sh
if [ -z "$(command -v mediainfo)" ]; then
echo "mediainfo required."
exit
fi
## This will check for badly encoded audio.
while read -r i; do
BUFFER="$(mediainfo "$i")"
if [ -n "$(echo "$BUFFER" | grep "Bit rate mode *: Constant")" ]; then
echo "$i : CBR"
fi
if [ -n "$(echo "$BUFFER" | grep "Cover *: Yes")" ]; then
echo "$i : Cover"
fi
if [ -n "$(echo "$BUFFER" | grep "Track name/Position *: 0+")" ]; then
echo "$i : Leading zeros"
fi
done <<EOF
$(find "." \( \
-iname '*.mp3' -o \
-iname '*.flac' -o \
-iname '*.wv' -o \
-iname '*.aac' -o \
-iname '*.wav' -o \
-iname '*.ape' -o \
-iname '*.mpc' \) )
EOF

380
.scripts/tc-audio-transcode Executable file
View File

@ -0,0 +1,380 @@
#!/bin/sh
if [ -z "$(command -v ffmpeg)" ]; then
echo "ffmpeg required."
exit
fi
if [ ! -f "${0%/*}/titlecase.awk" ]; then
echo "AWK titlecase script required."
exit
fi
################################################################################
## User options
################################################################################
## For the sake of simplicity we convert everything to OGG.
## You can easily set output folder to current folder with TC_AUDIO_DEST=".".
TC_AUDIO_DEST="/media/data1/Musics/"
## OGG quality ranges from -1 to 10.
## -q-1 45 kbit/s
## -q0 64 kbit/s
## -q1 80 kbit/s
## -q2 96 kbit/s
## -q3 112 kbit/s
## -q4 128 kbit/s
## -q5 160 kbit/s
## -q6 192 kbit/s
## -q7 224 kbit/s
## -q8 256 kbit/s
## -q9 320 kbit/s
## -q10 500 kbit/s
## Artists: we use same value for artist and album_artist.
## Genres: since this is not universal by nature, we do not put a genre in tags.
## Composer: not universal neither, we prefer ARTIST over COMPOSER, so COMPOSER will be empty.
################################################################################
## End of user options
################################################################################
## This function is supposed to work on a per-album basis. Folders will not be
## accepted as argument. This function will work best if all tracks of a folder
## belong to the same album. Theres is no way to handle covers raliably, so you
## should leave the only covers you want to keep in the working folder.
## TODO: cover resolution check. Should be > 100x100. Above <1000x1000 should give a warning.
## TODO: extract cover from tags if checksum does not match any from current folder.
_printhelp ()
{
cat <<EOF
Usage: $1 [OPTIONS] FILE
Options:
-p : preview (do not change file)
-s : skip encoding
Tags:
-a : artist
-b : bitrate
-d : date
-g : genre
-l : album
-n : track number
-t : title
You can use the following variables to refer to existing tags:
\$ALBUM
\$ALBUM_ARTIST
\$ARTIST
\$COMPOSER
\$DATE
\$TYER
\$GENRE
\$TRACK
Default output folder:
OUTPUT="\$TC_AUDIO_DEST/\$OUTPUT_ARTIST/\${OUTPUT_ALBUM:+\${OUTPUT_DATE:+\$OUTPUT_DATE - }\$OUTPUT_ALBUM/}"
Default output file:
OUTPUT_FILE="\$OUTPUT\$OUTPUT_ARTIST - \${OUTPUT_TRACK:+\$OUTPUT_TRACK - }\$OUTPUT_TITLE.\$OUTPUT_FORMAT"
Examples:
Set the 'artist' tag and reencode:
$1 -a 'Franz Lizst' file.mp3
Set 'artist' to be 'composer', and 'title' to be preceeded by 'artist', do not reencode:
$1 -s -a '\$COMPOSER' -t '\$ARTIST - \$TITLE' file.ogg
IMPORTANT: you *must* use single quotes when using variables.
EOF
}
## OPTIONS
SKIP=0
PREVIEW=0
## TAGS
OUTPUT_ALBUM='$ALBUM'
OUTPUT_ARTIST='$ARTIST'
OUTPUT_DATE='$DATE'
OUTPUT_GENRE='$GENRE'
OUTPUT_TITLE='$TITLE'
OUTPUT_TRACK='$TRACK'
## PROPERTIES
OUTPUT_BITRATE=0
## Non-cli-option data. Modifying these imply modifications in code below.
OUTPUT_FORMAT="ogg"
OGG_PARAM="-c:a libvorbis -b:a ${OUTPUT_BITRATE}k"
## These ones are not cli-options either, but this could be easily changed.
OUTPUT='$TC_AUDIO_DEST/$OUTPUT_ARTIST/${OUTPUT_ALBUM:+${OUTPUT_DATE:+$OUTPUT_DATE - }$OUTPUT_ALBUM/}'
OUTPUT_FILE='$OUTPUT$OUTPUT_ARTIST - ${OUTPUT_PADDEDTRACK:+$OUTPUT_PADDEDTRACK - }$OUTPUT_TITLE'
while getopts ":a:b:d:g:l:n:t:hps" opt; do
case $opt in
a) OUTPUT_ARTIST=$OPTARG ;;
b) OUTPUT_BITRATE=$OPTARG ;;
d) OUTPUT_DATE=$OPTARG ;;
g) OUTPUT_GENRE=$OPTARG ;;
l) OUTPUT_ALBUM=$OPTARG ;;
n) OUTPUT_TRACK=$OPTARG ;;
t) OUTPUT_TITLE=$OPTARG ;;
h)
_printhelp "$0"
exit 1
;;
p)
PREVIEW=1
;;
s)
SKIP=1
;;
?)
_printhelp "$0"
exit 1
;;
:)
echo "Missing argument."
echo "Use $0 -h for help."
exit 1
;;
esac
done
shift $(($OPTIND - 1))
if [ $# -eq 0 ]; then
_printhelp "$0"
exit
fi
##================================================================================
## Get metadata.
STREAM=$(ffmpeg -i "$1" 2>&1)
METADATA=$(echo "$STREAM" | sed -n '/Metadata/ ! d; /Metada/{b cont}; :cont ; {n;p;b cont}')
STREAM=$(echo "$STREAM" | grep "Stream")
if [ -z "$STREAM" ]; then
echo "Non-audio file."
exit
fi
## We get format from extension, because codec is not reliable either.
FORMAT="${1##*.}"
## CODEC is unused for now.
CODEC=$(echo "$STREAM" | sed -n '/Audio:/ {s/.*Audio: \([^,]*\),.*/\1/;p}')
BITRATE=$(echo "$STREAM" | sed -n '/kb\/s/ {s/.*, \(.*\) kb\/s/\1/;p}')
if [ -z "$FORMAT" ]; then
echo "ERROR: non-audio file."
exit
fi
_metadata_filter()
{
echo "$METADATA" | grep -i "\<$1\>" | sed 's/[^:]* : //g'
}
TITLE=$(_metadata_filter "title")
ARTIST=$(_metadata_filter "artist")
ALBUM=$(_metadata_filter "album")
ALBUM_ARTIST=$(_metadata_filter "album_artist")
COMPOSER=$(_metadata_filter "composer")
DISC=$(_metadata_filter "disc")
GENRE=$(_metadata_filter "genre")
TRACK=$(_metadata_filter "track")
DATE=$(_metadata_filter "date")
TYER=$(_metadata_filter "TYER")
##================================================================================
## OUTPUT variables.
## We use the AWK script to set title case. The script contains
## exceptions that can be configured. We fix some chars with sed.
# => '
# : => -
# / => -
_string_cleanser()
{
echo "$@" | awk -f "${0%/*}/titlecase.awk" \
| sed -n -e "s//'/g ; s/ *: */ - /g ; s| */ *| - |g; p; q"
}
OUTPUT_TITLE=$(eval _string_cleanser $OUTPUT_TITLE)
OUTPUT_TITLE="${OUTPUT_TITLE:-Unknown Title}"
## We use album artist if artist is empty.
OUTPUT_ARTIST=$(eval _string_cleanser $OUTPUT_ARTIST)
[ -z "$OUTPUT_ARTIST" ] && [ -n "$ALBUM_ARTIST" ] && OUTPUT_ARTIST="$ALBUM_ARTIST"
OUTPUT_ARTIST="${OUTPUT_ARTIST:-Unknown Artist}"
OUTPUT_ALBUM=$(eval _string_cleanser $OUTPUT_ALBUM)
[ -z "$OUTPUT_ALBUM" ] && echo "${#OUTPUT_ALBUM}${OUTPUT_ALBUM}"
## We put genre in lower case and underscore to ease matching. If it
## matches, we use the Title Case match. If it does not, we set it to empty.
OUTPUT_GENRE=$(eval _string_cleanser $OUTPUT_GENRE | tr '[:upper:] ' '[:lower:]_')
case $OUTPUT_GENRE in
ost) OUTPUT_GENRE="Soundtrack" ;;
soundtrack) OUTPUT_GENRE="Soundtrack";;
original_soundtrack) OUTPUT_GENRE="Soundtrack";;
classical) OUTPUT_GENRE="Classical";;
classics) OUTPUT_GENRE="Classical";;
classic) OUTPUT_GENRE="Classical";;
*) OUTPUT_GENRE="";;
esac
## We remove the track count if any, we suppress leading zeros.
OUTPUT_TRACK=$(eval _string_cleanser $OUTPUT_TRACK | sed -e 's/^0*//' -e 's|/.*||')
## If DATE is not a year, we use TYER if it is a year.
OUTPUT_DATE=$(eval _string_cleanser $OUTPUT_DATE)
TYER_REG=$(echo "$TYER" | sed -n 's/.*\([[:digit:]]\{4\}\).*/\1/p')
if [ ${#DATE} -ne 4 ] && [ ${#TYER_REG} -eq 4 ]; then
OUTPUT_DATE="$TYER_REG"
fi
## QUALITY
## If bitrate argumument is not provided, we use BITRATE value.
[ $OUTPUT_BITRATE -eq 0 ] && OUTPUT_BITRATE=${BITRATE}
## TODO: test if table is useful at all.
# if [ $OUTPUT_BITRATE -eq 0 ]; then
# [ $BITRATE -le 45 ] && OUTPUT_BITRATE=45k
# [ $BITRATE -gt 45 ] && OUTPUT_BITRATE=64k
# [ $BITRATE -gt 64 ] && OUTPUT_BITRATE=80k
# [ $BITRATE -gt 80 ] && OUTPUT_BITRATE=96k
# [ $BITRATE -gt 96 ] && OUTPUT_BITRATE=112k
# [ $BITRATE -gt 112 ] && OUTPUT_BITRATE=128k
# [ $BITRATE -gt 128 ] && OUTPUT_BITRATE=160k
# [ $BITRATE -gt 160 ] && OUTPUT_BITRATE=192k
# [ $BITRATE -gt 192 ] && OUTPUT_BITRATE=224k
# [ $BITRATE -gt 224 ] && OUTPUT_BITRATE=256k
# [ $BITRATE -gt 256 ] && OUTPUT_BITRATE=320k
# [ $BITRATE -gt 320 ] && OUTPUT_BITRATE=500k
# fi
## Only reencode if not in OGG and if SKIP not set.
OGG_PARAM="-c:a libvorbis -b:a ${OUTPUT_BITRATE}k"
[ $SKIP -ne 0 ] && OGG_PARAM="-c:a copy" && OUTPUT_FORMAT="$FORMAT"
[ "$FORMAT" = "ogg" ] && OGG_PARAM="-c:a copy"
## Make sure track number has two digits for file name only.
OUTPUT_PADDEDTRACK
OUTPUT_PADDEDTRACK=$OUTPUT_TRACK
if [ -n "$OUTPUT_PADDEDTRACK" ]; then
[ ${OUTPUT_PADDEDTRACK} -lt 10 ] && OUTPUT_PADDEDTRACK="0$OUTPUT_PADDEDTRACK"
fi
OUTPUT=$(eval echo $OUTPUT)
OUTPUT_FILE=$(eval echo $OUTPUT_FILE)
## IF file exist, we append a uniq timestamp to the name.
[ -e "${OUTPUT_FILE}.$OUTPUT_FORMAT" ] && OUTPUT_FILE="$OUTPUT_FILE-$(date '+%F-%H%M%S')"
##==============================================================================
## PREVIEW
echo "==> BEFORE"
echo "ALBUM [$ALBUM]"
echo "ALBUM_ARTIST [$ALBUM_ARTIST]"
echo "ARTIST [$ARTIST]"
echo "BITRATE [$BITRATE]"
echo "COMPOSER [$COMPOSER]"
echo "DATE [$DATE]"
echo "DISC [$DISC]"
echo "FORMAT [$FORMAT]"
echo "GENRE [$GENRE]"
echo "TITLE [$TITLE]"
echo "TRACK [$TRACK]"
echo "TYER [$TYER]"
echo
echo "==> AFTER"
echo "ALBUM [$OUTPUT_ALBUM]"
echo "ARTIST [$OUTPUT_ARTIST]"
echo "BITRATE [$OUTPUT_BITRATE]"
echo "DATE [$OUTPUT_DATE]"
echo "FORMAT [$OUTPUT_FORMAT]"
echo "GENRE [$OUTPUT_GENRE]"
echo "TITLE [$OUTPUT_TITLE]"
echo "TRACK [$OUTPUT_TRACK]"
echo
echo "==> OUTPUT"
echo "[$OUTPUT_FILE.$OUTPUT_FORMAT]"
# echo "[$OGG_PARAM]"
echo
[ $PREVIEW -ne 0 ] && exit
##==============================================================================
## RUN PROCESS
## Make sure directory exists.
mkdir -p "$OUTPUT"
if [ $? -ne 0 ]; then
echo "ERROR: could not create output folder"
exit
fi
## COVER
## We copy cover only if it does not already exist.
while read -r i; do
OUTPUT_COVER="$OUTPUT/${OUTPUT_ALBUM:+$OUTPUT_ALBUM - }Cover"
OUTPUT_COVERFILE="$OUTPUT_COVER.${i##*.}"
COVER_COUNTER=1
## Same cover is already in target folder.
if [ -e "$OUTPUT_COVERFILE" ] && \
[ "$(sha1sum $OUTPUT_COVERFILE | cut -f1 -d' ')" = "$(sha1sum $i | cut -f1 -d' ')" ]; then
continue
fi
## Different cover with same name is in target folder. We append a number.
while [ -e "$OUTPUT_COVERFILE" ] && \
[ ! "$(sha1sum $OUTPUT_COVERFILE | cut -f1 -d' ')" = "$(sha1sum $i | cut -f1 -d' ')" ]; do
OUTPUT_COVERFILE="${OUTPUT_COVER} $COVER_COUNTER.${i##*.}"
COVER_COUNTER=$(($COVER_COUNTER+1))
done
echo "==> COVER"
cp -nv "$i" "$OUTPUT_COVERFILE"
echo
done <<EOF
$(find "." \( -iname '*.png' -o -iname '*.jpg' \) )
EOF
## Zsh compatibility. We need it otherwise word splitting of parameter like
## OGG_PARAM will not work.
STATUS="$(set -o | grep 'shwordsplit' | awk '{print $2}')"
[ "$STATUS" = "off" ] && set -o shwordsplit
## TAG/RECODE
ffmpeg -i "$1" $OGG_PARAM \
-metadata title="$OUTPUT_TITLE" \
-metadata artist="$OUTPUT_ARTIST" \
-metadata track="$OUTPUT_TRACK" \
-metadata date="$OUTPUT_DATE" \
-metadata album="$OUTPUT_ALBUM" \
-metadata album_artist="$OUTPUT_ARTIST" \
-metadata genre="$OUTPUT_GENRE" \
-metadata composer="" \
-metadata TYER="" \
-metadata disc="" \
"$OUTPUT_FILE.$OUTPUT_FORMAT"
## Restore Zsh previous options. This will not turn off shwordsplit if it
## was on before calling the function.
[ "$STATUS" = "off" ] && set +o shwordsplit

43
.scripts/tc-text-2utf8 Executable file
View File

@ -0,0 +1,43 @@
#!/bin/sh
if [ -z "$(command -v recode)" ]; then
echo "recode needed."
exit
fi
## Convert all 'bad' encoding to UTF-8/LF. WARNING: It will fail for encodings
## other the one explicitly supported below.
while read -r i; 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"
## sed -i is not the fastest depending on the implementations. 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 <<EOF
$(find . -type f -size -50M -print)
EOF

10
.scripts/tc-text-scan Executable file
View File

@ -0,0 +1,10 @@
#!/bin/sh
while read -r i; do
echo -n "# "
file "$i"
grep -m1 "\`" "$i"
grep -m1 "oe" "$i"
done <<EOF
$(find . -type f -size -50M -print)
EOF

16
.scripts/tc-video-audio2ogg Executable file
View File

@ -0,0 +1,16 @@
#!/bin/sh
if [ -z "$(command -v ffmpeg)" ]; then
echo "ffmpeg required."
exit
fi
if [ $# -ne 1 ]; then
echo "Usage: ${0##*/} VIDEO"
fi
## TODO: getopt support for audio quality.
TC_VIDEO_AUDIO_QUAL=192k
echo "================================================================================"
ffmpeg -i "$1" -vn -c:a libvorbis -b:a $TC_VIDEO_AUDIO_QUAL "${1%.*}-$(date '+%F-%H%M%S').ogg"

12
.scripts/tc-video-demux-audio Executable file
View File

@ -0,0 +1,12 @@
#!/bin/sh
if [ -z "$(command -v ffmpeg)" ]; then
echo "ffmpeg required."
exit
fi
if [ $# -ne 2 ]; then
echo "Usage: ${0##*/} VIDEO AUDIO_OUTPUT"
fi
ffmpeg -i "$1" -vn -sn -c:a copy -map 0:1 "$2"

158
.scripts/tc-video-transcode Executable file
View File

@ -0,0 +1,158 @@
#!/bin/sh
################################################################################
## User options
################################################################################
## To check what fmmpeg supports:
# ffmpeg -codecs
# ffmpeg -formats
## Useful guides
## x264: http://ffmpeg.org/trac/ffmpeg/wiki/x264EncodingGuide
## ID3 details: http://en.wikipedia.org/wiki/ID3
TC_VIDEO_AUDIO_QUAL=192k
## 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=""
################################################################################
## End of user options
################################################################################
## 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: workout -threads option.
## TODO: separate functions:
## tc_video_batch
## tc_video_transcode
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.
-f: Overwrite existing file if any.
-h: Display this help.
-s: Sample of ten minutes.
EOF
}
## What to do if file exists:
# -y overwrite
# -n do not overwrite.
TC_OVERWRITE="-n"
TC_SAMPLE=""
while getopts ":fhs" opt; do
case $opt in
f)
TC_OVERWRITE="-y"
;;
h)
_printhelp "$0"
exit 1
;;
s)
TC_SAMPLE="-ss 60 -t 600"
;;
?)
_printhelp "$0"
exit 1
;;
:)
echo "Missing argument."
echo "Use $0 -h for help."
exit 1
;;
esac
done
shift $(($OPTIND - 1))
if [ $# -eq 0 ]; then
tc_transcode .
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()
{
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_VIDEO_AUDIO_QUAL \
-c:s copy \
-map 0 "${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
## Argument is a regular file.
else
_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

View File

@ -1,23 +0,0 @@
## -*- mode:sh -*- #
alias pa='sudo pkg_add -r'
# alias pd='sudo pkg_delete'
alias pd='sudo pkg_deinstall -cd'
alias pi='pkg_info -RrcdsD -l "::"'
alias pil='pkg_info -L'
## Origin of file
alias piw='pkg_info -W'
## Search
alias pis='pkg_info -Qox'
# alias pvs='pkg_version -Is'
alias psr='pkg_search -r'
## Out-of-date packages.
alias pv='pkg_version -Il "<"'
## Port tree
alias mi='sudo make install'
alias mid='sudo make install distclean'
alias mc='sudo make config'

View File

@ -1,26 +0,0 @@
## -*- mode:sh -*- #
PACMAN_FRONTEND='pacman'
## Use of pacman-color
if [ -e "/usr/bin/pacman-color" ]; then
PACMAN_FRONTEND='pacman-color'
if [ "zsh" = "$SHELL_CURRENT" ]; then
compdef _pacman pacman-color
elif [ "bash" = "$SHELL_CURRENT" ]; then
complete -o default -o nospace -F _pacman pacman-color
fi
fi
## The eval trick lets us define the alias after the variable has been expanded.
## Bash will not auto-complete aliases.
eval 'alias pc="sudo $PACMAN_FRONTEND -Sc"'
eval 'alias pi="sudo $PACMAN_FRONTEND -S --needed"'
eval 'alias pqi="$PACMAN_FRONTEND -Qi"'
eval 'alias pqo="$PACMAN_FRONTEND -Qo"'
eval 'alias pqs="$PACMAN_FRONTEND -Qs"'
eval 'alias pr="sudo $PACMAN_FRONTEND -Rs"'
eval 'alias psi="$PACMAN_FRONTEND -Si"'
eval 'alias pss="$PACMAN_FRONTEND -Ss"'
eval 'alias pu="sudo $PACMAN_FRONTEND -Syu"'

View File

@ -4,10 +4,6 @@
## Date 2013-01-04
################################################################################
##==============================================================================
## General
##==============================================================================
## Warning: if this does not work if you change shell without relogging, use
## 'source .<shell>rc' instead.
@ -21,6 +17,7 @@ if [ "zsh" = "$SHELL_CURRENT" ]; then
fi
##==============================================================================
## General
##==============================================================================
## 'ls' redefinition
@ -94,15 +91,6 @@ alias xmorphzi='xrandr --output $(xrandr | grep "\<connected\>" | cut -f1 -d" ")
alias xres='xrandr -s $(xrandr | awk '"'"'/^ / {print $1;exit}'"'"')'
##==============================================================================
## Emacs
##==============================================================================
# See .homeinit
if [ -f /bin/em ]; then
alias ema='emacs -q -l ~/.emacs-light'
alias emacs-reload="emacsclient -e '(kill-emacs)' >/dev/null 2>&1; emacs --daemon"
fi
##==============================================================================
## Zsh power aliases
##==============================================================================
@ -117,15 +105,71 @@ fi
# fi
##==============================================================================
## Emacs
##==============================================================================
# See .homeinit
if [ -f /bin/em ]; then
alias ema='emacs -q -l ~/.emacs-light'
alias emacs-reload="emacsclient -e '(kill-emacs)' >/dev/null 2>&1; emacs --daemon"
fi
##==============================================================================
## Pacman aliases
##==============================================================================
[ -e "/usr/bin/pacman" ] && . ~/.shell.d/alias_pacman
if [ -e "/usr/bin/pacman" ]; then
PACMAN_FRONTEND='pacman'
## Use of pacman-color
if [ -e "/usr/bin/pacman-color" ]; then
PACMAN_FRONTEND='pacman-color'
if [ "zsh" = "$SHELL_CURRENT" ]; then
compdef _pacman pacman-color
elif [ "bash" = "$SHELL_CURRENT" ]; then
complete -o default -o nospace -F _pacman pacman-color
fi
## The eval trick lets us define the alias after the variable has been expanded.
## Bash will not auto-complete aliases.
eval 'alias pc="sudo $PACMAN_FRONTEND -Sc"'
eval 'alias pi="sudo $PACMAN_FRONTEND -S --needed"'
eval 'alias pqi="$PACMAN_FRONTEND -Qi"'
eval 'alias pqo="$PACMAN_FRONTEND -Qo"'
eval 'alias pqs="$PACMAN_FRONTEND -Qs"'
eval 'alias pr="sudo $PACMAN_FRONTEND -Rs"'
eval 'alias psi="$PACMAN_FRONTEND -Si"'
eval 'alias pss="$PACMAN_FRONTEND -Ss"'
eval 'alias pu="sudo $PACMAN_FRONTEND -Syu"'
fi
fi
##==============================================================================
## FreeBSD aliases
##==============================================================================
[ "$(uname)" = "FreeBSD" ] && . ~/.shell.d/alias_freebsd
if [ "$(uname)" = "FreeBSD" ]; then
alias pa='sudo pkg_add -r'
# alias pd='sudo pkg_delete'
alias pd='sudo pkg_deinstall -cd'
alias pi='pkg_info -RrcdsD -l "::"'
alias pil='pkg_info -L'
## Origin of file
alias piw='pkg_info -W'
## Search
alias pis='pkg_info -Qox'
# alias pvs='pkg_version -Is'
alias psr='pkg_search -r'
## Out-of-date packages.
alias pv='pkg_version -Il "<"'
## Port tree
alias mi='sudo make install'
alias mid='sudo make install distclean'
alias mc='sudo make config'
fi
##==============================================================================
## TeXlive aliases

View File

@ -965,8 +965,3 @@ if [ -d "/usr/local/texlive" ]; then
}
fi
##==============================================================================
## Transcoding functions
##==============================================================================
[ -n "$(command -v ffmpeg)" ] && . "${SHELL_DIR}/funs_transcode"

View File

@ -1,694 +0,0 @@
## -*- mode:sh -*- #
################################################################################
## Shell -- Trancode function set.
## Date 2013-01-27
################################################################################
## Tool list: ffmpeg, recode, titlecase.awk
## Support:
# ffmpeg -codecs
# ffmpeg -formats
## Useful guides
## x264: http://ffmpeg.org/trac/ffmpeg/wiki/x264EncodingGuide
## ID3 details: http://en.wikipedia.org/wiki/ID3
################################################################################
## Text
tc_text_scan ()
{
while read -r i; do
echo -n "# "
file "$i"
grep -m1 "\`" "$i"
grep -m1 "oe" "$i"
done <<EOF
$(find . -type f -size -50M -print)
EOF
}
## 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
while read -r i; 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 <<EOF
$(find . -type f -size -50M -print)
EOF
}
################################################################################
## Audio
## For the sake of simplicity we convert everything to OGG.
## You can easily set output folder to current folder with TC_AUDIO_DEST=".".
TC_AUDIO_DEST="/media/data1/Musics/"
## OGG quality ranges from -1 to 10.
## -q-1 45 kbit/s
## -q0 64 kbit/s
## -q1 80 kbit/s
## -q2 96 kbit/s
## -q3 112 kbit/s
## -q4 128 kbit/s
## -q5 160 kbit/s
## -q6 192 kbit/s
## -q7 224 kbit/s
## -q8 256 kbit/s
## -q9 320 kbit/s
## -q10 500 kbit/s
## Artists: we use same value for artist and album_artist.
## Genres: since this is not universal by nature, we do not put a genre in tags.
## Composer: not universal neither, we prefer ARTIST over COMPOSER, so COMPOSER will be empty.
tc_audio_scan()
{
local BUFFER
while read -r i; do
BUFFER="$(mediainfo "$i")"
if [ -n "$(echo "$BUFFER" | grep "Bit rate mode *: Constant")" ]; then
echo "$i : CBR"
fi
if [ -n "$(echo "$BUFFER" | grep "Cover *: Yes")" ]; then
echo "$i : Cover"
fi
if [ -n "$(echo "$BUFFER" | grep "Track name/Position *: 0+")" ]; then
echo "$i : Leading zeros"
fi
done <<EOF
$(find "." \( \
-iname '*.mp3' -o \
-iname '*.flac' -o \
-iname '*.wv' -o \
-iname '*.aac' -o \
-iname '*.wav' -o \
-iname '*.ape' -o \
-iname '*.mpc' \) )
EOF
}
## This will convert all tracks in current folder and subfolders.
tc_audio_batch()
{
while read -r i; do
tc_audio_transcode "$@" $i
done <<EOF
$(find "." \( \
-iname '*.mp3' -o \
-iname '*.flac' -o \
-iname '*.wv' -o \
-iname '*.aac' -o \
-iname '*.wav' -o \
-iname '*.ape' -o \
-iname '*.mpc' \) )
EOF
}
## This function is supposed to work on a per-album basis. Folders will not be
## accepted as argument. This function will work best if all tracks of a folder
## belong to the same album. Theres is no way to handle covers raliably, so you
## should leave the only covers you want to keep in the working folder.
## TODO: cover resolution check. Should be > 100x100. Above <1000x1000 should give a warning.
## TODO: extract cover from tags if checksum does not match any from current folder.
tc_audio_transcode()
{
_printhelp ()
{
cat <<EOF
Usage: $1 [OPTIONS] FILE
Options:
-p : preview (do not change file)
-s : skip encoding
Tags:
-a : artist
-b : bitrate
-d : date
-g : genre
-l : album
-n : track number
-t : title
You can use the following variables to refer to existing tags:
\$ALBUM
\$ALBUM_ARTIST
\$ARTIST
\$COMPOSER
\$DATE
\$TYER
\$GENRE
\$TRACK
Default output folder:
OUTPUT="\$TC_AUDIO_DEST/\$OUTPUT_ARTIST/\${OUTPUT_ALBUM:+\${OUTPUT_DATE:+\$OUTPUT_DATE - }\$OUTPUT_ALBUM/}"
Default output file:
OUTPUT_FILE="\$OUTPUT\$OUTPUT_ARTIST - \${OUTPUT_TRACK:+\$OUTPUT_TRACK - }\$OUTPUT_TITLE.\$OUTPUT_FORMAT"
Examples:
Set the 'artist' tag and reencode:
$1 -a 'Franz Lizst' file.mp3
Set 'artist' to be 'composer', and 'title' to be preceeded by 'artist', do not reencode:
$1 -s -a '\$COMPOSER' -t '\$ARTIST - \$TITLE' file.ogg
IMPORTANT: you *must* use single quotes when using variables.
EOF
}
## OPTIONS
local SKIP
SKIP=0
local PREVIEW
PREVIEW=0
## TAGS
local OUTPUT_ALBUM
OUTPUT_ALBUM='$ALBUM'
local OUTPUT_ARTIST
OUTPUT_ARTIST='$ARTIST'
local OUTPUT_DATE
OUTPUT_DATE='$DATE'
local OUTPUT_GENRE
OUTPUT_GENRE='$GENRE'
local OUTPUT_TITLE
OUTPUT_TITLE='$TITLE'
local OUTPUT_TRACK
OUTPUT_TRACK='$TRACK'
## PROPERTIES
local OUTPUT_BITRATE
OUTPUT_BITRATE=0
## Non-cli-option data. Modifying these imply modifications in code below.
local OUTPUT_FORMAT
OUTPUT_FORMAT="ogg"
local OGG_PARAM
OGG_PARAM="-c:a libvorbis -b:a ${OUTPUT_BITRATE}k"
## These ones are not cli-options either, but this could be easily changed.
local OUTPUT
local OUTPUT_FILE
OUTPUT='$TC_AUDIO_DEST/$OUTPUT_ARTIST/${OUTPUT_ALBUM:+${OUTPUT_DATE:+$OUTPUT_DATE - }$OUTPUT_ALBUM/}'
OUTPUT_FILE='$OUTPUT$OUTPUT_ARTIST - ${OUTPUT_PADDEDTRACK:+$OUTPUT_PADDEDTRACK - }$OUTPUT_TITLE'
while getopts ":a:b:d:g:l:n:t:hps" opt; do
case $opt in
a) OUTPUT_ARTIST=$OPTARG ;;
b) OUTPUT_BITRATE=$OPTARG ;;
d) OUTPUT_DATE=$OPTARG ;;
g) OUTPUT_GENRE=$OPTARG ;;
l) OUTPUT_ALBUM=$OPTARG ;;
n) OUTPUT_TRACK=$OPTARG ;;
t) OUTPUT_TITLE=$OPTARG ;;
h)
_printhelp "$0"
return 1
;;
p)
PREVIEW=1
;;
s)
SKIP=1
;;
?)
_printhelp "$0"
return 1
;;
:)
echo "Missing argument."
echo "Use $0 -h for help."
return 1
;;
esac
done
shift $(($OPTIND - 1))
if [ $# -eq 0 ]; then
_printhelp "$0"
return
fi
##================================================================================
## Get metadata.
local METADATA
local STREAM
STREAM=$(ffmpeg -i "$1" 2>&1)
METADATA=$(echo "$STREAM" | sed -n '/Metadata/ ! d; /Metada/{b cont}; :cont ; {n;p;b cont}')
STREAM=$(echo "$STREAM" | grep "Stream")
if [ -z "$STREAM" ]; then
echo "Non-audio file."
return
fi
## We get format from extension, because codec is not reliable either.
local FORMAT
FORMAT="${1##*.}"
## CODEC is unused for now.
local CODEC
CODEC=$(echo "$STREAM" | sed -n '/Audio:/ {s/.*Audio: \([^,]*\),.*/\1/;p}')
local BITRATE
BITRATE=$(echo "$STREAM" | sed -n '/kb\/s/ {s/.*, \(.*\) kb\/s/\1/;p}')
if [ -z "$FORMAT" ]; then
echo "ERROR: non-audio file."
return
fi
_metadata_filter()
{
echo "$METADATA" | grep -i "\<$1\>" | sed 's/[^:]* : //g'
}
local TITLE
TITLE=$(_metadata_filter "title")
local ARTIST
ARTIST=$(_metadata_filter "artist")
local ALBUM
ALBUM=$(_metadata_filter "album")
local ALBUM_ARTIST
ALBUM_ARTIST=$(_metadata_filter "album_artist")
local COMPOSER
COMPOSER=$(_metadata_filter "composer")
local DISC
DISC=$(_metadata_filter "disc")
local GENRE
GENRE=$(_metadata_filter "genre")
local TRACK
TRACK=$(_metadata_filter "track")
local DATE
DATE=$(_metadata_filter "date")
local TYER
TYER=$(_metadata_filter "TYER")
##================================================================================
## OUTPUT variables.
_string_cleanser()
{
## We use the AWK script to set title case. The script contains
## exceptions that can be configured. We fix some chars with sed.
# => '
# : => -
# / => -
awk -f "$HOME/.shell.d/titlecase.awk" \
<(echo "$@" | sed -n -e "s//'/g ; s/ *: */ - /g ; s| */ *| - |g; p; q")
}
OUTPUT_TITLE=$(eval _string_cleanser $OUTPUT_TITLE)
OUTPUT_TITLE="${OUTPUT_TITLE:-Unknown Title}"
## We use album artist if artist is empty.
OUTPUT_ARTIST=$(eval _string_cleanser $OUTPUT_ARTIST)
[ -z "$OUTPUT_ARTIST" ] && [ -n "$ALBUM_ARTIST" ] && OUTPUT_ARTIST="$ALBUM_ARTIST"
OUTPUT_ARTIST="${OUTPUT_ARTIST:-Unknown Artist}"
OUTPUT_ALBUM=$(eval _string_cleanser $OUTPUT_ALBUM)
[ -z "$OUTPUT_ALBUM" ] && echo "${#OUTPUT_ALBUM}${OUTPUT_ALBUM}"
## We put genre in lower case and underscore to ease matching. If it
## matches, we use the Title Case match. If it does not, we set it to empty.
OUTPUT_GENRE=$(eval _string_cleanser $OUTPUT_GENRE | tr '[:upper:] ' '[:lower:]_')
case $OUTPUT_GENRE in
ost) OUTPUT_GENRE="Soundtrack" ;;
soundtrack) OUTPUT_GENRE="Soundtrack";;
original_soundtrack) OUTPUT_GENRE="Soundtrack";;
classical) OUTPUT_GENRE="Classical";;
classics) OUTPUT_GENRE="Classical";;
classic) OUTPUT_GENRE="Classical";;
*) OUTPUT_GENRE="";;
esac
## We remove the track count if any, we suppress leading zeros.
OUTPUT_TRACK=$(eval _string_cleanser $OUTPUT_TRACK | sed -e 's/^0*//' -e 's|/.*||')
## If DATE is not a year, we use TYER if it is a year.
OUTPUT_DATE=$(eval _string_cleanser $OUTPUT_DATE)
local TYER_REG=$(echo "$TYER" | sed -n 's/.*\([[:digit:]]\{4\}\).*/\1/p')
if [ ${#DATE} -ne 4 ] && [ ${#TYER_REG} -eq 4 ]; then
OUTPUT_DATE="$TYER_REG"
fi
## QUALITY
## If bitrate argumument is not provided, we use BITRATE value.
[ $OUTPUT_BITRATE -eq 0 ] && OUTPUT_BITRATE=${BITRATE}
## TODO: test if table is useful at all.
# if [ $OUTPUT_BITRATE -eq 0 ]; then
# [ $BITRATE -le 45 ] && OUTPUT_BITRATE=45k
# [ $BITRATE -gt 45 ] && OUTPUT_BITRATE=64k
# [ $BITRATE -gt 64 ] && OUTPUT_BITRATE=80k
# [ $BITRATE -gt 80 ] && OUTPUT_BITRATE=96k
# [ $BITRATE -gt 96 ] && OUTPUT_BITRATE=112k
# [ $BITRATE -gt 112 ] && OUTPUT_BITRATE=128k
# [ $BITRATE -gt 128 ] && OUTPUT_BITRATE=160k
# [ $BITRATE -gt 160 ] && OUTPUT_BITRATE=192k
# [ $BITRATE -gt 192 ] && OUTPUT_BITRATE=224k
# [ $BITRATE -gt 224 ] && OUTPUT_BITRATE=256k
# [ $BITRATE -gt 256 ] && OUTPUT_BITRATE=320k
# [ $BITRATE -gt 320 ] && OUTPUT_BITRATE=500k
# fi
## Only reencode if not in OGG and if SKIP not set.
OGG_PARAM="-c:a libvorbis -b:a ${OUTPUT_BITRATE}k"
[ $SKIP -ne 0 ] && OGG_PARAM="-c:a copy" && OUTPUT_FORMAT="$FORMAT"
[ "$FORMAT" = "ogg" ] && OGG_PARAM="-c:a copy"
## Make sure track number has two digits for file name only.
local OUTPUT_PADDEDTRACK
OUTPUT_PADDEDTRACK=$OUTPUT_TRACK
if [ -n "$OUTPUT_PADDEDTRACK" ]; then
[ ${OUTPUT_PADDEDTRACK} -lt 10 ] && OUTPUT_PADDEDTRACK="0$OUTPUT_PADDEDTRACK"
fi
OUTPUT=$(eval echo $OUTPUT)
OUTPUT_FILE=$(eval echo $OUTPUT_FILE)
## IF file exist, we append a uniq timestamp to the name.
[ -e "${OUTPUT_FILE}.$OUTPUT_FORMAT" ] && OUTPUT_FILE="$OUTPUT_FILE-$(date '+%F-%H%M%S')"
##==============================================================================
## PREVIEW
echo "==> BEFORE"
echo "ALBUM [$ALBUM]"
echo "ALBUM_ARTIST [$ALBUM_ARTIST]"
echo "ARTIST [$ARTIST]"
echo "BITRATE [$BITRATE]"
echo "COMPOSER [$COMPOSER]"
echo "DATE [$DATE]"
echo "DISC [$DISC]"
echo "FORMAT [$FORMAT]"
echo "GENRE [$GENRE]"
echo "TITLE [$TITLE]"
echo "TRACK [$TRACK]"
echo "TYER [$TYER]"
echo
echo "==> AFTER"
echo "ALBUM [$OUTPUT_ALBUM]"
echo "ARTIST [$OUTPUT_ARTIST]"
echo "BITRATE [$OUTPUT_BITRATE]"
echo "DATE [$OUTPUT_DATE]"
echo "FORMAT [$OUTPUT_FORMAT]"
echo "GENRE [$OUTPUT_GENRE]"
echo "TITLE [$OUTPUT_TITLE]"
echo "TRACK [$OUTPUT_TRACK]"
echo
echo "==> OUTPUT"
echo "[$OUTPUT_FILE.$OUTPUT_FORMAT]"
# echo "[$OGG_PARAM]"
echo
[ $PREVIEW -ne 0 ] && return
##==============================================================================
## RUN PROCESS
## Make sure directory exists.
mkdir -p "$OUTPUT"
if [ $? -ne 0 ]; then
echo "ERROR: could not create output folder"
return
fi
## COVER
## We copy cover only if it does not already exist.
local OUTPUT_COVER
local COVER_COUNTER
local OUTPUT_COVERFILE
while read -r i; do
OUTPUT_COVER="$OUTPUT/${OUTPUT_ALBUM:+$OUTPUT_ALBUM - }Cover"
OUTPUT_COVERFILE="$OUTPUT_COVER.${i##*.}"
COVER_COUNTER=1
## Same cover is already in target folder.
if [ -e "$OUTPUT_COVERFILE" ] && \
[ "$(sha1sum $OUTPUT_COVERFILE | cut -f1 -d' ')" = "$(sha1sum $i | cut -f1 -d' ')" ]; then
continue
fi
## Different cover with same name is in target folder. We append a number.
while [ -e "$OUTPUT_COVERFILE" ] && \
[ ! "$(sha1sum $OUTPUT_COVERFILE | cut -f1 -d' ')" = "$(sha1sum $i | cut -f1 -d' ')" ]; do
OUTPUT_COVERFILE="${OUTPUT_COVER} $COVER_COUNTER.${i##*.}"
COVER_COUNTER=$(($COVER_COUNTER+1))
done
echo "==> COVER"
cp -nv "$i" "$OUTPUT_COVERFILE"
echo
done <<EOF
$(find "." \( -iname '*.png' -o -iname '*.jpg' \) )
EOF
## Zsh compatibility. We need it otherwise word splitting of parameter like
## OGG_PARAM will not work.
local STATUS
STATUS="$(set -o | grep 'shwordsplit' | awk '{print $2}')"
[ "$STATUS" = "off" ] && set -o shwordsplit
## TAG/RECODE
ffmpeg -i "$1" $OGG_PARAM \
-metadata title="$OUTPUT_TITLE" \
-metadata artist="$OUTPUT_ARTIST" \
-metadata track="$OUTPUT_TRACK" \
-metadata date="$OUTPUT_DATE" \
-metadata album="$OUTPUT_ALBUM" \
-metadata album_artist="$OUTPUT_ARTIST" \
-metadata genre="$OUTPUT_GENRE" \
-metadata composer="" \
-metadata TYER="" \
-metadata disc="" \
"$OUTPUT_FILE.$OUTPUT_FORMAT"
## Restore Zsh previous options. This will not turn off shwordsplit if it
## was on before calling the function.
[ "$STATUS" = "off" ] && set +o shwordsplit
}
################################################################################
## 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_VIDEO_AUDIO_QUAL=192k
## 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_video_demux_audio()
{
ffmpeg -i "$1" -vn -sn -c:a copy -map 0:1 "$2"
}
tc_video_audio2ogg()
{
echo "================================================================================"
ffmpeg -threads 4 -i "$1" -vn -c:a libvorbis -b:a $TC_VIDEO_AUDIO_QUAL "${1%.*}-$(date '+%F-%H%M%S').ogg"
}
## TODO: separate functions.
## tc_video_batch
## tc_video_transcode
tc_video_transcode()
{
_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.
-f: Overwrite existing file if any.
-h: Display this help.
-s: Sample of ten minutes.
EOF
}
## 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"
;;
?)
_printhelp "$0"
return 1
;;
:)
echo "Missing argument."
echo "Use $0 -h for help."
return 1
;;
esac
done
shift $(($OPTIND - 1))
if [ $# -eq 0 ]; then
tc_transcode .
return
fi
## Zsh compatibility. We need it otherwise word splitting of parameter like
## TC_SAMPLE will not work.
local STATUS
STATUS="$(set -o | grep 'shwordsplit' | awk '{print $2}')"
[ "$STATUS" = "off" ] && set -o shwordsplit
_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_VIDEO_AUDIO_QUAL \
-c:s copy \
-map 0 "${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
## Argument is a regular file.
else
_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
}
################################################################################
## 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