Shell: audio transcoder with tag parameters.

master
Pierre Neidhardt 2013-01-27 16:37:22 +01:00
parent 5097953f76
commit 349eea6ea6
1 changed files with 239 additions and 87 deletions

View File

@ -80,11 +80,7 @@ tc_text_2utf8 ()
## 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. If TC_AUDIO_QUAL is 0, bitrate will be set
## automatically according to the source.
TC_AUDIO_QUAL=0
## OGG values.
## OGG quality ranges from -1 to 10.
## -q-1 45 kbit/s
## -q0 64 kbit/s
## -q1 80 kbit/s
@ -99,11 +95,10 @@ TC_AUDIO_QUAL=0
## -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.
## Genres: since this is not universal by nature, we do not put a genre in tags,
## except for Classical and Soundtrack.
TC_AUDIO_GENRE=""
## TODO: implement.
## Check for
# MP3 CBR
# In-tag Covers
@ -113,17 +108,9 @@ tc_audio_scan()
echo "void"
}
## TEST: move png,jpg and name $ALBUM - Cover.$EXT. if multiple png,jpg, append counter. TEST.
## TEST: tr some chars like ´ to '. TEST.
## TEST: remove useless tags. TEST.
## TEST: dynamic quality. If aac or OGG, do not reencode. If FLAC or WavPack, reencode -q9. TEST.
## TEST: remove cover from tags. TEST.
## TEST: case checking. handle roman numerals. Handle initials. Handle exception list. TEST.
## TEST: if dest exist, append date.
## TODO: Empty composer field.
## 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.
## TODO: Empty composer field.
## TODO: tag parameters.
# -a artist
@ -141,6 +128,125 @@ tc_audio_scan()
## should leave the only covers you want to keep in the working folder.
tc_audio_transcode()
{
_printhelp ()
{
cat <<EOF
Usage: $0 [OPTIONS] FILE
Options:
-p : preview (do not change file)
-s : skip encoding
Tags:
-a : artist
-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:
\$TC_AUDIO_DEST/\$ARTIST/{{\$YEAR - }\$ALBUM/}\$ARTIST - {\$TRACK - }\$TITLE.\$OUTPUT_FORMAT
Braces mean it is conditional.
Examples:
Set the 'artist' tag:
$0 -a 'Franz Lizst' file.ogg
Set 'artist' to be 'composer', and 'title' to be preceeded by 'artist'.
$0 -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=''
local OUTPUT_TITLE
OUTPUT_TITLE='$TITLE'
local OUTPUT_TRACK
OUTPUT_TRACK='$TRACK'
## PROPERTIES
local OUTPUT_FORMAT
OUTPUT_FORMAT="ogg"
local OUTPUT_BITRATE
local OUTPUT_FILE
local OGG_PARAM
OGG_PARAM="-c:a libvorbis -b:a ${OUTPUT_BITRATE}k"
while getopts ":a:d:g:l:n:t:hps" opt; do
case $opt in
a) OUTPUT_ARTIST=$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
@ -173,12 +279,8 @@ tc_audio_transcode()
local TITLE
TITLE=$(_metadata_filter "title")
[ -z "$TITLE" ] && TITLE="Unknown"
local ARTIST
ARTIST=$(_metadata_filter "artist")
[ -z "$ARTIST" ] && ARTIST="Unknown"
local ALBUM
ALBUM=$(_metadata_filter "album")
local ALBUM_ARTIST
@ -190,41 +292,117 @@ tc_audio_transcode()
local GENRE
GENRE=""
## We remove the track count if any
local TRACK
TRACK=$(_metadata_filter "track" | sed -e 's/^0*//' -e 's|/.*||')
local DATE
DATE=$(_metadata_filter "date")
local TYER
TYER=$(_metadata_filter "TYER" | sed -n 's/.*\([[:digit:]]\{4\}\).*/\1/p')
##================================================================================
## OUTPUT_* variables.
## If DATE is not a year, we use TYER if it is a year.
if [ ${#DATE} -ne 4 ] && [ ${#TYER} -eq 4 ]; then
DATE="$TYER"
OUTPUT_DATE="$TYER"
fi
[ -z "$TITLE" ] && OUTPUT_TITLE="Unknown"
[ -z "$ARTIST" ] && OUTPUT_ARTIST="Unknown"
eval OUTPUT_ARTIST=$OUTPUT_ARTIST
eval OUTPUT_ALBUM=$OUTPUT_ALBUM
eval OUTPUT_TITLE=$OUTPUT_TITLE
eval OUTPUT_GENRE=$OUTPUT_GENRE
eval OUTPUT_TRACK=$OUTPUT_TRACK
eval OUTPUT_DATE=$OUTPUT_DATE
## Only reencode if not in OGG and if SKIP not set..
[ $SKIP -ne 0 ] && OGG_PARAM="" && OUTPUT_FORMAT="$FORMAT"
[ "$FORMAT" = "ogg" ] && OGG_PARAM=""
## TODO: test w/o qual to see default param.
## QUALITY
eval OUTPUT_BITRATE=${BITRATE}
# 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
## SET OUTPUT{,_FILE,_COVER} according to other OUTPUT_* variables.
local OUTPUT
local OUTPUT_FILE
OUTPUT="$TC_AUDIO_DEST/$OUTPUT_ARTIST/"
if [ -n "$OUTPUT_ALBUM" ]; then
[ -n "$OUTPUT_DATE" ] && OUTPUT="$OUTPUT$OUTPUT_DATE - "
OUTPUT="$OUTPUT$OUTPUT_ALBUM"
fi
OUTPUT_FILE="$OUTPUT/$OUTPUT_ARTIST"
if [ -n "$OUTPUT_TRACK" ]; then
## Make sure track number has two digits.
if [ ${OUTPUT_TRACK} -lt 10 ]; then
OUTPUT_FILE="$OUTPUT_FILE - 0$OUTPUT_TRACK"
else
OUTPUT_FILE="$OUTPUT_FILE - $OUTPUT_TRACK"
fi
fi
OUTPUT_FILE="$OUTPUT_FILE - $OUTPUT_TITLE"
## 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 [$OUTPUT_FILE]"
## DEBUG only.
# echo "[$ALBUM]"
# echo "[$ALBUM_ARTIST]"
# echo "[$ARTIST]"
# echo "[$BITRATE]"
# echo "[$COMPOSER]"
# echo "[$DATE]"
# echo "[$DISC]"
# echo "[$FORMAT]"
# echo "[$GENRE]"
# echo "[$TITLE]"
# echo "[$TRACK]"
# echo "[$TYER]"
# echo "FORMAT: [$FORMAT]"
# echo "BITRATE: [$TC_AUDIO_QUAL]"
# echo "OUTPUT: [$OUTPUT_TRACK]"
## OUTPUT
local OUTPUT
local OUTPUT_TRACK
local OUTPUT_COVER
OUTPUT="$TC_AUDIO_DEST/$ARTIST/"
if [ -n "$ALBUM" ]; then
[ -n "$DATE" ] && OUTPUT="$OUTPUT$DATE - "
OUTPUT="$OUTPUT$ALBUM"
fi
[ $PREVIEW -ne 0 ] && return
##==============================================================================
## RUN PROCESS
## Make sure directory exists.
mkdir -p "$OUTPUT"
@ -233,20 +411,9 @@ tc_audio_transcode()
return
fi
OUTPUT_TRACK="$OUTPUT/$ARTIST"
if [ -n "$TRACK" ]; then
## Make sure track number has two digits.
if [ ${TRACK} -lt 10 ]; then
OUTPUT_TRACK="$OUTPUT_TRACK - 0$TRACK"
else
OUTPUT_TRACK="$OUTPUT_TRACK - $TRACK"
fi
fi
OUTPUT_TRACK="$OUTPUT_TRACK - $TITLE"
## If file exist, we append a uniq timestamp to the name.
[ -e "${OUTPUT_TRACK}.ogg" ] && OUTPUT_TRACK="$OUTPUT_TRACK-$(date '+%F-%H%M%S')"
## COVER
local OUTPUT_COVER
local COVER_COUNTER
OUTPUT_COVER="$OUTPUT/"
[ -n "$ALBUM" ] && OUTPUT_COVER="$OUTPUT_COVER$ALBUM - "
@ -272,38 +439,20 @@ tc_audio_transcode()
fi
done
## TODO: test w/o qual to see default param.
## QUALITY
if [ $TC_AUDIO_QUAL -eq 0 ]; then
[ $BITRATE -le 45 ] && TC_AUDIO_QUAL=45k
[ $BITRATE -gt 45 ] && TC_AUDIO_QUAL=64k
[ $BITRATE -gt 64 ] && TC_AUDIO_QUAL=80k
[ $BITRATE -gt 80 ] && TC_AUDIO_QUAL=96k
[ $BITRATE -gt 96 ] && TC_AUDIO_QUAL=112k
[ $BITRATE -gt 112 ] && TC_AUDIO_QUAL=128k
[ $BITRATE -gt 128 ] && TC_AUDIO_QUAL=160k
[ $BITRATE -gt 160 ] && TC_AUDIO_QUAL=192k
[ $BITRATE -gt 192 ] && TC_AUDIO_QUAL=224k
[ $BITRATE -gt 224 ] && TC_AUDIO_QUAL=256k
[ $BITRATE -gt 256 ] && TC_AUDIO_QUAL=320k
[ $BITRATE -gt 320 ] && TC_AUDIO_QUAL=500k
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
## DEBUG only.
# echo "FORMAT: [$FORMAT]"
# echo "BITRATE: [$TC_AUDIO_QUAL]"
# echo "OUTPUT: [$OUTPUT_TRACK]"
## TAG/RECODE
ffmpeg -i "$1" $OGG_PARAM -metadata \
title="$OUTPUT_TITLE",artist="$OUTPUT_ARTIST",track="$OUTPUT_TRACK",date="$OUTPUT_DATE",album="$OUTPUT_ALBUM",album_artist="$OUTPUT_ARTIST",genre="$OUTPUT_GENRE",composer="",TYER="",disc="" \
"$OUTPUT_FILE.$OUTPUT_FORMAT"
## TODO: set -o shwordsplit
## Only reencode if not in OGG.
local OGG_PARAM
OGG_PARAM="-c:a libvorbis -b:a $TC_AUDIO_QUAL"
[ "$FORMAT" = "ogg" ] && OGG_PARAM=""
# ffmpeg -i "$1" $OGG_PARAM \
ffmpeg -i "$1" -c:a libvorbis -b:a $TC_AUDIO_QUAL -metadata \
title="$TITLE",artist="$ARTIST",track="$TRACK",date="$DATE",album="$ALBUM",album_artist="$ARTIST",genre="$GENRE",composer="$COMPOSER" \
"$OUTPUT_TRACK.ogg"
## Restore Zsh previous options. This will not turn off shwordsplit if it
## was on before calling the function.
[ "$STATUS" = "off" ] && set +o shwordsplit
}
@ -355,6 +504,9 @@ tc_video_audio2ogg()
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()