{"id":25120083,"url":"https://github.com/damajor/bald","last_synced_at":"2025-04-02T14:20:26.194Z","repository":{"id":276055754,"uuid":"927881921","full_name":"damajor/BALD","owner":"damajor","description":"Brand new Audible Library Downloader","archived":false,"fork":false,"pushed_at":"2025-03-17T11:19:46.000Z","size":455,"stargazers_count":9,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-17T12:30:38.815Z","etag":null,"topics":["aax","aaxc","audible","audible-converter","audible-library","audible-library-extractor","audiobook","audiobooks","audiobookshelf","downloader","ffmpeg","ogg","podman","shell"],"latest_commit_sha":null,"homepage":"https://damajor.github.io/BALD/","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/damajor.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-02-05T17:41:47.000Z","updated_at":"2025-03-17T11:19:51.000Z","dependencies_parsed_at":"2025-03-09T21:33:01.327Z","dependency_job_id":null,"html_url":"https://github.com/damajor/BALD","commit_stats":null,"previous_names":["damajor/bald"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/damajor%2FBALD","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/damajor%2FBALD/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/damajor%2FBALD/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/damajor%2FBALD/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/damajor","download_url":"https://codeload.github.com/damajor/BALD/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246828477,"owners_count":20840474,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aax","aaxc","audible","audible-converter","audible-library","audible-library-extractor","audiobook","audiobooks","audiobookshelf","downloader","ffmpeg","ogg","podman","shell"],"created_at":"2025-02-08T05:19:08.703Z","updated_at":"2025-04-02T14:20:26.181Z","avatar_url":"https://github.com/damajor.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"---\ntitle: BALD\npermalink: index.html\noutput: pdf_document\ngeometry: margin=2cm\n---\n\n[![Docker Repository on Quay](https://quay.io/repository/damajor/bald/status \"Docker Repository on Quay\")](https://quay.io/repository/damajor/bald)\n\n    BBBBBBBBBBBBBBBBB               AAA               LLLLLLLLLLL             DDDDDDDDDDDDD        \n    B::::::::::::::::B             A:::A              L:::::::::L             D::::::::::::DDD     \n    B::::::BBBBBB:::::B           A:::::A             L:::::::::L             D:::::::::::::::DD   \n    BB:::::B     B:::::B         A:::::::A            LL:::::::LL             DDD:::::DDDDD:::::D  \n      B::::B     B:::::B        A:::::::::A             L:::::L                 D:::::D    D:::::D \n      B::::B     B:::::B       A:::::A:::::A            L:::::L                 D:::::D     D:::::D\n      B::::BBBBBB:::::B       A:::::A A:::::A           L:::::L                 D:::::D     D:::::D\n      B:::::::::::::BB       A:::::A   A:::::A          L:::::L                 D:::::D     D:::::D\n      B::::BBBBBB:::::B     A:::::A     A:::::A         L:::::L                 D:::::D     D:::::D\n      B::::B     B:::::B   A:::::AAAAAAAAA:::::A        L:::::L                 D:::::D     D:::::D\n      B::::B     B:::::B  A:::::::::::::::::::::A       L:::::L                 D:::::D     D:::::D\n      B::::B     B:::::B A:::::AAAAAAAAAAAAA:::::A      L:::::L         LLLLLL  D:::::D    D:::::D \n    BB:::::BBBBBB::::::BA:::::A             A:::::A   LL:::::::LLLLLLLLL:::::LDDD:::::DDDDD:::::D  \n    B:::::::::::::::::BA:::::A               A:::::A  L::::::::::::::::::::::LD:::::::::::::::DD   \n    B::::::::::::::::BA:::::A                 A:::::A L::::::::::::::::::::::LD::::::::::::DDD     \n    BBBBBBBBBBBBBBBBBAAAAAAA                   AAAAAAALLLLLLLLLLLLLLLLLLLLLLLLDDDDDDDDDDDDD        \n                _____               _                     _____       _ _ _   _          \n               | __  |___ ___ ___ _| |   ___ ___ _ _ _   |  _  |_ _ _| |_| |_| |___      \n               | __ -|  _| .'|   | . |  |   | -_| | | |  |     | | | . | | . | | -_|     \n               |_____|_| |__,|_|_|___|  |_|_|___|_____|  |__|__|___|___|_|___|_|___|     \n                                                                                         \n             __    _ _                      ____                _           _         \n            |  |  |_| |_ ___ ___ ___ _ _   |    \\ ___ _ _ _ ___| |___ ___ _| |___ ___ \n            |  |__| | . |  _| .'|  _| | |  |  |  | . | | | |   | | . | .'| . | -_|  _|\n            |_____|_|___|_| |__,|_| |_  |  |____/|___|_____|_|_|_|___|__,|___|___|_|  \n                                    |___|                                             \n\n\nBrand new Audible Library Downloader\n====================================\n\n**Author: damajor**\n\n**Source code: [BALD @ GitHub](https://github.com/damajor/BALD)**\n\n**Topics: Automatic download / art cover embedding / metadata tagging / conversion / renaming of Audible books**\n\nTable of content\n================\n\u003c!-- @import \"[TOC]\" {cmd=\"toc\" depthFrom=1 depthTo=2 orderedList=true} --\u003e\n\u003c!-- code_chunk_output --\u003e\n\n1. [Description](#description)\n2. [Feature details](#feature-details)\n3. [For the impatient](#for-the-impatient)\n4. [Pre-requisites](#pre-requisites)\n5. [Required tools](#required-tools)\n6. [Optional tools](#optional-tools)\n7. [Repository files description](#repository-files-description)\n8. [Installation](#installation)\n9. [Usage examples](#usage-examples)\n    1. [Manual run](#manual-run)\n    2. [Automatic run (crontab)](#automatic-run-crontab)\n    3. [Container usage](#container-usage)\n10. [Configuration](#configuration)\n    1. [Script main settings](#script-main-settings)\n    2. [Download settings](#download-settings)\n    3. [Metadata related settings](#metadata-related-settings)\n    4. [Conversion settings](#conversion-settings)\n    5. [File move settings](#file-move-settings)\n    6. [Debug settings](#debug-settings)\n11. [Anti-piracy notice](#anti-piracy-notice)\n12. [License](#license)\n\n\u003c!-- /code_chunk_output --\u003e\n\n# Description\n\nBALD is a highly configurable tool to download your Audible library and build your local library.  \nBALD uses various tools to download, enrich metadata, convert audiobooks, rename files and move them to target location.\nThis script is intended to be run on a Linux system (WSL may work) with bash and some other tools installed\n\nLast run time is stored in a status file for next runs, so only deltas are downloaded.\n\nSome logs will be created \u0026 deleted inside `script_dir/tmp` directory.\nAll working files during processing are stored in the same directory as the downloaded books.\n\nA Dockerfile is also provided for those who want to use it in rootless containers.\n\nIn case of a problem please open an issue on GitHub \u003chttps://github.com/damajor/BALD/issues\u003e\n\n\u003e **NB:**\n\u003e Some metadata may be wrong or malformed, don't blame the script but complains to Audible\n\u003e If you find a reliable logic or source of metadata to fix Audible quirks, open an issue \u0026 let me know.\n\n# Feature details\n\n - automatic Audible audiobooks downloads\n - crontab friendly (delta runs)\n - library history downloads (full \u0026 deltas)\n - wishlist download\n - either one of:\n   - keep original chapters,\n   - chapters renaming,\n   - or rebuild entirely all chapters\n - metadata enrichment (from normal \u0026 hidden AAX/AAXC tags, or from history TSV file)\n - cover art embedding\n - audiobooks conversion to **oga** (Ogg container with Opus codec)\n - size control of converted audiobooks:\n   - custom fixed bitrate\n   - dynamic bitrate based on a user ratio\n - parallelization of heavy work (conversion \u0026 metadata enrichment)\n - \"perfect\" embedded metadata for AudioBookShelf ([AudioBookShelf](https://github.com/advplyr/audiobookshelf))\n - dynamic naming scheme for destination directories \u0026 file names\n - helper script for downloading external scripts\n - container Dockerfile provided with all dependencies \u0026 external scripts (tested on Podman rootless)\n - basic statistics after each run\n - local TSV database of converted audiobooks\n - and more...\n\n# For the impatient\n\nGo read the full Podman walkthrough here [README_Podman_Walkthrough.md](README_Podman_Walkthrough.md).\n\n# Pre-requisites\n\n - install `audible-cli` and create a profile (check instructions here \u003chttps://github.com/mkb79/audible-cli\u003e)\n - modify script user config variables to match your needs\n - run `parallel --citation` and follow instructions to avoid output warning garbage\n\n# Required tools\n\n - bash (v4.3+)\n - jq\n - bc\n - xxd (for ogg image blobber script)\n - audible-cli (at least version 0.3.2b3)\n - ffmpeg / ffprobe (tested 6.1.2 \u0026 7.1)\n - mediainfo\n - parallel\n\n**Also download these scripts and put them in the same directory as this script**\n\n - `ogg-image-blobber.sh` (from \u003chttps://github.com/twopoint71/ogg-image-blobber\u003e)\n - `update_chapter_titles.py` (from \u003chttps://github.com/mkb79/audible-cli/blob/master/utils/update_chapter_titles.py\u003e)\n\n# Optional tools\n\n - Java + Tika (download jar from [Apache Tika](https://tika.apache.org/))  \n   **It slows down metadata extraction** but gives very good language accuracy detection.\n\nOr\n\n - Your own Tika server (**processing is faster than using the jar**)\n\n# Repository files description\n\n- `BALD.sh` it is the main script with all the processing logic.\n- `grab_additional_scripts.sh` a quick and dirty script for lazy boys. It will download external scripts and optional tool for you, as well creating a user config file with default values (just remove `myconfig` if you want to set parameters in the script itself).\n- `docker_mod.sh` not to be used directly by the user, it is sourced by the main script to make it compatible with containers.\n- `rebuild_chapters.sh` used to build `ffmpeg` chapters metadata\n- `Dockerfile` used to build your own container image.\n- `compose.yaml` example of for Podman/Docker compose.\n- `README.md` the file you are currently reading.\n- `README.pdf` for convenience purposes the README is also exported as PDF file.\n- `LICENSE` is the license file of this project.\n\n# Installation\n\nIt is as simple as:\n\n1. Clone GitHub repository or download archive of it  \n`git clone https://github.com/damajor/BALD`  \n2. Manually grab external tools and put them in the same directory of the script **OR** execute the download script (this will also create a default `myconfig` file)  \n`./grab_additional_scripts.sh`  \n3. Carefully configure all settings in `myconfig` or directly inside the script\n\n\u003e **Note:**  \n\u003e The script is not compatible with NTFS filesystem.\n\n# Usage examples\n\nDouble check prerequisites and settings :)\n\nBALD was designed to run every day at most.\n\n## Manual run\n\nOnce configured the only thing is to run the script.\n\nOn the first run the script will download ALL your library to the desired location and will do its jobs for metadata, conversion and moving converted files to target location.\n\nUpcoming runs will only download new books from Audible (delta run) and process them as usual.\n\n\u003e **Example:**  \n\u003e either  \n\u003e `/full/path/of/script/BALD.sh`  \n\u003e or if the script is in your path, just use:  \n\u003e `BALD.sh`  \n\u003e or if you start it manually from the script location:  \n\u003e `./BALD.sh`\n\n## Automatic run (crontab)\n\nIt is recommended to run the script daily at most. It works better with a daily scheduling or more like every week or month.\n\n\u003e **Example:**  \n\u003e Run every day at 4PM  \n\u003e `0 4 * * * /full/path/of/script/BALD.sh \u003edev/null 2\u003e/dev/null`  \n\u003e Run every first day of each month at 4PM  \n\u003e `0 4 1 * * /full/path/of/script/BALD.sh \u003edev/null 2\u003e/dev/null`\n\n\u003e **Notes:**  \n\u003e - Please note that automated runs does NOT prevent you to manually run the script at any time you want.  \n\u003e Example, if you set up a weekly update, but you want to quickly run it manually once because you purchased a new audiobook, then just do it! (the script will store the last execution to the time of the manual run)  \n\u003e - Before setting up your automation, try to run manually the script to see if it behaves the way you have configured it.  \n\u003e - **Also, it is HIGHLY recommended doing the first run manually. Just because it will sync entire library and can take hours of processing for big libraries.**\n\n## Container usage\n\n[![Docker Repository on Quay](https://quay.io/repository/damajor/bald/status \"Docker Repository on Quay\")](https://quay.io/repository/damajor/bald)\n\n\u003e **Notes:**  \n\u003e The script has been developed using Podman rootless.  \n\u003e It should work on Docker (rootless or not).  \n\u003e Everything inside the container runs as 'root' user, **use rootless containers without CAP_ADMIN for security**.\n\n\u003e **IMPORTANT:**  \n\u003e [Initialize audible-cli](#audible-cli-initialization)\n\nWhen used in containers the script makes some settings 'readonly'.\nThe user MUST map specific volumes (the script will check all volumes are mapped, or it will exit).\n\nThe following settings are hard coded using the script inside container:\n```\nHIST_LIB_DIR=\"/audible_history\"\nSTATUS_FILE=\"/status_file\"\nDOWNLOAD_DIR=\"/audible_dl\"\nDEST_BASE_DIR=\"/audiobooks_dest\"\nLOCAL_DB=\"/BALD/personal_library.tsv\"\nDEBUG_USEAAXSAMPLE=/sample.aax\nDEBUG_USEAAXCSAMPLE=/sample.aaxc\n```\nThe user is responsible to map volumes accordingly.\n\n### Container volume maps list\n\nWhen mapping local directories to your container, make sure that they all exist.\n\n#### Required\n\nThe following volumes MUST be mapped to the container, if one map is missing the script will exit with an error message with the missing volume:\n\n| Local                                     | Container                   | Type    |\n|-------------------------------------------|-----------------------------|---------|\n| [HIST_LIB_DIR](#hist_lib_dir)             | /audible_history            | dir     |\n| [STATUS_FILE](#status_file)               | /status_file                | file    |\n| [DOWNLOAD_DIR](#download_dir)             | /audible_dl                 | dir     |\n| [DEST_BASE_DIR](#dest_base_dir)           | /audiobooks_dest            | dir     |\n| [LOCAL_DB](#local_db)                     | /BALD/personal_library.tsv  | dir     |\n| myconfig                                  | /BALD/myconfig              | file    |\n| tmp logs directory                        | /BALD/tmp                   | dir     |\n| audible-cli config dir                    | /root/.audible              | dir     |\n\n#### Optional\n\nThose volumes are optional, just if you want to debug the script:\n\n| Local                                         | Container             | Type    |\n|-----------------------------------------------|-----------------------|---------|\n| [DEBUG_USEAAXSAMPLE](#debug_useaaxsample)     | /BALD/sample.aax      | file    |\n| [DEBUG_USEAAXCSAMPLE](#debug_useaaxcsample)   | /BALD/sample.aaxc     | file    |\n| aaxc voucher file                             | /BALD/sample.voucher  | file    |\n\n### Audible CLI initialization\n\nIf you have `audible-cli` installed and initialized then you can directly map your `audible-cli` config directory and skip this part.\n\nIf you had never used `audible-cli` then follow what comes next.\n\nMake local `audible-cli` configuration directory:  \n    `mkdir -p /home/myuser/.audible`\n\nRun `audible-cli` quick-start enrollment:  \n    `podman run -it --rm -v /home/myuser/.audible:/root/.audible quay.io/damajor/bald:latest audible quickstart`\n\nFor more information refers to `audible-cli` documentation here \u003chttps://github.com/mkb79/audible-cli/blob/master/README.md#getting-started\u003e.\n\n### Podman command line\n\nIf you want to use the following settings with Podman:\n```\nHIST_LIB_DIR=\"/home/myuser/Audible/lib_history\"\nSTATUS_FILE=\"/home/myuser/Audible/audible_last_sync\"\nDOWNLOAD_DIR=\"/home/myuser/Audible/Downloads\"\nDEST_BASE_DIR=\"/home/myuser/AudioBookShelf/audiobooks\"\nLOCAL_DB=\"/home/myuser/Audible/personal_library.tsv\"\nDEBUG_USEAAXSAMPLE=sample.aax\nDEBUG_USEAAXCSAMPLE=sample.aaxc\n```\n\nUse the following command (*change local paths to match your needs*):\n```\npodman run -it --rm \\\n    -v /home/myuser/.audible:/root/.audible \\\n    -v /home/myuser/Audible/lib_history:/audible_history \\\n    -v /home/myuser/Audible/audible_last_sync:/status_file \\\n    -v /home/myuser/Audible/Downloads:/audible_dl \\\n    -v /home/myuser/Audible/personal_library.tsv:/BALD/personal_library.tsv \\\n    -v /home/myuser/AudioBookShelf/audiobooks:/audiobooks_dest \\\n    -v /home/myuser/BALD/myconfig:/BALD/myconfig \\\n    -v /home/myuser/BALD/tmp:/BALD/tmp \\\n    quay.io/damajor/bald:latest\n```\n\nIf you want to debug using sample files, just add:\n```\n    -v /home/myuser/BALD/sample.aax:/BALD/sample.aax \\\n    -v /home/myuser/BALD/sample.aaxc:/BALD/sample.aaxc \\\n    -v /home/myuser/BALD/sample.voucher:/BALD/sample.voucher \\\n```\n\n### Podman compose\n\nUse compose file only after you have done `audible-cli` initialization ([Help here](#audible-cli-initialization)).\nCompose file example:\n\n```\nservices:\n  BALD:\n    image: quay.io/damajor/bald:latest\n    environment:\n      - TZ=Europe/Rome\n    volumes:\n      - /home/myuser/.audible:/root/.audible:z\n      - /home/myuser/Audible/lib_history:/audible_history:z\n      - /home/myuser/Audible/audible_last_sync:/status_file:z\n      - /home/myuser/Audible/downloads:/audible_dl:z\n      - /home/myuser/Audible/personal_library.tsv:/BALD/personal_library.tsv:z\n      - /home/myuser/AudioBookShelf/audiobooks:/audiobooks_dest:z\n      - /home/myuser/BALD/myconfig:/BALD/myconfig:z\n      - /home/myuser/BALD/tmp:/BALD/tmp:z\n```\n\nRun with:  \n`podman compose -f compose.yaml up --force-recreate`\n\n### Podman Quadlet (systemd integration)\n\nBelow is an example systemd quadlet for a oneshot BALD service.\n\n1. Create a file `/home/YOURUSER/.config/containers/systemd/bald.container` with the content below (change the path to your local paths)\n\n```\n[Unit]\nDescription=Podman BALD\n\n[Install]\n\n[Service]\nRestart=no\nType=oneshot\n\n[Container]\nImage=quay.io/damajor/bald:latest\nContainerName=bald\nHostName=bald\nAutoUpdate=registry\nVolume=/home/myuser/Audible/lib_history:/audible_history:Z\nVolume=/home/myuser/Audible/audible_last_sync:/status_file:Z\nVolume=/home/myuser/Audible/downloads:/audible_dl:Z\nVolume=/home/myuser/AudioBookShelf/audiobooks:/audiobooks_dest:z\nVolume=/home/myuser/Audible/personal_library.tsv:/BALD/personal_library.tsv:Z\nVolume=/home/myuser/BALD/myconfig:/BALD/myconfig:Z\nVolume=/home/myuser/BALD/tmp:/BALD/tmp:Z\nVolume=/home/myuser/.audible:/root/.audible:Z\nEnvironment=\"GENERIC_TIMEZONE=Europe/Rome\" \"TZ=Europe/Rome\"\n```\n\n2. Run `systemctl --user daemon-reload`\n3. To run BALD just do `systemctl --user start bald.service` each time you need to sync your Audible library\n\n### Podman Quadlet Automation\n\nFor scheduling synchronization of your library, create a systemd timer.\n\n1. Create the timer file `/home/YOURUSER/.config/systemd/user/bald.timer` with the following content\n\n```\n[Unit]\nDescription=Podman BALD timer\nRefuseManualStart=no\nRefuseManualStop=no\n\n[Timer]\n# Runs sync every day at 23:30\nOnCalendar=Mon..Sun 23:30\nPersistent=false\nUnit=bald.service\n\n[Install]\nWantedBy=timers.target\n```\n\n2. Run `systemctl --user daemon-reload`\n3. Enable \u0026 start the timer with `systemctl --user enable --now bald.timer`\n\n# Configuration\n\n**Make sure you read all setting descriptions and usage.**\n\nChange the variables in the script section **User config** according to your needs.\n\n**All the parameters MUST have a value set** (there is only basic validation).\n\nYou can avoid to change settings in the script itself by creating a file named `myconfig` and put all the settings in it. The script will load this file if it exists, otherwise it will use default values from script itself.\n`myconfig` file takes precedence over internal settings.\n\n## Script main settings\n\n### AUDIBLECLI_PROFILE\n\nThis variable holds the profile name created with `audible-cli`.\nIt should match one of the existing JSON file in `~/audible/`\n\n\u003e **Example config (`~/audible/myprofile.json`):**  \n\u003e `AUDIBLECLI_PROFILE=myprofile`\n\n### HIST_LIB_DIR\n\nLocation of the downloaded library history files. Those files are TSV files containing your entire list of Audiobooks (and Podcasts) and delta TSV files.\n\n\u003e **Snapshot of what it looks:**\n\u003e ```\n\u003e 2024-02-01_library_full.tsv\n\u003e 2024-02-01_library_new.tsv\n\u003e 2024-03-01_library_full.tsv\n\u003e 2024-03-01_library_new.tsv\n\u003e 2024-04-01_library_full.tsv\n\u003e ```\n\n\u003e **Example config:**  \n\u003e `HIST_LIB_DIR=$HOME/Audible/lib_history`\n\n### HIST_FULL_LIB\n\nThis flag allows to download the full history TSV file of your Audible library each time the script is run.\nIf you run the script every day I recommend disabling it. If you run every week or month then you can keep it to 'true'.\n\nAllowed values:  \n- 'true'  \n- 'false' or anything else\n\n\u003e **Example config:**  \n\u003e `HIST_FULL_LIB=true`\n\n\u003e **Note:**\n\u003e This setting is ignored when using the container. You MUST use volume mapping instead.\n\n### STATUS_FILE\n\nThis is the full path and filename where the script stores the two last execution times.\nThe next run will use the last execution time to download only new audiobooks.\n**If you want to force a full sync, delete the file and run again.**\n\nThe status file stores the complete date of the script's last execution (the date is formulated as `+%Y-%m-%d`).\n\n\u003e **Example config:**  \n\u003e `STATUS_FILE=$HOME/Audible/audible_last_sync`\n\n\u003e **Note:**\n\u003e This setting is ignored when using the container. You MUST use volume mapping instead.\n\n### LOCAL_DB\n\nThis is the file location where is stored all information about the audiobooks moved to your personal library.\n\n\u003e **Example config:**  \n\u003e `LOCAL_DB=$HOME/Audible/personal_library.tsv`\n\n### SKIP_IFIN_LOCAL_DB\n\nThis flag tells the script to skip any kind of processing (download / metadata / conversion \u0026 file move) if the Audiobook is found in personal library.\n\n\u003e **Example config:**  \n\u003e `SKIP_IFIN_LOCAL_DB=true`\n\n## Download settings\n\n### DOWNLOAD_PDF\n\nThis flag allows downloading companion PDF file for each audiobook (if there is any).\n\nAllowed values:  \n- 'true'  \n- 'false' or anything else\n\n\u003e **Example config:**  \n\u003e `DOWNLOAD_PDF=true`\n\n### DOWNLOAD_ANNOT\n\nThis flag allows downloading annotations (bookmarks) for each audiobook (if there is any).\n\nAllowed values:  \n- 'true'  \n- 'false' or anything else\n\n\u003e **Example config:**  \n\u003e `DOWNLOAD_ANNOT=true`\n\n### DOWNLOAD_COVERS\n\nThis flag allows downloading art covers for each audiobook.\n\nAllowed values:  \n- 'true'  \n- 'false' or anything else\n\n\u003e **Example config:**  \n\u003e `DOWNLOAD_COVERS=true`\n\n### DOWNLOAD_COVERS_SIZE\n\nThis parameter allows to specify the cover sizes to download for each audiobook. Multiple values are allowed.\n500 seems the default size for every Audible audiobooks.\n\nAllowed values, any mix of the following:  \n252 315 360 408 500 558 570 882 900 1215\n\n\u003e **Example config:**  \n\u003e `DOWNLOAD_COVERS_SIZE=(500 1215)`\n\n### DOWNLOAD_WISHLIST\n\nThis flag allows to download your Audible account wishlist.\n\nAllowed values:  \n- 'true'  \n- 'false' or anything else\n\n\u003e **Example config:**  \n\u003e `DOWNLOAD_WISHLIST=false`\n\n### DOWNLOAD_JOBS\n\nThis setting is the concurrency level during Audiobook download. At this moment it doesn't do much because all audiobooks are not downloaded in parallel because of an issue with `audible-cli` (\u003chttps://github.com/mkb79/audible-cli/issues/218\u003e)\n\nIt sets the parallel level inside `audible-cli` (for example it parallelizes download of covers, AXX, annotations for a single audiobook).\n\n\u003e **Example config:**  \n\u003e `DOWNLOAD_JOBS=2`\n\n### DOWNLOAD_RETRIES\n\nNumbers of retries if a download fails.\nCareful of not hammering Amazon servers by keeping this setting low as there is no cooldown in the script.\n\n\u003e **Example config:**  \n\u003e `DOWNLOAD_RETRIES=3`\n\n### DOWNLOAD_DIR\n\nAAX \u0026 AAXC Audible files will be downloaded here\n\n\u003e **Example config:**  \n\u003e `DOWNLOAD_DIR=$HOME/Audible/MyDownloads`\n\n\u003e **Note:**\n\u003e This setting is ignored when using the container. You MUST use volume mapping instead.\n\n## Metadata related settings\n\n### METADATA_PARALLEL\n\nParallelization setting for metadata processing. This parameter allows the user to specify the number of jobs for metadata extraction.\n\nAllowed values: any number \u003e= 1\n\n\u003e **Example config:**  \n\u003e `METADATA_PARALLEL=3`\n\n### METADATA_SOURCE\n\nThis setting allow to specify the source of metadata. It can be `aax`, meaning that only metadata from AAX/AAXC files will be considered, or `all` which means metadata will be fetched from original AAX/AAXC files, but also from `mediainfo` tool extraction, and finally also from library file.\n\nAllowed values:  \n- 'aax'  \n- 'all'\n\n\u003e **Example config:**  \n\u003e `METADATA_SOURCE=all`\n\n### METADATA_TIKA\n\nUse Tika for language detection if title description/comments is long enough.\n\n**(slow)** For local java execution, the jar file **must be** in the same directory of this script.\n\n**(faster)** For remote execution, just put the URL of your Tika server.\n\nAllowed values:  \n - jar file name  \n - HTTP URL of Tika server\n\n\u003e **Example config:**  \n\u003e `METADATA_TIKA=tika-app-2.9.2.jar`\n\n\u003e **Example config:**  \n\u003e  `METADATA_TIKA=http://mytikahost:9998`\n\n### METADATA_CLEAN_AUTHOR_PATTERN\n\nI noticed that author/narrators metadata was not always clean, so I added a pattern matching. If you want to remove all authors that match this regex, set it here.  \nThe script first split author between ',' and then remove all authors that match this regex (*this is a non-case-sensitive regex match*).  \nBasically any authors/narrators matching any of the regex words will be removed from the list.\nThis applies also to narrators.\n\nAllowed values: regex string  \n- '*' =\u003e keep all authors  \n- 'traducteur|traductrice|editeur|editrice' =\u003e remove all authors matching any of these words\n\n\u003e **Example config:**  \n\u003e `METADATA_CLEAN_AUTHOR_PATTERN='traducteur|traductrice|editeur|editrice|editor|illustrateur|éditeur|éditrice'`\n\n### METADATA_SINGLENAME_AUTHORS\n\nIf an audiobook has multiple authors, this flag allows the script to discard all authors that are identified by a single word name (like pseudo/nicknames/etc.).  \nThis setting is ignored if there is only a single author.  \nThis applies also to narrators.\n\n\u003e **Note:** This was a dirty workaround to bad AudioBookShelf metadata parser. But it gets fixed.\n\nAllowed values:  \n- 'true' or anything else =\u003e Keep single name authors\n- 'false' =\u003e Discard single name authors\n\n\u003e **Example config:**  \n\u003e `METADATA_SINGLENAME_AUTHORS=false`\n\n### METADATA_SKIP_IFEXISTS\n\nThis flag allows the script to skip current metadata processing if the final metadata final is already present.\n\nAllowed values:  \n- 'true'\n- 'false'\n\n\u003e **Example config (default value):**  \n\u003e `METADATA_SKIP_IFEXISTS=false`\n\n### METADATA_CHAPTERS\n\nBehavior of the script while processing audiobook chapters.\n\nPossible values are:\n- 'keep' =\u003e do not modify chapters, keep the chapters defined in the AAX/AAXC files\n- 'updatetitles' =\u003e only try to update chapter titles with the python helper script\n- 'rebuild' =\u003e fully rebuild all the chapters based on Audible chapters.json file\n\n\u003e **Example config (default value):**  \n\u003e `METADATA_CHAPTERS=rebuild`\n\n## Conversion settings\n\n### CONVERT_BITRATE\n\nThis parameter sets the target bit rate of the converted file.\nLower bit rates mean smaller sizes but also lower quality.\n\nAllowed values: any string that can be parsed by `ffmpeg` (ex: 96k, 128k, etc.)\n\n\u003e **Example config:**  \n\u003e `CONVERT_BITRATE=96k`\n\n### CONVERT_BITRATE_RATIO\n\nThis setting delegates to the script the calculation of the target bitrates of all converted files.\n\nAllowed values:  \n- 'false' =\u003e disable this feature and use only fixed bitrate\n- or a ratio like 1/2, 1/3, 2/3 etc.... \n\n\u003e **Example config:**  \n\u003e `CONVERT_BITRATE_RATIO=2/3`\n\n### CONVERT_PARALLEL\n\nParallelization setting for file conversion. This parameter allows the user to specify the number of jobs for audiobook conversion.\nThis is entirely independent of METADATA_PARALLEL.\n\nOptimal setting depends on how many cores and memory you have. Usually `ffmpeg` takes 1 to 2 threads and ~800 MB of memory per encoding process.\n\nAllowed values: any number \u003e= 1\n\n\u003e **Example config:**  \n\u003e `CONVERT_PARALLEL=3`\n\n### CONVERT_SKIP_IFOGAEXISTS\n\nIf an audiobook was previously converted but not moved to target library, it may be still present in download directory, this flag tells the script to skip conversion of such Audiobooks.\n\nAllowed values:  \n- 'true'  \n- 'false' or anything else\n\n\u003e **Example config:**  \n\u003e `CONVERT_SKIP_IFOGAEXISTS=false`\n\n### CONVERT_DECRYPTONLY\n\nThis flag allows to bypass all metadata enrichment and audio format conversion of the script. Only AAX/AAXC decryption will be done during the processing of audiobooks resulting in a playable mp4 file (this will also bypass file moving to destination library).\n\n**This can be considered as a debug flag. Keep 'false' if you don't know what you are doing.**\n\nAllowed values:  \n- 'true'  \n- 'false' or anything else\n\n\u003e **Example config:**  \n\u003e `CONVERT_DECRYPTONLY=false`\n\n## File move settings\n\n### Available keys for the naming schemes\n\n| Key           | Description |\n|---------------|-------------|\n| title         | audiobook title |\n| album         | audiobook title |\n| subtitle      | audiobook subtitle |\n| year          | publish year |\n| lang          | language country code (e.g.: en, de, fr, etc.) |\n| language      | language country code (e.g.: en, de, fr, etc.) |\n| genre         | genre list (should not be used in any scheme) |\n| artist        | author |\n| album_artist  | author |\n| composer      | narrator |\n| asin          | ASIN |\n| audible_asin  | ASIN |\n| copyright     | Copyright text (should not be used in any scheme) |\n| publisher     | publisher (not relevant in any naming scheme) |\n| comment       | long description of the audiobooks (should not be used in any scheme) |\n| series        | Series name |\n| mvnm          | Series name |\n| series-part   | Series volume |\n| mvin          | Series volume |\n\nIt is recommended to stick with the following ones:  \n - title  \n - subtitle  \n - lang  \n - artist  \n - asin  \n - series  \n - series-part\n\nIn short the script will produce dynamic directory names based on metadata and aggregated based on user settings.\n\n*Directory as follows:*\n`DEST_BASE_DIR + DEST_DIR_NAMING_SCHEME_AUDIOBOOK + DEST_BOOKDIR_NAMING_SCHEME_AUDIOBOOK`\n\n*Audiobook filename:*\n`DEST_BOOK_NAMING_SCHEME_AUDIOBOOK`\n\n**These settings can be confusing pay attention to the parameter names!**\n\n### DEST_BASE_DIR\n\nBase directory for converted files (will be created if it doesn't exist).\nIf you want your converted files in a different location, change this setting.\n\n\u003e **Example config:**  \n\u003e `DEST_BASE_DIR=$HOME/AudioBookShelf/audiobooks`\n\n\u003e **Note:**\n\u003e This setting is ignored when using the container. You MUST use volume mapping instead.\n\n### DEST_DIR_NAMING_SCHEME_AUDIOBOOK\n\nDirectory path for audiobooks, it will be created under [DEST_BASE_DIR](#dest_base_dir).\n\n*Example:* `(artist series)` will produce `/Isaac Asimov/Foundation`.\n\nKeep the keys inside parentheses. If a key is non-existent for an audiobook then it's ignored.\n\nTo have only one directory per audiobook then use empty value like `()` and look for next parameter to configure the naming scheme of the audiobook directory.\n\nAllowed values:  \n - any combination of [the available keys](#available-keys-for-the-naming-schemes)  \n - or empty ()\n\n\u003e **Example config will produce /artists/series directory:**  \n\u003e `DEST_DIR_NAMING_SCHEME_AUDIOBOOK=(artist series)`\n\n### DEST_BOOKDIR_NAMING_SCHEME_AUDIOBOOK\n\nAudiobook DIRECTORY naming scheme (**cannot be empty**).\n\nThis is the directory where the audiobook will be moved, it is created under [DEST_DIR_NAMING_SCHEME_AUDIOBOOK](#dest_dir_naming_scheme_audiobook).\n\nUse `\"%string\"` to insert custom text in the file name example: `(series-part \"% - \" title)` will produce a directory named `1 - audiobook_title`.\n\nCustom string parameters are ignored if they are in the start of the naming scheme, in previous example `(series-part \"% - \" title)` if 'series-part' is not defined for an audiobook then only 'title' will be used.\n\nKeep the keys inside parentheses.\n\nAllowed values:  \n - any combination of [the available keys](#available-keys-for-the-naming-schemes)  \n - and custom user strings starting with '%' (example: '% - ')\n\n\u003e **Example config:**  \n\u003e `DEST_BOOKDIR_NAMING_SCHEME_AUDIOBOOK=(series-part \"% - \" title)`\n\n### DEST_BOOK_NAMING_SCHEME_AUDIOBOOK\n\nAudiobook FILE naming scheme (**cannot be empty**).\n\nUse `\"%string\"` to insert custom text in the file name example: `(series-part \"% - \" title)`.\n\nThe same rules apply here as in [DEST_BOOKDIR_NAMING_SCHEME_AUDIOBOOK](#dest_bookdir_naming_scheme_audiobook).\n\nAllowed values:  \n - any combination of [the available keys](#available-keys-for-the-naming-schemes)  \n - and custom user strings starting with '%' (example: '% - ')\n\n\u003e **Example config:**  \n\u003e `DEST_BOOK_NAMING_SCHEME_AUDIOBOOK=(title)`\n\n### DEST_DIR_OVERWRITE\n\nDestination directory overwrite mode (**cannot be empty**)\n\nAllowed values:  \n - **'true' or 'ignore'**: If audiobook destination directory exists then overwrite files in it, other files in directory are preserved  \n - **'remove'**: If audiobook destination directory exists then remove it and recreate it (all existing files in it will be deleted)  \n - **'keep'**: If audiobook destination directory exists then create a new one with an incremental suffix  \n - **'false' or any other value**: If audiobook destination directory exists then skip processing to next audiobook\n\n\u003e **Example config:**  \n\u003e `DEST_DIR_OVERWRITE=true`\n\n### DEST_COPY_COVER\n\nThis flag allows the user to specify if cover image should be copied to audiobook destination directory.\nIf the flag is set then a copy of the largest cover will be created in the audiobook destination directory.\nDoes nothing if no covers are found.\n\nAllowed values:  \n- 'true'  \n- 'false' or anything else\n\n\u003e **Example config:**  \n\u003e `DEST_COPY_COVER=true`\n\n### DEST_COPY_PDF\n\nThis flag allows the user to specify if PDF should be copied to audiobook destination directory.\nDoes nothing if no PDF exists.\n\nAllowed values:  \n- 'true'  \n- 'false' or anything else\n\n\u003e **Example config:**  \n\u003e `DEST_COPY_PDF=true`\n\n### DEST_COPY_CHAPTERS_FILE\n\nThis flag allows the user to specify if JSON chapters file should be copied to audiobook destination directory.\nDoes nothing if no PDF exists.\n\nAllowed values:  \n- 'true'  \n- 'false' or anything else\n\n\u003e **Example config:**  \n\u003e `DEST_COPY_CHAPTERS_FILE=true`\n\n### DEST_COPY_ANNOT_FILE\n\nThis flag allows the user to specify if JSON annotations/bookmarks file should be copied to audiobook destination directory.\nDoes nothing if no PDF exists.\n\nAllowed values:  \n- 'true'  \n- 'false' or anything else\n\n\u003e **Example config:**  \n\u003e `DEST_COPY_ANNOT_FILE=true`\n\n### CLEAN_TMPLOGS\n\nDelete logs generated during the current run (old ones are kept)\nIt is safe to keep to 'true'\n\nAllowed values:  \n- 'true'  \n- 'false' or anything else\n\n\u003e **Example config:**  \n\u003e `CLEAN_TMPLOGS=true`\n\n### KEEP_DOWNLOADS\n\nThis flag allows the script to delete downloaded files once they are converted and pushed to final target directory.\n\nOnly converted files may be deleted, not converted audiobook remaining are not deleted. \n\nAllowed values:  \n- 'true' or anything else =\u003e Keep downloaded files.  \n- 'false' =\u003e Deleted only files that have been converted\n\n\u003e **Example config:**  \n\u003e `KEEP_DOWNLOADS=true`\n\n## Debug settings\n\nParameters below are for debugging purposes (**default for all boolean parameters is 'false'**).\n\nKeep all settings below to `false` for normal behavior.\n\n### Main debug flags\n\n#### DEBUG\n\nGlobal debug flag, also change behavior while moving files to target directory, instead files are copied.\n\nAllowed values:  \n- 'true'  \n- 'false' or anything else\n\n\u003e **Example config:**  \n\u003e `DEBUG=false`\n\n#### DEBUG_REPEAT_LAST_RUN\n\nThis flag is used to repeat the last run without updating the [STATUS_FILE](#status_file).\n\nAllowed values:  \n- 'true'  \n- 'false' or anything else\n\n\u003e **Example config:**  \n\u003e `DEBUG_REPEAT_LAST_RUN=false`\n\n#### DEBUG_DONT_UPDATE_LASTRUN\n\nFlag to tell if the script should update the [STATUS_FILE](#status_file).\nThis is handy if you want to run a script multiple times for debugging purposes.\n\nAllowed values:  \n- 'true'  \n- 'false' or anything else\n\n\u003e **Example config:**  \n\u003e `DEBUG_DONT_UPDATE_LASTRUN=false`\n\n#### DEBUG_STEP\n\nWhen DEBUG is enabled and STATUS_FILE contains an old date, this setting only increments the STATUS_FILE date with the specified period of time.\nThis allows manual stepped runs over specified time periods.\nRequires [STATUS_FILE](#status_file) exists and populated.\n\nAllowed values:  \n- '1 month'  \n- '2 week'  \n- '4 days'  \n- any time period understood by 'date' console command\n\n\u003e **Example config:**  \n\u003e  `DEBUG_STEP=\"1 month\"`\n\n#### DEBUG_SKIPDOWNLOADS\n\nThis flag disables all Audible downloads for the current run.\nIf other parts of the scripts are enabled then the scripts expect to find the correct download folder with all the required files in it.\n\nAllowed values:  \n - 'true' =\u003e Disable ALL downloads  \n - 'false' or any other value =\u003e normal behavior\n\n\u003e **Example config:**  \n\u003e `DEBUG_SKIPDOWNLOADS=false`\n\n#### DEBUG_SKIPBOOKCONVERT\n\nThis flag disables all audiobook conversions for the current run.\nIf other parts of the scripts are enabled then the scripts expect to find the correct download folder with all the required files in it.\n\nAllowed values:  \n - 'true' =\u003e disable audiobook conversion  \n - 'false' or any other value =\u003e normal behavior\n\n\u003e **Example config:**  \n\u003e `DEBUG_SKIPBOOKCONVERT=false`\n\n#### DEBUG_SKIPBOOKMETADATA\n\nThis flag disables all audiobook metadata gathering for the current run.\nIf other parts of the scripts are enabled then the scripts expect to find the correct download folder with all the required files in it.\n\nAllowed values:  \n - 'true' =\u003e disable metadata gathering for audiobooks  \n - 'false' or any other value =\u003e normal behavior\n\n\u003e **Example config:**  \n\u003e `DEBUG_SKIPBOOKMETADATA=false`\n\n#### DEBUG_SKIPMOVEBOOKS\n\nThis flag disables the last part of the script and no file will be moved to destination directory for the current run.\n\nAllowed values:  \n - 'true' =\u003e disable moving audiobooks  \n - 'false' or any other value =\u003e normal behavior\n\n\u003e **Example config:**  \n\u003e `DEBUG_SKIPMOVEBOOKS=false`\n\n#### DEBUG_DONTEMBEDCOVER\n\nThis flag, if enabled, prevents the art cover file to be embedded in the converted audiobook.\nIt does not prevent the copy of the cover JPG file into destination directory (use this instead [DEST_COPY_COVER](#dest_copy_cover)).\n\nAllowed values:  \n - 'true' =\u003e disable moving audiobooks  \n - 'false' or any other value =\u003e normal behavior\n\n\u003e **Example config:**  \n\u003e `DEBUG_DONTEMBEDCOVER=false`\n\n#### DEBUG_METADATA\n\nThis flag allows more detailed debug output of metadata to be print during script execution.\nIt also allows you to create a debug file with all the metadata extracted by `ffprobe` for each converted file.\n\nAllowed values:  \n - 'true' =\u003e disable moving audiobooks  \n - 'false' or any other value =\u003e normal behavior\n\n\u003e **Example config:**  \n\u003e `DEBUG_METADATA=false`\n\n### Audiobook debug samples\n\nDebug samples are small AAX and AAXC files that will be used during audiobook conversions instead of using big original files.\nThe metadata is still fetched from the original files and inserted in converted samples.\n\nIt is recommended to take the smallest AAX and the smallest AAXC files + voucher.\n\n#### DEBUG_USEAAXSAMPLE\n\nFull path and file name of the AAX sample file. The file must come from your own Audible account or the script will not be able to process it.\n\nAllowed values:  \n - `sample.aax` =\u003e file name (must be in BALD directory)  \n - 'false' =\u003e normal behavior\n\n\u003e **Example config:**  \n\u003e `DEBUG_USEAAXSAMPLE=sample.aax`\n\n\u003e **Note:**\n\u003e This setting is ignored when using the container. You MUST use volume mapping instead.\n\n#### DEBUG_USEAAXCSAMPLE\n\nFile name of the AAXC sample file. The file must come from your own Audible account or the script will not be able to process it.\nDo not forget to put aside the voucher file for it.\n\nAllowed values:  \n - `sample.aaxc` =\u003e file name (must be in BALD directory)  \n - 'false' =\u003e normal behavior\n\n\u003e **Example config:**  \n\u003e `DEBUG_USEAAXCSAMPLE=sample.aaxc`\n\n\u003e **Note:**\n\u003e This setting is ignored when using the container. You MUST use volume mapping instead.\n\n# Anti-piracy notice\n\n**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 audiobook in the same manner that the official audiobook playing software does.\n\n**Please only use this application for gaining full access to your own audiobooks for archiving/conversion/convenience. DeDRMed audiobooks should not be uploaded to open servers, torrents, or other methods of mass distribution. No help will be given to people doing such things. Authors, retailers, and publishers all need to make a living, so that they can continue to produce audiobooks for us to hear, and enjoy.**\n\nThis blurb is borrowed from the \u003chttps://apprenticealf.wordpress.com/\u003e page.\n\n# License\n\nMIT License\n\nCopyright (c) [2025] [damajor @ \u003chttps://github.com/damajor\u003e]\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdamajor%2Fbald","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdamajor%2Fbald","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdamajor%2Fbald/lists"}