Files
audiobook-player/README.md
T
nmemmertandClaude Sonnet 5.5 429a72f2c3
build / check (push) Successful in 10s
build / image (push) Successful in 31s
New headphones app icon set, hardened streaming and playback, download removal controls
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 14:11:31 -04:00

3.2 KiB

Audiobook Player

A web player for an OpenAudible library, with user accounts, per-user listening progress synced across devices, and an iPhone-friendly layout. Python 3 standard library only.

Setup

python3 server.py setup          # OpenAudible login the server uses (shared by all accounts)
python3 server.py adduser NAME   # create a player account
python3 server.py serve          # --upstream http://HOST:8000 --port 8080

Then open http://<server-ip>:8080 and sign in. The first account (and the PLAYER_USER default in Docker) is an admin. Admins manage users at /admin. Other commands: users, passwd NAME, deluser NAME.

Only MP3/M4B files can be played in a browser; convert Audible .aax/.aaxc books in OpenAudible first.

Notes

  • Credentials and user data live in config.json, users.json, sessions.json, progress_users.json (git-ignored).
  • Only read-only OpenAudible endpoints are proxied; admin commands and import are blocked.
  • Traffic is plain HTTP. Use a VPN (e.g. Tailscale) or a TLS reverse proxy for access outside your home network.

Docker

# .env next to docker-compose.yml
OPENAUDIBLE_USER=...
OPENAUDIBLE_PASSWORD=...
PLAYER_USER=nate          # default account, created on first start
PLAYER_PASSWORD=...

docker compose up -d, then sign in at port 8080. The default account is only created if it doesn't exist, so changing its password later with docker exec -it audiobook-player python server.py passwd nate sticks. Add more people with adduser.

Offline listening

Tap the ↓ on a book (or "Download" in the player) to save it on the device. Downloaded books show a ✓, and the "Downloaded only" view lists them. They play with no connection to the server, and progress syncs when you're back online.

  • Keep the app open while a download runs; iOS pauses pages in the background.
  • The audio is stored in the browser (IndexedDB). iOS counts it against the site's storage quota, which is much larger once the site is added to the Home Screen.
  • To open the app itself offline, serve it over HTTPS. Browsers only allow the service worker (sw.js) on secure origins. Put a reverse proxy with a certificate in front of port 8080 (and a domain name). Over plain HTTP, downloads still play but the page can't load without a connection.

Troubleshooting playback

Run this on the player server (or docker exec -it audiobook-player python server.py check):

python3 server.py check

It logs in to OpenAudible, lists a few books' files, and tests whether each file can stream to a phone. iPhones will only play audio from a server that answers byte-range requests; if OpenAudible doesn't, the player server emulates them (seeking in very large books is slower). The container's log (docker logs audiobook-player) notes when that happens and records any upstream errors.

The player also recovers by itself from dropped connections and stalls (it reloads from the same spot, up to four times), and your position is saved every few seconds, on pause, and when the page is closed or backgrounded.

Icons

python3 tools/make_icons.py regenerates the app icons (needs Pillow).