Merge pull request #2 from upuv/tiddy

Tiddy merge Master
This commit is contained in:
upuv 2018-05-19 23:47:30 +10:00 committed by GitHub
commit c3b53b6e56
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 53 additions and 119 deletions

2
.gitignore vendored
View File

@ -1,2 +1,4 @@
ACTIVATION ACTIVATION
.authcode .authcode
*aax
Audiobook/*

108
AAXtoM4A
View File

@ -1,108 +0,0 @@
#!/usr/bin/env bash
set -o errexit -o noclobber -o nounset -o pipefail
codec=copy
extension=m4a
mode=chaptered
GREP=$(grep --version | grep -q GNU && echo "grep" || echo "ggrep")
if ! [[ $(type -P "$GREP") ]]; then
echo "$GREP (GNU grep) is not in your PATH"
echo "Without it, this script will break."
echo "On macOS, you may want to try: brew install grep"
exit 1
fi
if [ "$#" -eq 0 ]; then
echo "Usage: bash AAXtoM4A [--single] AUTHCODE {FILES}"
exit 1
fi
if [[ "$1" == '--single' ]]
then
mode=single
shift
fi
if [ ! -f .authcode ]; then
auth_code=$1
shift
else
auth_code=`head -1 .authcode`
fi
debug() {
echo "$(date "+%F %T%z") ${1}"
}
trap 'rm -r -f "${working_directory}"' EXIT
working_directory=`mktemp -d 2>/dev/null || mktemp -d -t 'mytmpdir'`
metadata_file="${working_directory}/metadata.txt"
save_metadata() {
local media_file
media_file="$1"
ffprobe -i "$media_file" 2> "$metadata_file"
}
get_metadata_value() {
local key
key="$1"
normalize_whitespace "$($GREP --max-count=1 --only-matching "${key} *: .*" "$metadata_file" | cut -d : -f 2- | sed -e 's#/##g;s/ (Unabridged)//' | tr -s '[:blank:]' ' ')"
}
get_bitrate() {
get_metadata_value bitrate | $GREP --only-matching '[0-9]\+'
}
normalize_whitespace() {
echo $*
}
for path
do
debug "Decoding ${path} with auth code ${auth_code}..."
save_metadata "${path}"
genre=$(get_metadata_value genre)
artist=$(get_metadata_value artist)
title=$(get_metadata_value title)
output_directory="$(dirname "${path}")/${genre}/${artist}/${title}"
mkdir -p "${output_directory}"
full_file_path="${output_directory}/${title}.${extension}"
</dev/null ffmpeg -loglevel error -stats -activation_bytes "${auth_code}" -i "${path}" -vn -codec:a "${codec}" -ab "$(get_bitrate)k" -map_metadata -1 -metadata title="${title}" -metadata artist="${artist}" -metadata album_artist="$(get_metadata_value album_artist)" -metadata album="$(get_metadata_value album)" -metadata date="$(get_metadata_value date)" -metadata track="1/1" -metadata genre="${genre}" -metadata copyright="$(get_metadata_value copyright)" "${full_file_path}"
debug "Created ${full_file_path}."
cover_path="${output_directory}/cover.jpg"
debug "Extracting cover into ${cover_path}..."
</dev/null ffmpeg -loglevel error -activation_bytes "${auth_code}" -i "${path}" -an -codec:v copy "${cover_path}"
if [ "${mode}" == "chaptered" ]; then
chaptercount=$($GREP -Pc "Chapter.*start.*end" $metadata_file)
debug "Extracting ${chaptercount} chapter files from ${full_file_path}..."
chapternum=1
while read -r -u9 first _ _ start _ end
do
if [[ "${first}" = "Chapter" ]]
then
read -r -u9 _
read -r -u9 _ _ chapter
chapter_title="${title} - $(printf %0${#chaptercount}d $chapternum) ${chapter}"
chapter_file="${output_directory}/${chapter_title}.${extension}"
</dev/null ffmpeg -loglevel error -stats -i "${full_file_path}" -i "${cover_path}" -ss "${start%?}" -to "${end}" -vn -codec:a copy -map 0:0 -map 1:0 -id3v2_version 3 \
-metadata:s:v title="Album cover" -metadata:s:v comment="Cover (Front)" -metadata track="${chapternum}" -metadata title="${chapter_title}" \
"${chapter_file}"
chapternum=$((chapternum + 1 ))
fi
done 9< "$metadata_file"
rm "${full_file_path}"
debug "Done creating chapters. Chaptered files contained in ${output_directory}."
fi
debug "Done."
rm "${metadata_file}"
done

View File

@ -9,7 +9,13 @@ extension=mp3
mode=chaptered mode=chaptered
auth_code= auth_code=
targetdir= targetdir=
DEBUG=0
# -----
# Code tip Do not have any script above this point that calls a function or a binary. If you do
# the $1 will no longer be a ARGV element. So you should only do basic variable setting above here.
#
# Process the command line options. This allows for un-ordered options. Sorta like a getops style
while true; do while true; do
case "$1" in case "$1" in
-f | --flac ) codec=flac; extension=flac; mode=single ; shift ;; -f | --flac ) codec=flac; extension=flac; mode=single ; shift ;;
@ -18,13 +24,14 @@ while true; do
-s | --single ) mode=single; shift ;; -s | --single ) mode=single; shift ;;
-t | --target_dir ) targetdir="$2"; shift 2 ;; -t | --target_dir ) targetdir="$2"; shift 2 ;;
-A | --authcode ) auth_code="$2"; shift 2 ;; -A | --authcode ) auth_code="$2"; shift 2 ;;
-d | --debug ) DEBUG=1; shift ;; # Not so secret flag for debug output. to use in code [ $DEBUG == 1 ] && sample=2 -d | --debug ) DEBUG=1; shift ;;
-h | --help ) printf "$usage" $0 ; exit ;; -h | --help ) printf "$usage" $0 ; exit ;;
-- ) shift; break ;; -- ) shift; break ;;
* ) break ;; * ) break ;;
esac esac
done done
# Empty argv means we have nothing to do so lets bark some help.
if [ "$#" -eq 0 ]; then if [ "$#" -eq 0 ]; then
printf "$usage" $0 printf "$usage" $0
exit 1 exit 1
@ -43,6 +50,7 @@ if ! [[ $(type -P "$GREP") ]]; then
exit 1 exit 1
fi fi
# -----
# Obtain the authcode from either the command line, local directory or home directory. # Obtain the authcode from either the command line, local directory or home directory.
if [ -z $auth_code ]; then if [ -z $auth_code ]; then
if [ -r .authcode ]; then if [ -r .authcode ]; then
@ -57,6 +65,7 @@ if [ -z $auth_code ]; then
exit 1 exit 1
fi fi
# -----
# Check the target dir for if set if it is writable # Check the target dir for if set if it is writable
if [[ ! -w "${targetdir}" || ! -d "${targetdir}" ]] ; then if [[ ! -w "${targetdir}" || ! -d "${targetdir}" ]] ; then
echo "ERROR Target Directory is not writable: \"$targetdir\"" echo "ERROR Target Directory is not writable: \"$targetdir\""
@ -67,7 +76,25 @@ fi
# ======================================================================== # ========================================================================
# Utility Functions # Utility Functions
# debug
debug() { debug() {
if [ $DEBUG == 1 ] ; then
echo "$(date "+%F %T%z") DEBUG ${1}"
fi
}
# debug dump contents of a file to STDOUT
debug_file() {
if [ $DEBUG == 1 ] ; then
echo "$(date "+%F %T%z") DEBUG"
echo "================================================================================"
cat "${1}"
echo "================================================================================"
fi
}
# log
log() {
echo "$(date "+%F %T%z") ${1}" echo "$(date "+%F %T%z") ${1}"
} }
@ -79,6 +106,8 @@ save_metadata() {
local media_file local media_file
media_file="$1" media_file="$1"
ffprobe -i "$media_file" 2> "$metadata_file" ffprobe -i "$media_file" 2> "$metadata_file"
debug "Metadata file $metadata_file"
debug_file "$metadata_file"
} }
get_metadata_value() { get_metadata_value() {
@ -99,7 +128,7 @@ normalize_whitespace() {
# Main Transcode Loop # Main Transcode Loop
for path for path
do do
debug "Decoding ${path} with auth code ${auth_code}..." log "Decoding ${path} with auth code ${auth_code}..."
# Check for Presense of Audiobook # Check for Presense of Audiobook
if [[ ! -r "${path}" ]] ; then if [[ ! -r "${path}" ]] ; then
@ -118,27 +147,35 @@ do
fi fi
mkdir -p "${output_directory}" mkdir -p "${output_directory}"
full_file_path="${output_directory}/${title}.${extension}" full_file_path="${output_directory}/${title}.${extension}"
bitrate="$(get_bitrate)k"
album_artist="$(get_metadata_value album_artist)"
album="$(get_metadata_value album)"
album_date="$(get_metadata_value date)"
copyright="$(get_metadata_value copyright)"
# Big long DEBUG output. Fully describes the settings used for transcoding. I could probably do this better.
debug "$(printf '\n%-18s: %s\n%-18s: %s\n%-18s: %s\n%-18s: %s\n%-18s: %s\n%-18s: %s\n%-18s: %s\n%-18s: %s\n%-18s: %s\n%-18s: %s\n%-18s: %s\n%-18s: %s\n%-18s: %s\n%-18s: %sn%-18s: %s' title "${title}" auth_code "${auth_code}" mode "${mode}" path "${path}" codec "${codec}" bitrate "${bitrate}" artist "${artist}" album_artist "${album_artist}" album "${album}" album_date "${album_date}" genre "${genre}" copyright "${copyright}" full_file_path "${full_file_path}" metadata_file "${metadata_file}" working_directory "${working_directory}" )"
# This is the primary transcode. All the heavy lifting is here. # This is the primary transcode. All the heavy lifting is here.
</dev/null ffmpeg -loglevel error -stats -activation_bytes "${auth_code}" -i "${path}" -vn -codec:a "${codec}" -ab "$(get_bitrate)k" -map_metadata -1 -metadata title="${title}" -metadata artist="${artist}" -metadata album_artist="$(get_metadata_value album_artist)" -metadata album="$(get_metadata_value album)" -metadata date="$(get_metadata_value date)" -metadata track="1/1" -metadata genre="${genre}" -metadata copyright="$(get_metadata_value copyright)" "${full_file_path}" </dev/null ffmpeg -loglevel error -stats -activation_bytes "${auth_code}" -i "${path}" -vn -codec:a "${codec}" -ab ${bitrate} -map_metadata -1 -metadata title="${title}" -metadata artist="${artist}" -metadata album_artist="${album_artist}" -metadata album="${album}" -metadata date="${album_date}" -metadata track="1/1" -metadata genre="${genre}" -metadata copyright="${copyright}" "${full_file_path}"
debug "Created ${full_file_path}." log "Created ${full_file_path}."
# Grab the cover art if available. # Grab the cover art if available.
cover_path="${output_directory}/cover.jpg" cover_path="${output_directory}/cover.jpg"
debug "Extracting cover into ${cover_path}..." log "Extracting cover into ${cover_path}..."
</dev/null ffmpeg -loglevel error -activation_bytes "${auth_code}" -i "${path}" -an -codec:v copy "${cover_path}" </dev/null ffmpeg -loglevel error -activation_bytes "${auth_code}" -i "${path}" -an -codec:v copy "${cover_path}"
# If we want multiple file we take the big mp3 and split it by chapter. # If we want multiple file we take the big mp3 and split it by chapter.
if [ "${mode}" == "chaptered" ]; then if [ "${mode}" == "chaptered" ]; then
# Playlist m3u support # Playlist m3u support
playlist_file="${output_directory}/${title}.m3u" playlist_file="${output_directory}/${title}.m3u"
debug "Creating PlayList ${title}.m3u" log "Creating PlayList ${title}.m3u"
echo '#EXTM3U' > "${playlist_file}" echo '#EXTM3U' > "${playlist_file}"
chaptercount=$($GREP -Pc "Chapter.*start.*end" $metadata_file) chaptercount=$($GREP -Pc "Chapter.*start.*end" $metadata_file)
debug "Extracting ${chaptercount} chapter files from ${full_file_path}..." log "Extracting ${chaptercount} chapter files from ${full_file_path}..."
chapternum=1 chapternum=1
while read -r -u9 first _ _ start _ end while read -r -u9 first _ _ start _ end
@ -158,6 +195,10 @@ do
id3_version_param="-id3v2_version 3" id3_version_param="-id3v2_version 3"
fi fi
# Big Long chapter debug I could probably do this better.
debug "$(printf '\n%-18s: %s\n%-18s: %s\n%-18s: %s\n%-18s: %s\n%-18s: %s\n%-18s: %s\n%-18s: %s' cover_path "${cover_path}" start "${start%?}" end "${end}" id3_version_param "${id3_version_param}" chapternum "${chapternum}" chapter_title "${chapter_title}" chapter_file "${chapter_file}" )"
# Extract chapter by time stamps start and finish of chapter.
</dev/null ffmpeg -loglevel error -stats -i "${full_file_path}" -i "${cover_path}" -ss "${start%?}" -to "${end}" -map 0:0 -map 1:0 -acodec copy ${id3_version_param} \ </dev/null ffmpeg -loglevel error -stats -i "${full_file_path}" -i "${cover_path}" -ss "${start%?}" -to "${end}" -map 0:0 -map 1:0 -acodec copy ${id3_version_param} \
-metadata:s:v title="Album cover" -metadata:s:v comment="Cover (Front)" -metadata track="${chapternum}" -metadata title="${chapter_title}" \ -metadata:s:v title="Album cover" -metadata:s:v comment="Cover (Front)" -metadata track="${chapternum}" -metadata title="${chapter_title}" \
"${chapter_file}" "${chapter_file}"
@ -169,9 +210,9 @@ do
fi fi
done 9< "$metadata_file" done 9< "$metadata_file"
rm "${full_file_path}" rm "${full_file_path}"
debug "Done creating chapters. Chaptered files contained in ${output_directory}." log "Done creating chapters. Chaptered files contained in ${output_directory}."
fi fi
debug "Done." log "Done. ${title}"
rm "${metadata_file}" rm "${metadata_file}"
done done

View File

@ -1,4 +1,4 @@
# AAXtoMP3 AAXtoM4A AAxtoM4B # AAXtoMP3 AAxtoM4B
The purpose of this software is to convert AAX files to common MP3, M4A and M4B formats The purpose of this software is to convert AAX files to common MP3, M4A and M4B formats
through a basic bash script frontend to FFMPEG. through a basic bash script frontend to FFMPEG.
@ -32,7 +32,6 @@ Thanks to kbabioch, this script has also been packaged in the [AUR](https://aur.
## Usage(s) ## Usage(s)
``` ```
bash AAXtoMP3 [-f|--flac] [-o|--opus] [-a|-aac] [-s|--single] [-A|--authcode <AUTHCODE>] [-o|--output_dir <PATH>] <AAX INPUT_FILES>... bash AAXtoMP3 [-f|--flac] [-o|--opus] [-a|-aac] [-s|--single] [-A|--authcode <AUTHCODE>] [-o|--output_dir <PATH>] <AAX INPUT_FILES>...
bash AAXtoM4A [AUTHCODE] <AAX INPUT_FILES>...
bash AAXtoM4B [AUTHCODE] <AAX INPUT_FILES>... bash AAXtoM4B [AUTHCODE] <AAX INPUT_FILES>...
``` ```