A self hosted version of "Whispersync" which is position syncing between a Kobo ereader (served by Calibre-Web) and your audiobooks in Audiobookshelf
Listen to a chapter on your commute, then press the Kobo's native Sync button: the ebook jumps to the exact paragraph the narrator just finished. No new buttons, no separate app.
The hard part is knowing that audio second 14,203 equals page position X in the ebook. This project solves it with forced alignment: it runs aeneas against your audiobook narration and the ebook's kepub text spans, producing a per-book alignment map (tens of thousands of text fragments, each with a start time). After that, translating a position between the two formats is a table lookup.
- All alignment tooling (aeneas, espeak-ng, ffmpeg) is baked into the container; nothing is installed on the host.
- A small web UI on port 3005 lets you add a book and build its alignment map from the browser.
- The Calibre-Web side is one thin hook in
cps/kobo.py(seepatches/) that calls the container during a normal Kobo sync. Errors are swallowed, so if the container is down your native sync works exactly as before.
- Forward-only. Your position never moves backward. On any ambiguity or missing map, the sync is a no-op.
- Write-gated. Position write-back to Audiobookshelf is disabled until you
set
WHISPERSYNC_ALLOW_ABS_WRITE=1. - The hook never breaks the native sync: every whispersync error is caught.
- Audio → Kobo direction is live and verified end to end, and lands in a single Sync press (the hook asserts fresh audio positions before Calibre-Web builds its sync response).
- Kobo → Audiobookshelf write-back is included but off by default; enable it
with
WHISPERSYNC_ALLOW_ABS_WRITE=1once you trust the mapping.
- Calibre-Web with the Kobo sync endpoint enabled, and the ability to mount a
patched
cps/kobo.pyinto its container - Audiobookshelf with an API token
- Your ebook in kepub format (the alignment maps use koboSpan anchors)
- The matching audiobook files on disk
- Docker
-
cp .env.example .envand fill it in. -
docker compose up -d --buildOr skip the build and use the prebuilt image (published automatically from this repo by GitHub Actions, x86-64): in
docker-compose.yml, delete thebuild: .line and change theimage:line toimage: ghcr.io/jstriblet/open-whispersync:latest
then run
docker compose up -d. -
Open
http://YOUR-SERVER-IP:3005and add your book. What the fields mean:Field Needed? What it is Calibre book id required The number in the Calibre-Web book page URL ( .../book/129→129)kepub path (container) required to build The .kepubfile as seen inside the container — yourMEDIA_ROOTmount appears at/media, so e.g./media/books/Author/Title.kepubaudio mp3 path (container) required to build The audiobook file, same rule: /media/audiobooks/.../Title.mp3ABS library item id required to sync From the Audiobookshelf web app: open the audiobook and copy the id from the URL ( .../item/<id>)Title optional Display name in the book list and logs ABS media id optional Stored for reference; sync does not use it Then press Build. Alignment is CPU-heavy: expect roughly an hour for a long novel. The build log streams on the same page, and the book syncs only after the map build finishes.
-
Install the Calibre-Web hook (makes a timestamped backup, checks anchors, refuses anything it does not recognize, and syntax-checks the result):
python3 patches/install_hook.py /path/to/calibre-web/cps/kobo.py
Then restart Calibre-Web.
--uninstallreverses it cleanly, and re-running after a Calibre-Web upgrade re-applies it. Manual instructions live at the top ofpatches/whispersync_kobo_hook.pyif the installer refuses your version. -
Press Sync on the Kobo.
| Variable | Meaning |
|---|---|
MEDIA_ROOT |
Audiobook library root (read-only mount) |
CALIBRE_DB |
Path to Calibre-Web's app.db inside the container |
ABS_URL / ABS_TOKEN |
Audiobookshelf server and API token |
KOBO_USER_ID |
Calibre-Web user whose reading state is synced |
WHISPERSYNC_ALLOW_ABS_WRITE |
0 = never write to Audiobookshelf (default) |
If this project saved your reading spot or saved you from buying into a locked ecosystem, you can fuel the next alignment map:
MIT for everything in this repository except patches/, which modifies
Calibre-Web (GPL-3.0) and is therefore licensed GPL-3.0.
