67 lines
3.2 KiB
Markdown
67 lines
3.2 KiB
Markdown
# Audiobook Player
|
|
|
|
A web player for an [OpenAudible](https://openaudible.org) library, with user accounts, per-user listening progress synced across devices, and an iPhone-friendly layout. Python 3 standard library only.
|
|
|
|
## Setup
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
# .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`):
|
|
|
|
```bash
|
|
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).
|