- Python 61.4%
- QML 37.8%
- C 0.7%
- Shell 0.1%
|
|
||
|---|---|---|
| .forgejo/workflows | ||
| abs_htpc | ||
| flatpak | ||
| tests | ||
| .gitignore | ||
| pyproject.toml | ||
| README.md | ||
abs-htpc — Audiobookshelf client for Home Theater PCs
A 10-foot, couch-friendly client for an Audiobookshelf server. Built for Linux HTPCs and designed to be driven entirely by a remote control or game controller — no keyboard or mouse required (though both work).
- Fullscreen, large-type UI with bold focus rings for D-pad navigation
- On-screen keyboard for server/login entry (remote-only friendly)
- Left-sidebar navigation: Home, Library, Series, Authors
- Home shelves from the server's personalized API: Continue Listening (in-progress), Next in Series (server-computed next book after you finish one), and Recently Added
- Cover-art grids, Series (books in order) and Authors browsing, book detail with chapters, now-playing transport
- Audio playback via mpv (
libmpv), with chapter jumps and ±30s skip - Listening progress synced back to the server (resume where you left off)
- Game controller support via SDL2; media keys (Play/Pause/Next/Prev/Stop)
Requirements
System packages (install via your distro):
libmpv(mpv shared library) — e.g. Archmpv, Debian/Ubuntulibmpv2/libmpv-devlibSDL2— e.g. Archsdl2, Debian/Ubuntulibsdl2-2.0-0- Python ≥ 3.10
Python dependencies (installed below): PySide6, python-mpv, httpx, qasync, PySDL2,
segno (QR codes). QR phone-login also uses the openssl CLI for an ephemeral cert.
Install
python -m venv .venv
.venv/bin/pip install -e .
Run
.venv/bin/python -m abs_htpc # or: .venv/bin/abs-htpc
On first launch you'll get the Connect screen with two options:
- Log in with your phone (QR) — recommended, no typing on the TV. The app shows a QR code; scan it with your phone, accept the one-time security warning (it uses a self-signed certificate generated per session), and sign in on your phone's keyboard. The phone talks to the app over HTTPS on your LAN; the app exchanges your login for a token and stores only the token — your password is never written to disk. (The HTPC must be reachable on its LAN port from the phone; if you run a firewall, allow inbound on the local network.)
- Enter details manually — the on-screen keyboard for server URL / username /
password (a bare host like
abs.example.comautomatically getshttps://).
Either way, the saved token means subsequent launches skip straight to the profile picker.
Multiple users / profiles
The app keeps a list of accounts, each a real Audiobookshelf login with its own library and listening progress. On launch you get a "Who's listening?" picker:
- Choose a profile to sign in instantly (its token is stored on this device).
- + Add user opens the login screen (QR or keyboard) for another account.
- Delete on a focused profile removes it.
- From the library, press Back and choose Switch user to return to the picker (or Exit to quit to the desktop).
Notes on Audiobookshelf's design: there's no "impersonate" API, so each person signs in once (their token is then remembered). Listing all server users isn't possible from a regular account — it requires admin — so profiles are the ones you've added here, not an automatic roster of everyone on the server.
Controls
| Action | Remote / Keyboard | Game controller |
|---|---|---|
| Move focus | Arrow keys | D-pad / left stick |
| Select / OK | Enter | A |
| Back | Esc | B |
| Play / Pause | Space or media key | X |
| Skip −30s / +30s | (player) ←/→ on transport | LB / RB |
| Previous / Next chapter | media Prev/Next | Left / Right trigger |
| Scrub | focus the seek bar, then ←/→ | focus seek bar, then ←/→ |
In the player, Esc/B returns to the previous screen while playback continues; use the ⏹ Stop button to end the session. From the library, Esc/B opens an Exit to desktop? prompt (with Switch user when you have profiles).
Configuration
Config (including the auth token) is stored at:
$XDG_CONFIG_HOME/abs-htpc/config.json # default: ~/.config/abs-htpc/config.json
The token is written with 0600 permissions but is not encrypted (see Notes).
Delete this file to reset / log out.
Development
.venv/bin/pip install -e ".[dev]"
.venv/bin/python -m pytest # unit tests (endpoints, book timeline)
QT_QPA_PLATFORM=offscreen .venv/bin/python tests/smoke_qml.py # QML load check
QT_QPA_PLATFORM=xcb .venv/bin/python tests/capture.py out.png # render a screenshot
Architecture
abs_htpc/
api/ endpoints.py (URL builders) + client.py (async httpx AbsClient)
config.py Account + AccountStore: multi-account config (servers, tokens, active)
backend/ Qt controllers: auth (login + profiles), library, detail,
player (mpv), input (SDL2),
pairing (QR phone-login: ephemeral HTTPS server + segno QR)
+ timeline.py (pure book-time <-> track mapping, unit-tested)
qml/ Theme singleton; Main = left-sidebar shell over a content StackView;
components (Sidebar, FocusCard, …); views (Home, Library, Series,
Authors, BookDetail, Player, ProfilePicker, ServerSetup, QrLogin)
__main__.py QApplication + qasync loop, wiring, media-key filter
The networking is async (httpx on the qasync loop). mpv runs its tracks as a
playlist; timeline.py presents the multi-file book as one continuous timeline.
Controller input is translated by an SDL2 thread into synthetic arrow-key events
plus transport signals, so the same QML focus handling serves remote and pad.
Notes / roadmap (v1 scope)
- Auth token is stored in plaintext; OS keyring integration is a future option.
- Podcasts: the data layer understands episodes, but a dedicated podcast browse UI is not yet built.
- Out of scope for v1: offline downloads, multi-user switching, casting, LIRC/IR remotes (most IR remotes already present as keyboard input via the OS).