Skip to content

About

Play Audible from the command line / API

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

audctl

CI

Repository: github.com/SkyeClover/AudibleFromTheCommandLine

Terminal-first helper for your Audible library: sign in once (including SMS / authenticator prompts), index titles and ASINs into a local SQLite database, then open the normal web player by title without clicking through the library every time.

Playback still happens in a browser (Chromium/Chrome/Edge when available, otherwise your OS default). DRM stays in the browser. This project is not affiliated with Audible or Amazon and is not an official product; the library list uses the unofficial audible Python package (internal API), which can break if Amazon changes endpoints or policies.

Contributing: see CONTRIBUTING.md. Security: see SECURITY.md.

Typical workflow

First start

  1. Run audctl with no arguments (or audctl setup first if you prefer explicit steps).
  2. If no API credentials exist yet, you are prompted for email and password (password is hidden). Amazon may ask for authenticator codes, SMS/email codes, or a CAPTCHA—follow the on-screen prompts. Wrong password / account lockouts surface as clear errors instead of a generic failure. At the SMS/email verification step, the tool submits Amazon’s page first (so a code can actually be sent), then offers [r] resend if the page exposes a resend control—if nothing arrives, check spam, wait a minute, confirm -m marketplace matches your account, or finish sign-in in a normal browser.
  3. You are offered a browser for a one-time web login as well (Chromium/Chrome/Edge when available, otherwise the OS default—see AUDCTL_PREFER_DEFAULT_BROWSER). Accept unless you only care about metadata: the web player needs browser cookies for audio.
  4. Your library is synced into $XDG_STATE_HOME/audctl/library.db (ASIN, title, authors, narrators, runtime when the API returns them).
  5. A terminal UI opens: filter with /, S sync, T toggle “tracked”, P open the web player for the selected row (same browser strategy as audctl play).

Every later start

  • Run audctl (or audctl tui) to open the same UI. Use audctl sync to refresh the index after new purchases.

Command-line play by title

After sync, audctl play --title "…" resolves against the SQLite index (tracked titles first), then opens /webplayer?asin=…. If Chromium/Chrome/Edge is not on PATH, audctl play falls back to the system default browser using the same multi-strategy opener as web login (webbrowser, then Windows start / rundll32, xdg-open, etc.). If every method fails, the URL is printed and the command exits with code 7—set AUDCTL_CHROMIUM_BINARY or open the printed URL manually.

Test the whole flow again (clean slate)

From the project directory (with your venv activated if you use one):

audctl reset --force --yes --purge-browser-profile

That removes API credentials (audible_credentials.json), library index (library.db), optional legacy library_index.json, and optionally the audctl Chromium profile (web cookies). It does not delete $XDG_CONFIG_HOME/audctl/config.toml (marketplace, paths, etc.).

Then run:

audctl

You should get the first-time prompts again (or run audctl setup explicitly).

Log out / reset (what exists today)

Goal Command
Full local reset (re-test setup from scratch) audctl reset --force then confirm; add --yes to skip the prompt; add --purge-browser-profile to also wipe the Chromium data dir.
Web session only (Chromium cookies for audctl play) Sign out in the browser, or audctl logout --purge-profile --force.
Amazon account Use Amazon / Audible account pages to sign out or remove “Audible on iPhone” style devices; audctl cannot change your Amazon password.

Requirements

  • Python 3.10 or newer (3.13 supported; the audible wheel set may lag on very new interpreters—see PyPI).
  • Network access for login and sync.

Install

From a clone of the GitHub repository:

git clone https://github.com/SkyeClover/AudibleFromTheCommandLine.git
cd AudibleFromTheCommandLine
python -m venv .venv
source .venv/bin/activate          # Windows: .venv\Scripts\activate
pip install -e ".[dev]"

Or install from the clone root with pipx (no dev extras):

cd AudibleFromTheCommandLine
pipx install .

Entry point: audctl (or python -m audctl).

TUI keys

Key Action
/ Focus the filter box
S Re-sync library from Audible (background)
T Toggle “tracked” for the highlighted row
P Open web player for that ASIN (Chromium or default browser)
Q Quit

Commands

Command Description
(no args) First-time setup if needed, then TUI.
audctl setup API login wizard (-m / --marketplace for country code).
audctl sync Refresh SQLite index from your library.
audctl tui Open the TUI only.
audctl login Web sign-in for playback cookies (Chromium when available, else default browser).
audctl play / resolve / urls / stop / … Same as before (see --help).
audctl init-config Write config.toml (--marketplace sets host + country together).
audctl status Profile paths, API credential presence, library row count.
audctl reset Delete local credentials + library DB (+ optional --purge-browser-profile). Requires --force; use --yes for scripts.
audctl logout Instructions, or --purge-profile --force to delete only the Chromium profile.
audctl serve HTTP JSON API on http://127.0.0.1:8765 by default (see below).

Run audctl serve on boot (recommended)

Use a systemd user unit so the API survives reboots after you log in (or use linger so it starts at boot without a GUI session).

cd ~/AudibleFromTheCommandLine
python3 -m venv .venv && .venv/bin/pip install -e .
mkdir -p ~/.config/systemd/user
cp deploy/systemd/audctl-serve.service ~/.config/systemd/user/
# Edit the file if your clone path is not ~/AudibleFromTheCommandLine
systemctl --user daemon-reload
systemctl --user enable --now audctl-serve.service

Boot before any user logs in (headless or pre-login):

sudo loginctl enable-linger "$USER"

