From 86b88072496f645f3e0365efac6c9ca384745158 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sun, 20 Oct 2024 16:50:58 +0100 Subject: [PATCH] Initial commit Add initial files. --- .mise.toml | 9 ++++ README.md | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++ justfile | 106 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 238 insertions(+) create mode 100644 .mise.toml create mode 100644 README.md create mode 100644 justfile diff --git a/.mise.toml b/.mise.toml new file mode 100644 index 0000000..0a882c2 --- /dev/null +++ b/.mise.toml @@ -0,0 +1,9 @@ +[tools] +ffmpeg = "latest" +jq = "latest" +"pipx:mkb79/audible-cli" = "master" +"cargo:refile-m4b" = "latest" +fzf = "latest" +python = "latest" +pipx = "latest" +rust = "latest" diff --git a/README.md b/README.md new file mode 100644 index 0000000..63fe215 --- /dev/null +++ b/README.md @@ -0,0 +1,123 @@ +A justfile containing recipes to help download, convert, rename, file and archive your audiobook collection. + +The use of these recipes in intended for the sole purpose of maintaining a PERSONAL archive, and the resulting `.m4b` files should not be redistributed where doing so would violate your contract with the supplier of the original `.aax` and `.aaxc` files. + +## Requirements + +- [mise-en-place](https://mise.jdx.dev) + +Mise will be used to install the other dependencies. If you don't want to use `mise`, then you need to install the following: + +- [just](https://just.systems/) +- [audible-cli](https://github.com/mkb79/audible-cli) (recommended installation instuctions below) +- [fzf](https://github.com/junegunn/fzf) +- [jq](https://jqlang.github.io/jq/) +- [ffmpeg](https://ffmpeg.org) +- [refile-m4b](https://crates.io/crates/refile-m4b) + +### Transitive Dependencies + +For `refile-m4b` you will also need these libraries (or the equivalent for your OS): + +- libtag1-dev +- libtagc0-dev + +#### Debian + +```shell +sudo apt install libtag1-dev libtagc0-dev +``` + +### Install `mise` + +```shell +curl https://mise.run | sh +~/.local/bin/mise --version +``` + +### Install dependencies with `mise` + +```shell +mise install +``` + +This will use the `.mise.toml` file to install all the required dependencies. + +### Note on Installing `audible-cli` Manually + +If you aren't using `mise` to install the `audible-cli` then note that the latest version (`v0.3.1`) doesn't work (at least for me), so I recommend using the latest version in the `master` branch. + +## Usage + +### Check prerequisites + +Run the `doctor` recipe to verify prerequisites: + +```shell +just doctor +``` + +e.g.: + +```text +Verify required executables are on the path: +- OKAY : audible => ~/.local/share/mise/installs/pipx-mkb79-audible-cli/master/bin/audible +- OKAY : just => ~/.local/share/mise/installs/just/latest/bin/just +- OKAY : fzf => ~/.local/share/mise/installs/go-github-com-junegunn-fzf/latest/bin/fzf +- OKAY : jq => ~/.local/share/mise/installs/jq/latest/bin/jq +- OKAY : ffmpeg => ~/.local/share/mise/installs/ffmpeg/latest/bin/ffmpeg +- OKAY : refile-m4b => ~/.local/share/mise/installs/cargo-refile-m4b/latest/bin/refile-m4b +``` + +### Authenticate & Register + +When prompted to name your profile, use the default: '`audible`'. +We use that name to locate the file `~/.audible/audible.json` when converting AAX files. + +```shell +audible quickstart +audible activation-bytes +``` + +This will log in to you account, register a pseudo device in your account and store the details in `~/.audible/`. + +### Fetch Library + +Once you have bought a title or otherwise added to your account's library, you need to fetch a copy of the latest library list. + +```shell +just fetch-library +``` + +This will create a new file `library-{date}.txt`, that contains a list of everything available in your account. + +### Select, download and convert + +The recommended workflow is to run the default recipe which will present you with a searchable list of your library. +From here you can select items to download by pressing `TAB` (for selecting mutliple titles), or `ENTER` to select just the one. + +Once you have made your selection, the `.aax` and/or `.aaxc/.voucher` files will be downloaded, via a `./TEMP/` directory, +before being moved to either the `./AAX/` or `./AAXC/` directories. + +Once downloaded they will be automatically converted to DRM free `.m4b` files in the `./M4B/` directory. + +NOTE: After being converted the source files in the `./AAX/` and `./AAXC/` directories are deleted. + +The files in `./M4B/` will then be refiled, by `refile-m4b`, into directories based on the author, series and title. + +### Review + +You are now free to rename and/or move the files to more closely fit your own prefered archival needs. + +### Archive + +Once you are happy you can run the '`archive`' recipe to move the files into your archive. + +```shell +export AUDIOBOOK_ARCHIVE=/mnt/external/audio-books/ +just archive +``` + +Set the `AUDIOBOOK_ARCHIVE` environment variable to the directory where you want your `.m4b` files to be stored. + +NOTE: Once the files have been copied, the files in the `M4B` directory are deleted. diff --git a/justfile b/justfile new file mode 100644 index 0000000..c5e12af --- /dev/null +++ b/justfile @@ -0,0 +1,106 @@ +default: select-download convert refile + @tree M4B/ + +doctor: + @echo "Verify required executables are on the path:" + just _doc_require_exec_all audible just fzf jq ffmpeg refile-m4b + +_doc_require_exec_all *exec: + for one in {{ exec }} ; do just _doc_require_exec ${one} ; done + +_doc_require_exec exec: + #!/usr/bin/env bash + export EXEC=$(which {{ exec }}) + if test -z ${EXEC} ; then + echo "- MISSING : {{ exec }}" + else + echo "- OKAY : {{ exec }} => ${EXEC}" + fi + +select-download: + #!/usr/bin/env bash + SELECTION=$(cat $(just latest-library) | sort -k 2 | fzf -e -m) + ASINS="" + while IFS= read -r LINE ; do + echo "$LINE" + export ASIN=$(echo $LINE | cut -d: -f 1) + echo "ASIN: $ASIN" + ASINS="${ASINS} --asin ${ASIN}" + done <<< $SELECTION + just _download-asin $ASINS + +fetch-library: + audible library list > library-$(date +%Y-%m-%d).txt + +@latest-library: + ls library-*.txt | tail -n 1 + +_require_dir *dirs: + mkdir {{ dirs }} 2>/dev/null || true + +_move target *files: + mv {{ files }} {{ target }}/ 2>/dev/null || true + +_download-asin *asins: + just _require_dir TEMP + cd TEMP && audible download --aax-fallback {{ asins }} + just post-download + +post-download: + just _require_dir AAX AAXC + just _move AAX/ TEMP/*.aax + just _move AAXC/ TEMP/*.aaxc TEMP/*.voucher + +convert: convert-aax convert-aaxc + +convert-aax: + just _require_dir M4B + [ -f AAX/*.aax ] && for F in AAX/*.aax ; \ + do \ + O=M4B/$(basename $F .aax).m4b ; \ + ffmpeg \ + -y \ + -activation_bytes $(jq .activation_bytes ~/.audible/audible.json | tr '\"' ' ') \ + -i $F \ + -codec copy \ + $O && \ + rm $F ; \ + done || true + +convert-aaxc: + just _require_dir M4B + [ -f AAXC/*.aaxc ] && for AAXC in AAXC/*.aaxc ; \ + do \ + VOUCHER="${AAXC%.aaxc}.voucher" ; \ + M4B="M4B/$(basename ${AAXC%.aaxc}).m4b" ; \ + just _convert-one-aaxc $AAXC $VOUCHER $M4B ; \ + done || true + +_convert-one-aaxc aaxc_file voucher_file m4b_file: + #!/usr/bin/env bash + export KEY="$(jq .content_license.license_response.key {{ voucher_file }} | tr '\"' ' ')" + export IV="$(jq .content_license.license_response.iv {{ voucher_file }} | tr '\"' ' ')" + ffmpeg \ + -audible_key $KEY \ + -audible_iv $IV \ + -i {{ aaxc_file }} \ + -vn \ + -c:a copy \ + -map_metadata 0:g \ + {{ m4b_file }} && \ + rm {{ aaxc_file }} {{ voucher_file }} + +refile: + refile-m4b M4B + +archive: + [ -d "${AUDIOBOOK_ARCHIVE}" ] || (echo "ERROR: No archive specified" ; exit 1) + [ -f M4B/* ] || (echo "WARN: Nothing to be archived" ; exit 1) + cd M4B && cp -v -R * "${AUDIOBOOK_ARCHIVE}" + just _clean M4B + +clean: + for target in TEMP/* AAX/* AAXC/* M4B/* ; do just _clean $target ; done + +_clean target: + if [ -f {{ target }} -o -d {{ target }} ] ; then rm -r {{ target }} ; fi