diff --git a/.scripts/tc-audio-batch b/.scripts/tc-audio-batch new file mode 100755 index 00000000..e117d8f7 --- /dev/null +++ b/.scripts/tc-audio-batch @@ -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 < 100x100. Above <1000x1000 should give a warning. +## TODO: extract cover from tags if checksum does not match any from current folder. + +_printhelp () +{ + cat <&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 < temp.srt + fi + + if [ -n "$(echo $CODING | grep 'CRLF')" ]; then + echo "CRLF: [$i]" + sed -i 's/\r//g' "$i" + fi + +done <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 "\" | 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 diff --git a/.shell.d/funs_rc b/.shell.d/funs_rc index 5b45b046..f5667ecb 100644 --- a/.shell.d/funs_rc +++ b/.shell.d/funs_rc @@ -965,8 +965,3 @@ if [ -d "/usr/local/texlive" ]; then } fi -##============================================================================== -## Transcoding functions -##============================================================================== - -[ -n "$(command -v ffmpeg)" ] && . "${SHELL_DIR}/funs_transcode" diff --git a/.shell.d/funs_transcode b/.shell.d/funs_transcode deleted file mode 100644 index a88f4cf4..00000000 --- a/.shell.d/funs_transcode +++ /dev/null @@ -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 < temp.srt - fi - - if [ -n "$(echo $CODING | grep 'CRLF')" ]; then - echo "CRLF: [$i]" - sed -i 's/\r//g' "$i" - fi - - done < 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 <&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 <