Optional secrets (e.g. AUDCTL_HTTP_TOKEN): add EnvironmentFile=-%h/AudibleFromTheCommandLine/deploy/audctl-serve.env under [Service] in the unit, then create that file with KEY=value lines.

Docker (optional)

If you prefer a container (Chromium inside the image + host X11 + bind-mounted audctl config/state), use deploy/docker-compose.yml. Copy deploy/audctl-docker.env.example → deploy/.env, adjust paths, then:

docker compose -f deploy/docker-compose.yml --env-file deploy/.env up -d --build

This publishes 8765 on the host. Axiom in Docker can use http://host.docker.internal:8765/v1/play. The image uses Debian’s /usr/bin/chromium (not snap); your mounted profile directory should be the one audctl is configured to use.

HTTP API (audctl serve)

Run on the machine that has your Audible login / browser (or use host.docker.internal from a container with correct networking).

audctl serve --host 127.0.0.1 --port 8765

Use --host 0.0.0.0 --port 8765 only when other machines or Docker containers must reach the API on the LAN (prefer firewall + AUDCTL_HTTP_TOKEN).

Discovery: GET / returns a list of routes and short descriptions.

Method Path Body (JSON) Response
GET / — Service name, version, endpoint list.
GET /health — { "status": "ok" }
GET /v1/status — Same fields as audctl status (paths, library_items, credentials present, …).
POST /v1/play { "asin": "B0…" } and/or { "title": "…" }, optional headless, offscreen, offscreen_position Opens web player or search; search defaults to offscreen when not headless. Returns via, pid, url, asin, resolver.
POST /v1/stop { "signal": "term" } or "kill" Best-effort: signals Chromium using the configured profile (see audctl stop).
POST /v1/sync {} Refreshes library DB (requires prior audctl setup).
POST /v1/resolve { "title": "…" } and/or { "asin": "B0…" } { "ok": true, "result": { … } } (same shape as CLI resolve --json).

Examples:

curl -sS http://127.0.0.1:8765/
curl -sS http://127.0.0.1:8765/v1/status
curl -sS -X POST http://127.0.0.1:8765/v1/play -H 'Content-Type: application/json' -d '{"asin":"B012345678","headless":false}'
curl -sS -X POST http://127.0.0.1:8765/v1/play -H 'Content-Type: application/json' -d '{"title":"Some Book","offscreen":true}'
curl -sS -X POST http://127.0.0.1:8765/v1/stop -H 'Content-Type: application/json' -d '{"signal":"term"}'
curl -sS -X POST http://127.0.0.1:8765/v1/resolve -H 'Content-Type: application/json' -d '{"title":"Some Book"}'
curl -sS -X POST http://127.0.0.1:8765/v1/sync -H 'Content-Type: application/json' -d '{}'

Security: by default there is no authentication and responses use CORS * for simple local scripting. Set AUDCTL_HTTP_TOKEN to require Authorization: Bearer <token> on every route except GET / and GET /health. Bind to 127.0.0.1 only; if you must expose the API, put TLS + auth (reverse proxy, API gateway) in front.

What works vs caveats

Area Works Caveats
Library index audctl sync via unofficial audible client; SQLite for fast local match. Subject to Amazon / Audible changes; respect their ToS.
2FA / SMS Prompted in the terminal during setup. CAPTCHA flows may need you to read a URL or image per Amazon’s challenge.
Playback Chromium + official web player URL. Separate from API tokens—you still need a logged-in browser profile for audio.
Snap Chromium SNAP_USER_COMMON default profile path. You may need AUDCTL_CHROMIUM_PROFILE_DIR under ~/snap/chromium/common/… if SingletonLock errors appear.

Configuration

Variable / file Purpose
$XDG_CONFIG_HOME/audctl/config.toml audible_host, marketplace_country, chromium_profile_dir, etc.
$AUDCTL_MARKETPLACE Marketplace country code (us, uk, …).
$AUDCTL_AUDIBLE_HOST Override web host for player URLs.
$AUDCTL_CHROMIUM_PROFILE_DIR Chromium profile for web session.
$AUDCTL_PREFER_DEFAULT_BROWSER If 1 / true, skip Chromium and always use the OS default browser for web login.
$AUDCTL_ALLOW_SEARCH_SCRAPE Last-resort HTML search for resolve when nothing else matches.
$AUDCTL_HTTP_TOKEN If set, audctl serve requires Authorization: Bearer … (except GET / and GET /health).
$AUDCTL_CHROME_OFFSCREEN_POSITION X,Y for --offscreen Chromium launches (default 10000,200).
$AUDCTL_LIBRARY_INDEX Legacy JSON [{title, asin}] if you still use it (SQLite is preferred).

API credentials are stored under $XDG_STATE_HOME/audctl/audible_credentials.json (encrypted by the audible library). Config files written by audctl init-config use mode 600 on POSIX.

License

MIT — see LICENSE. Changelog: CHANGELOG.md.

Development

python3 -m venv .venv && . .venv/bin/activate
pip install -e ".[dev]"
pytest

See CONTRIBUTING.md for branching, PR expectations, and the checklist after you create the GitHub remote (e.g. add [project.urls] in pyproject.toml). CI runs pytest on Ubuntu and Windows for Python 3.10–3.13 (see .github/workflows/ci.yml).

Stretch ideas

  • MPRIS / playerctl for pause–resume.
  • Home Assistant–friendly envelopes for serve.

About

Play Audible from the command line / API

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages