- Intro
- Docker
- Activation Bytes
- Which Version?
- Python Config
- Python Secrets
- Shell Config
- Shell Secrets
- Notes
Bookworm aims to ease the Audible audiobook archiving process by simplifying a user's workflow. Once running, bookworm will convert your .aax
files into .m4b
files allowing almost any player to play them, including Plex Media Server.
You can build your own containers with the included Dockerfile
. I don't maintain a latest
tag because I always pin versions anyways. Tags will match available releases in this repo.
docker pull craighton/bookworm:[tag]
In order for Bookworm to convert your file, you need to supply your activation_bytes
. As far as I'm aware, this is an account-wide secret valid for any book downloaded from your Audible account. The purpose is to prevent Person A from downloading an audiobook from their account and sharing the downloaded file with Person B. Although third-party players like iTunes allow you to listen to downloaded Audible audiobooks, behind the scenes they will login to your Audible account to retrieve your activation_bytes
that then allow them to play the downloaded audiobook.
An easy way to retrieve this value is to run the following in your terminal (note: this is dependent on a 3rd party who may choose to disable their API at any time):
checksum=$(ffprobe /path/to/audiobook 2>&1 | grep checksum | awk '{print $NF}')
curl -s https://aaxactivationserviceapi.azurewebsites.net/api/v1/activation/${checksum}
Both versions work equally well when configured properly.
The shell
version (releases without a -python
suffix) is incompatible with network shares because it uses inotify
to receive file events from the linux kernel which are not triggered on nfs
shared folders. Thus, bookworm would hang forever never doing any work.
Assuming the input directory would allow for either version to run, then the determining factor would be ease of scheduling the python
version to run at some interval as it does not currently keep the main thread alive after performing work. If running in kubernetes, it is simple enough to run bookworm in a CronJob
. See how I do it in my home k3s cluster.
The following key/value pairs should be located in one or more yaml
files mounted in /app/config
. Bookworm will load all yaml
files in that directory. The container does contain a default file which should be sufficient for most cases. The directory in which config is found may also be changed with the CONFIG_DIRECTORY_NAME
environment variable.
Name | Description | Default |
---|---|---|
input.path |
path to directory that input files will be found; see Input Path Notes for more details | /app/watch |
input.extension |
file extension of input files; will ignore files not matching this value | .aax |
input.cleanup |
switch to control whether input files should be deleted after successful conversion | true |
output.path |
path to directory that converted files will be placed | /app/output |
output.extension |
file extension of output files | .m4b |
output.overwrite |
switch to control whether converted files should overwrite an existing file with the same name in the output location | false |
ffmpeg.run |
switch to control whether call to ffmpeg is allowed; useful to set false for debugging |
true |
ffmpeg.path |
path to ffmpeg ; if ffmpeg is in PATH , keep default value |
ffmpeg |
ffmpeg.additional_args |
list of extra args added to ffmpeg call; see ffmpeg Additional Args for more details | ['-hide_banner', '-loglevel', 'error', '-nostats', '-y'] |
ffprobe.path |
path to ffprobe ; if ffprobe is in PATH , keep default value |
ffprobe |
ffprobe.additional_args |
list of extra args added to ffprobe call; these grab a specific value, so best not to change the default | ['-show_entries', 'format_tags=title', '-of', 'compact=p=0', '-v', '"0"'] |
logging.level |
controls logging verbosity; can be one of info , warning , error , debug ; see Debug Logging for important information on security concerns |
info |
logging.format |
controls desired logging format | '%(asctime)s - %(levelname)s - [%(name)s] %(message)s' |
The following key/value pairs should be located in one or more yaml
files mounted in /app/secrets
. Bookworm will load all yaml
files in that directory. The container does not contain a default secrets file and will error with a helpful message if this is not set. The directory in which secrets are found may also be changed with the SECRETS_DIRECTORY_NAME
environment variable.
Name | Description | Default |
---|---|---|
activation_bytes |
string to open your audible files | none |
Instead of yaml
files, the shell releases use env
variables. The script will attempt to load the following config from the env
first, and if not found, will export variables from defaults.env
.
Name | Description | Default |
---|---|---|
WATCH_DIR |
path to directory that input files will be found; see Input Path Notes for more details | ~/.watch |
OUTPUT_DIR |
path to directory that converted files will be placed | ~/.output |
Instead of yaml
files, the shell releases use env
variables. The script will attempt to load the following secrets from the env
first, and if not found, will export variables from secrets.env
. The container does not contain a default secrets file and will error if this is not set.
Name | Description | Default |
---|---|---|
ACTIVATION_BYTES |
string to open your audible files | none |
If your input.path
is an nfs
shared folder, you must use the python
releases of bookworm. The shell
versions leverage inotify
for kernel events which nfs
does not broadcast. However, if using local storage, the shell
versions will be slightly faster given that they use inotify
and may be more convenient as they don't require scheduling bookworm on an interval.
The additional args will be added to the command between ffmpeg
and -activation_bytes
. Some options will not work where these are placed. Following is an example command with default values:
ffmpeg -hide_banner -loglevel error -nostats -y -activation_bytes <activation_bytes> -i <input.path> -c copy <output.path>
If debug logging is enabled, your activation_bytes
will be written to stdout. Depending on your environment, this may mean your activation_bytes
will be logged in plain text to a file on disk.