Merge pull request #151 from fabh2o/custom-output-folder

Custom naming scheme
This commit is contained in:
KrumpetPirate 2021-02-11 19:31:39 -05:00 committed by GitHub
commit 1e9c42aa83
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 102 additions and 35 deletions

View File

@ -5,13 +5,23 @@
# Command Line Options # Command Line Options
# Usage Synopsis. # Usage Synopsis.
usage=$'\nUsage: AAXtoMP3 [--flac] [--aac] [--opus ] [--single] [--level <COMPRESSIONLEVEL>]\n[--chaptered] [-e:mp3] [-e:m4a] [-e:m4b] [--authcode <AUTHCODE>] [--no-clobber]\n[--target_dir <PATH>] [--complete_dir <PATH>] [--validate]\n[--continue <CHAPTERNUMBER>] [--keep-author <N>] [--author <AUTHOR>] [--loglevel <LOGLEVEL>] {FILES}\n' usage=$'\nUsage: AAXtoMP3 [--flac] [--aac] [--opus ] [--single] [--level <COMPRESSIONLEVEL>]
[--chaptered] [-e:mp3] [-e:m4a] [-e:m4b] [--authcode <AUTHCODE>] [--no-clobber]
[--target_dir <PATH>] [--complete_dir <PATH>] [--validate] [--loglevel <LOGLEVEL>]
[--keep-author <N>] [--author <AUTHOR>] [--{dir,file,chapter}-naming-scheme <STRING>]
[--continue <CHAPTERNUMBER>] {FILES}\n'
codec=libmp3lame # Default encoder. codec=libmp3lame # Default encoder.
extension=mp3 # Default encoder extension. extension=mp3 # Default encoder extension.
level=-1 # Compression level. Can be given for mp3, flac and opus. -1 = default/not specified. level=-1 # Compression level. Can be given for mp3, flac and opus. -1 = default/not specified.
mode=chaptered # Multi file output mode=chaptered # Multi file output
auth_code= # Required to be set via file or option. auth_code= # Required to be set via file or option.
targetdir= # Optional output location. Note default is basedir of AAX file. targetdir= # Optional output location. Note default is basedir of AAX file.
dirNameScheme= # Custom directory naming scheme, default is $genre/$author/$title
customDNS=0
fileNameScheme= # Custom file naming scheme, default is $title
customFNS=0
chapterNameScheme= # Custom chapter naming scheme, default is '$title-$(printf %0${#chaptercount}d $chapternum) $chapter' (BookTitle-01 Chapter 1)
customCNS=0
completedir= # Optional location to move aax files once the decoding is complete. completedir= # Optional location to move aax files once the decoding is complete.
container=mp3 # Just in case we need to change the container. Used for M4A to M4B container=mp3 # Just in case we need to change the container. Used for M4A to M4B
VALIDATE=0 # Validate the input aax file(s) only. No Transcoding of files will occur VALIDATE=0 # Validate the input aax file(s) only. No Transcoding of files will occur
@ -47,6 +57,12 @@ while true; do
-e:m4b ) codec=copy; extension=m4b; mode=single; container=mp4; shift ;; -e:m4b ) codec=copy; extension=m4b; mode=single; container=mp4; shift ;;
# Change the working dir from AAX directory to what you choose. # Change the working dir from AAX directory to what you choose.
-t | --target_dir ) targetdir="$2"; shift 2 ;; -t | --target_dir ) targetdir="$2"; shift 2 ;;
# Use a custom directory naming scheme, with variables.
-D | --dir-naming-scheme ) dirNameScheme="$2"; customDNS=1; shift 2 ;;
# Use a custom file naming scheme, with variables.
-F | --file-naming-scheme ) fileNameScheme="$2"; customFNS=1; shift 2 ;;
# Use a custom chapter naming scheme, with variables.
--chapter-naming-scheme ) chapterNameScheme="$2"; customCNS=1; shift 2 ;;
# Move the AAX file to a new directory when decoding is complete. # Move the AAX file to a new directory when decoding is complete.
-C | --complete_dir ) completedir="$2"; shift 2 ;; -C | --complete_dir ) completedir="$2"; shift 2 ;;
# Authorization code associate with the AAX file(s) # Authorization code associate with the AAX file(s)
@ -474,16 +490,11 @@ do
fi fi
title=$(get_metadata_value title | $SED 's/'\:'/'-'/g' | $SED 's/- /-/g' | xargs -0) title=$(get_metadata_value title | $SED 's/'\:'/'-'/g' | $SED 's/- /-/g' | xargs -0)
title=${title:0:100} title=${title:0:100}
if [ "x${targetdir}" != "x" ] ; then
output_directory="${targetdir}/${genre}/${artist}/${title}"
else
output_directory="$(dirname "${aax_file}")/${genre}/${artist}/${title}"
fi
output_file="${output_directory}/${title}.${extension}"
bitrate="$(get_bitrate)k" bitrate="$(get_bitrate)k"
album="$(get_metadata_value album)" album="$(get_metadata_value album)"
album_date="$(get_metadata_value date)" album_date="$(get_metadata_value date)"
copyright="$(get_metadata_value copyright)" copyright="$(get_metadata_value copyright)"
# Get more tags with mediainfo # Get more tags with mediainfo
if [[ $(type -P mediainfo) ]]; then if [[ $(type -P mediainfo) ]]; then
narrator="$(get_metadata_value nrt)" narrator="$(get_metadata_value nrt)"
@ -495,6 +506,30 @@ do
publisher="" publisher=""
fi fi
# Define the output_directory
if [ "${customDNS}" == "1" ]; then
currentDirNameScheme="$(eval echo "${dirNameScheme}")"
else
# The Default
currentDirNameScheme="${genre}/${artist}/${title}"
fi
# If we defined a target directory, use it. Otherwise use the location of the AAX file
if [ "x${targetdir}" != "x" ] ; then
output_directory="${targetdir}/${currentDirNameScheme}/"
else
output_directory="$(dirname "${aax_file}")/${currentDirNameScheme}/"
fi
# Define the output_file
if [ "${customFNS}" == "1" ]; then
currentFileNameScheme="$(eval echo "${fileNameScheme}")"
else
# The Default
currentFileNameScheme="${title}"
fi
output_file="${output_directory}/${currentFileNameScheme}.${extension}"
if [[ "${noclobber}" = "1" ]] && [[ -d "${output_directory}" ]]; then if [[ "${noclobber}" = "1" ]] && [[ -d "${output_directory}" ]]; then
log "Noclobber enabled but directory '${output_directory}' exists. Exiting to avoid overwriting" log "Noclobber enabled but directory '${output_directory}' exists. Exiting to avoid overwriting"
exit 0 exit 0
@ -511,15 +546,16 @@ do
# Big long DEBUG output. Fully describes the settings used for transcoding. # Big long DEBUG output. Fully describes the settings used for transcoding.
# Note this is a long debug command. It's not critical to operation. It's purely for people debugging # Note this is a long debug command. It's not critical to operation. It's purely for people debugging
# and coders wanting to extend the script. # and coders wanting to extend the script.
debug_vars "Book and Variable values" title auth_code mode aax_file container codec bitrate artist album_artist album album_date genre copyright narrator description publisher output_file metadata_file working_directory debug_vars "Book and Variable values" title auth_code mode aax_file container codec bitrate artist album_artist album album_date genre copyright narrator description publisher currentDirNameScheme output_directory currentFileNameScheme output_file metadata_file working_directory
# Display the total length of the audiobook in format hh:mm:ss # Display the total length of the audiobook in format hh:mm:ss
# 10#$var force base-10 interpretation. By default it's base-8, so values like 08 or 09 are not octal numbers
total_length="$(ffprobe -v error -activation_bytes "${auth_code}" -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 ${aax_file} | cut -d . -f 1)" total_length="$(ffprobe -v error -activation_bytes "${auth_code}" -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 ${aax_file} | cut -d . -f 1)"
hours="$((total_length/3600))" hours="$((total_length/3600))"
if [ "$((hours<10))" = "1" ]; then hours="0$hours"; fi if [ "$((hours<10))" = "1" ]; then hours="0$hours"; fi
minutes="$((total_length/60-60*hours))" minutes="$((total_length/60-60*10#$hours))"
if [ "$((minutes<10))" = "1" ]; then minutes="0$minutes"; fi if [ "$((minutes<10))" = "1" ]; then minutes="0$minutes"; fi
seconds="$((total_length-3600*hours-60*minutes))" seconds="$((total_length-3600*10#$hours-60*10#$minutes))"
if [ "$((seconds<10))" = "1" ]; then seconds="0$seconds"; fi if [ "$((seconds<10))" = "1" ]; then seconds="0$seconds"; fi
log "Total length: $hours:$minutes:$seconds" log "Total length: $hours:$minutes:$seconds"
@ -576,10 +612,10 @@ do
# for more detail # for more detail
if [ "${mode}" == "chaptered" ]; then if [ "${mode}" == "chaptered" ]; then
# Playlist m3u support # Playlist m3u support
playlist_file="${output_directory}/${title}.m3u" playlist_file="${output_directory}/${currentFileNameScheme}.m3u"
if [ "${continue}" == "0" ]; then if [ "${continue}" == "0" ]; then
if [ "$((${loglevel} > 0))" == "1" ]; then if [ "$((${loglevel} > 0))" == "1" ]; then
log "Creating PlayList ${title}.m3u" log "Creating PlayList ${currentFileNameScheme}.m3u"
fi fi
echo '#EXTM3U' > "${playlist_file}" echo '#EXTM3U' > "${playlist_file}"
fi fi
@ -622,7 +658,13 @@ do
# The formatting of the chapters names and the file names. # The formatting of the chapters names and the file names.
# Chapter names are used in a few place. # Chapter names are used in a few place.
chapter_title="${title}-$(printf %0${#chaptercount}d $chapternum) ${chapter}" # Define the chapter_file
if [ "${customCNS}" == "1" ]; then
chapter_title="$(eval echo "${chapterNameScheme}")"
else
# The Default
chapter_title="${title}-$(printf %0${#chaptercount}d $chapternum) ${chapter}"
fi
chapter_file="${output_directory}/${chapter_title}.${extension}" chapter_file="${output_directory}/${chapter_title}.${extension}"
# Since the .aax file allready got converted we can use # Since the .aax file allready got converted we can use
@ -638,7 +680,7 @@ do
fi fi
# Big Long chapter debug # Big Long chapter debug
debug_vars "Chapter Variables:" cover_file chapter_start chapter_end chapternum chapter_title chapter_file debug_vars "Chapter Variables:" cover_file chapter_start chapter_end chapternum chapterNameScheme chapter_title chapter_file
if [ "$((${continueAt} > ${chapternum}))" = "0" ]; then if [ "$((${continueAt} > ${chapternum}))" = "0" ]; then
# Extract chapter by time stamps start and finish of chapter. # Extract chapter by time stamps start and finish of chapter.
# This extracts based on time stamps start and end. # This extracts based on time stamps start and end.
@ -674,16 +716,6 @@ do
echo "${chapter_title}.${extension}" >> "${playlist_file}" echo "${chapter_title}.${extension}" >> "${playlist_file}"
fi fi
chapternum=$((chapternum + 1 )) chapternum=$((chapternum + 1 ))
# ----
# Add the cover art to m4a and m4b file types.
if [[ ${container} == "mp4" && $(type -P mp4art) ]]; then
mp4art -q --add "${cover_file}" "${chapter_file}"
if [ "$((${loglevel} > 1))" == "1" ]; then
log "Added cover art to ${chapter_title}"
fi
fi
fi fi
done 9< "$metadata_file" done 9< "$metadata_file"
@ -698,15 +730,9 @@ do
else else
# Perform file tasks on output file. # Perform file tasks on output file.
# ---- # ----
# Add the cover art to m4a and m4b file types. # ffmpeg seems to copy only chapter position, not chapter names.
if [[ ${container} == "mp4" && $(type -P mp4art) ]]; then
mp4art -q --add "${cover_file}" "${output_file}"
if [ "$((${loglevel} > 1))" == "1" ]; then
log "Added cover art to ${title}.${extension}"
fi
fi
if [[ ${container} == "mp4" && $(type -P mp4chaps) ]]; then if [[ ${container} == "mp4" && $(type -P mp4chaps) ]]; then
ffprobe -i "${aax_file}" -print_format csv -show_chapters 2>/dev/null | awk -F "," '{printf "CHAPTER%02d=%02d:%02d:%02.3f\nCHAPTER%02dNAME=%s\n", NR, $5/60/60, $5/60%60, $5%60, NR, $8}' > "${output_directory}/${title}.chapters.txt" ffprobe -i "${aax_file}" -print_format csv -show_chapters 2>/dev/null | awk -F "," '{printf "CHAPTER%02d=%02d:%02d:%02.3f\nCHAPTER%02dNAME=%s\n", NR, $5/60/60, $5/60%60, $5%60, NR, $8}' > "${output_directory}/${fileNameScheme}.chapters.txt"
mp4chaps -i "${output_file}" mp4chaps -i "${output_file}"
fi fi
fi fi

