Initial commit
Add initial files.
This commit is contained in:
commit
86b8807249
3 changed files with 238 additions and 0 deletions
9
.mise.toml
Normal file
9
.mise.toml
Normal file
|
@ -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"
|
123
README.md
Normal file
123
README.md
Normal file
|
@ -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.
|
106
justfile
Normal file
106
justfile
Normal file
|
@ -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
|
Loading…
Reference in a new issue