View File

@ -54,6 +54,9 @@ bash AAXtoMP3 [-f|--flac] [-o|--opus] [-a|-aac] [-s|--single] [--level <COMPRESS
* **--keep-author &lt;FIELD&gt;** If a book has multiple authors and you don't want all of them in the metadata, with this flag you can specify a specific author (1 is the first, 2 is the second...) to keep while discarding the others. * **--keep-author &lt;FIELD&gt;** If a book has multiple authors and you don't want all of them in the metadata, with this flag you can specify a specific author (1 is the first, 2 is the second...) to keep while discarding the others.
* **--author &lt;AUTHOR&gt;** Manually set the author metadata field, useful if you have multiple books of the same author but the name reported is different (eg. spacing, accents..). Has precedence over `--keep-author`. * **--author &lt;AUTHOR&gt;** Manually set the author metadata field, useful if you have multiple books of the same author but the name reported is different (eg. spacing, accents..). Has precedence over `--keep-author`.
* **-l** or **--loglevel &lt;LOGLEVEL&gt;** Set loglevel: 0 = progress only, 1 (default) = more information, output of chapter splitting progress is limitted to a progressbar, 2 = more information, especially on chapter splitting, 3 = debug mode * **-l** or **--loglevel &lt;LOGLEVEL&gt;** Set loglevel: 0 = progress only, 1 (default) = more information, output of chapter splitting progress is limitted to a progressbar, 2 = more information, especially on chapter splitting, 3 = debug mode
* **--dir-naming-scheme &lt;STRING&gt;** or **-D** Use a custom directory naming scheme, with variables. See [below](#custom-naming-scheme) for more info.
* **--file-naming-scheme &lt;STRING&gt;** or **-F** Use a custom file naming scheme, with variables. See [below](#custom-naming-scheme) for more info.
* **--chapter-naming-scheme &lt;STRING&gt;** Use a custom chapter naming scheme, with variables. See [below](#custom-naming-scheme) for more info.
### [AUTHCODE] ### [AUTHCODE]
@ -122,6 +125,27 @@ __Note:__ At least one of the above must be exist. The code must also match the
* The default codec is mp3 * The default codec is mp3
* The default output is by chapter. * The default output is by chapter.
### Custom naming scheme
The following flags can modify the default naming scheme:
* **--dir-naming-scheme** or **-D**
* **--file-naming-scheme** or **-F**
* **--chapter-naming-scheme**
Each flag takes a string as argument. If the string contains a variable defined in the script (eg. artist, title, chapter, narrator...), the corresponding value is used.
The default options correspond to the following flags:
* `--dir-naming-scheme '$genre/$artist/$title'`
* `--file-naming-scheme '$title'`
* `--chapter-naming-scheme '$title-$(printf %0${#chaptercount}d $chapternum) $chapter'`
Additional notes:
* If a command substitution is present in the passed string, (for example `$(printf %0${#chaptercount}d $chapternum)`, used to pad with zeros the chapter number), the commands are executed.
So you can use `--dir-naming-scheme '$(date +%Y)/$artist'`, but using `--file-naming-scheme '$(rm -rf /)'` is a really bad idea. Be careful.
* You can use basic text, like `--dir-naming-scheme 'Converted/$title'`
* You can also use shell variables as long as you escape them properly: `CustomGenre=Horror ./AAXtoMP3 --dir-naming-scheme "$CustomGenre/\$artist/\$title" *.aax`
* If you want shorter chapter names, use `--chapter-naming-scheme '$(printf %0${#chaptercount}d $chapternum) $chapter'`: only chapter number and chapter name
* If you want to append the narrator name to the title, use `--dir-naming-scheme '$genre/$artist/$title-$narrator' --file-naming-scheme '$title-$narrator'`
* If you don't want to have the books separated by author, use `--dir-naming-scheme '$genre/$title'`
### Installing Dependencies. ### Installing Dependencies.
#### FFMPEG,FFPROBE #### FFMPEG,FFPROBE
__Ubuntu, Linux Mint, Debian__ __Ubuntu, Linux Mint, Debian__
@ -166,7 +190,7 @@ brew install gnu-sed
brew install grep brew install grep
``` ```
#### mp4art #### mp4art/mp4chaps
_Note: This is an optional dependency._ _Note: This is an optional dependency._
__Ubuntu, Linux Mint, Debian__ __Ubuntu, Linux Mint, Debian__
@ -178,13 +202,30 @@ __CentOS, RHEL & Fedora__
``` ```
# CentOS/RHEL and Fedora users make sure that you have enabled atrpms repository in system. Lets begin installing FFmpeg as per your operating system. # CentOS/RHEL and Fedora users make sure that you have enabled atrpms repository in system. Lets begin installing FFmpeg as per your operating system.
yum install mp4v2-utils yum install mp4v2-utils
``` ```
__MacOS__ __MacOS__
``` ```
brew install mp4v2 brew install mp4v2
``` ```
#### mediainfo
_Note: This is an optional dependency._
__Ubuntu, Linux Mint, Debian__
```
sudo apt-get update
sudo apt-get install mediainfo
```
__CentOS, RHEL & Fedora__
```
yum install mediainfo
```
__MacOS__
```
brew install mediainfo
```
## Anti-Piracy Notice ## Anti-Piracy Notice
Note that this project **does NOT crack** the DRM. It simply allows the user to Note that this project **does NOT crack** the DRM. It simply allows the user to
use their own encryption key (fetched from Audible servers) to decrypt the use their own encryption key (fetched from Audible servers) to decrypt the