{"id":47144484,"url":"https://github.com/stradichenko/audiobook.koplugin","last_synced_at":"2026-06-01T03:05:14.179Z","repository":{"id":343778572,"uuid":"1157951969","full_name":"stradichenko/audiobook.koplugin","owner":"stradichenko","description":"A plugin to give TTS-capabilities, includes bluetooth controllers.","archived":false,"fork":false,"pushed_at":"2026-05-31T23:44:09.000Z","size":1086,"stargazers_count":67,"open_issues_count":22,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2026-06-01T01:17:37.569Z","etag":null,"topics":["audio-streaming","audiobooks","koreader-plugin","koreader-plugins","tts-engines"],"latest_commit_sha":null,"homepage":"","language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stradichenko.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-14T15:07:10.000Z","updated_at":"2026-05-31T23:43:28.000Z","dependencies_parsed_at":"2026-04-20T19:00:42.660Z","dependency_job_id":null,"html_url":"https://github.com/stradichenko/audiobook.koplugin","commit_stats":null,"previous_names":["stradichenko/audiobook.koplugin"],"tags_count":119,"template":false,"template_full_name":null,"purl":"pkg:github/stradichenko/audiobook.koplugin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stradichenko%2Faudiobook.koplugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stradichenko%2Faudiobook.koplugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stradichenko%2Faudiobook.koplugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stradichenko%2Faudiobook.koplugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stradichenko","download_url":"https://codeload.github.com/stradichenko/audiobook.koplugin/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stradichenko%2Faudiobook.koplugin/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33757791,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-01T02:00:06.963Z","response_time":115,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["audio-streaming","audiobooks","koreader-plugin","koreader-plugins","tts-engines"],"created_at":"2026-03-12T23:08:54.006Z","updated_at":"2026-06-01T03:05:14.172Z","avatar_url":"https://github.com/stradichenko.png","language":"Lua","funding_links":["https://www.patreon.com/8153512/join","https://github.com/sponsors/stradichenko","https://buymeacoffee.com/stradichenko"],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"new_audio_logo.svg\" alt=\"Audiobook Read-Along logo\" width=\"200\"\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003e\n  Audiobook Read-Along Plugin for KOReader\n\u003c/h1\u003e\n\n\u003ch3 align=\"center\"\u003e\n\n![License: AGPL-3.0](https://img.shields.io/badge/license-AGPL--3.0-blue)\n![Platform](https://img.shields.io/badge/platform-Kobo%20%7C%20Kindle%20%7C%20PocketBook%20%7C%20Linux-blue)\n![Android](https://img.shields.io/badge/Android-supported-brightgreen)\n![TTS](https://img.shields.io/badge/TTS-Piper%20%7C%20espeak--ng%20%7C%20Android-green)\n\n\u003c/h3\u003e\n\n\u003ch4 align=\"center\"\u003e\n  Consider supporting:\u003cbr\u003e\u003cbr\u003e\n  \u003ca href=\"https://www.patreon.com/8153512/join\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Patreon-F96854?style=for-the-badge\u0026logo=patreon\u0026logoColor=white\" alt=\"Patreon\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/sponsors/stradichenko\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/sponsor-30363D?style=for-the-badge\u0026logo=GitHub-Sponsors\u0026logoColor=#EA4AAA\" alt=\"GitHub Sponsors\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://buymeacoffee.com/stradichenko\"\u003e\n    \u003cimg src=\"https://raw.githubusercontent.com/pachadotdev/buymeacoffee-badges/main/bmc-donate-white.svg\" alt=\"BuyMeACoffee\"\u003e\n  \u003c/a\u003e\n\u003c/h4\u003e\n\n\u003ch4 align=\"center\"\u003e\n\n[![Share on X](https://img.shields.io/badge/-Share%20on%20X-gray?style=flat\u0026logo=x)](https://x.com/intent/tweet?text=Audiobook%20Read-Along%20for%20KOReader!%20TTS%20with%20word%20highlighting%20on%20e-readers.\u0026url=https://github.com/stradichenko/audiobook.koplugin\u0026hashtags=KOReader,TTS,eink)\n\n\u003c/h4\u003e\n\nText-to-speech for [KOReader](https://github.com/koreader/koreader) with synchronized word highlighting, automatic page turns, and Bluetooth audio support. Works offline on Kobo, Kindle, Android, and Linux.\n\n**Also available:**\n\n* [Audio] Play music files (MP3, FLAC, OGG, and more)\n* [Books] Play audiobooks with scrubber seek, chapter navigation, and sleep timer\n* [Sync] Storyteller compatibility; EPUB 3 Media Overlays support (work in progress)\n\n## Quick start\n\n### 1. Download and copy the plugin\n\nDownload the **`.zip` file** from the [latest release](https://github.com/stradichenko/audiobook.koplugin/releases/latest) (look for `audiobook-koplugin-v*.zip` under **Assets**). Do **not** download \"Source code (zip)\" -- that only contains the Lua sources without the bundled TTS engines.\n\nUnzip it and copy the `audiobook.koplugin` folder into KOReader's plugins directory:\n\n| Platform | Path |\n|----------|------|\n| Kobo | `.adds/koreader/plugins/` |\n| Kindle | `koreader/plugins/` |\n| Linux | `~/.config/koreader/plugins/` |\n| Android | `/sdcard/koreader/plugins/` |\n| PocketBook | `applications/koreader/plugins/` |\n\nRestart KOReader after copying.\n\n### 2. Install a TTS engine (if not using the pre-built release)\n\nThe pre-built release from step 1 **already includes espeak-ng and Piper** -- no extra install needed on Kobo or Kindle. Skip to step 3.\n\nIf you cloned the repository instead:\n\n**Kobo** -- install espeak-ng via SSH or the terminal emulator (Menu \u003e More tools \u003e Terminal emulator):\n\n```bash\nopkg update \u0026\u0026 opkg install espeak-ng\n```\n\nIf `opkg` is unavailable, grab the `.ipk` from [nickel-packages](https://github.com/nickel-packages/packages) and run `opkg install /mnt/onboard/espeak-ng*.ipk`.\n\n**Linux** -- `sudo apt install espeak-ng`\n\n**Android (Boox, etc.)** -- the pre-built release includes `tts_helper.dex`, which bridges to the device's built-in TTS engine (Google, Samsung, etc.). Just unzip and copy the folder like any other platform. No extra steps needed.\n\nIf you cloned the repo instead of downloading a release, build the `.dex` manually (requires Android SDK):\n\n```bash\ncd audiobook.koplugin/android/\n./build-dex.sh\n```\n\nThe bundled espeak-ng and Piper binaries are for Linux-based e-readers and will not run on Android. See [Android support](#android-support) for details.\n\n### 3. Start reading\n\n- **Long-press a word** to open the dictionary popup, then tap **Read aloud from here**.\n- Or **select a paragraph**, then tap **Read aloud from here** in the selection menu.\n- Or go to **Tools \u003e Audiobook Read-Along \u003e Start reading from current page**.\n\n## Optional: Piper neural TTS\n\nPiper sounds much more natural than espeak-ng. It runs fully offline on Kobo's ARM processor (~40 MB for engine + voice model). The [pre-built release](https://github.com/stradichenko/audiobook.koplugin/releases/latest) already includes Piper and a default voice (`en_US-danny-low`). For faster load times on Kobo, `low` quality voices like this one are recommended (see [Choosing a voice](#choosing-a-voice)). To build a bundle yourself, see [Building from source](#building-from-source).\n\nSwitch between espeak-ng and Piper any time from **Tools \u003e Audiobook Read-Along \u003e Voice settings**.\n\n### Choosing a voice\n\nListen to samples and pick a voice: [rhasspy.github.io/piper-samples](https://rhasspy.github.io/piper-samples/)\n\nVoices come in four quality levels:\n\n| Quality | Sample rate | Size | Notes |\n|---------|-------------|------|-------|\n| low | 16 kHz | ~15 MB | **Recommended for Kobo** -- fast load, low RAM |\n| medium | 22 kHz | ~60 MB | Better quality, but slower to load on Kobo |\n| high | 22 kHz | ~100 MB | Best quality, more RAM/CPU |\n\n\u003e On Kobo (512 MB RAM), `low` voices are recommended. `medium` works but the model takes noticeably longer to load. Not every voice is available at every quality level -- check HuggingFace for what's offered.\n\n### Downloading additional voices\n\nEvery voice needs two files: a `.onnx` model and a `.onnx.json` config. Place both in `audiobook.koplugin/piper/`.\n\nVoices are hosted on HuggingFace. The URL pattern is:\n\n```text\nhttps://huggingface.co/rhasspy/piper-voices/resolve/main/\u003clang\u003e/\u003clang_REGION\u003e/\u003cspeaker\u003e/\u003cquality\u003e/\n```\n\nFor example, to download **en_US-lessac-medium**:\n\n```bash\ncd audiobook.koplugin/piper/\ncurl -LO https://huggingface.co/rhasspy/piper-voices/resolve/main/en/en_US/lessac/medium/en_US-lessac-medium.onnx\ncurl -LO https://huggingface.co/rhasspy/piper-voices/resolve/main/en/en_US/lessac/medium/en_US-lessac-medium.onnx.json\n```\n\nOr for **en_US-ryan-low**:\n\n```bash\ncurl -LO https://huggingface.co/rhasspy/piper-voices/resolve/main/en/en_US/ryan/low/en_US-ryan-low.onnx\ncurl -LO https://huggingface.co/rhasspy/piper-voices/resolve/main/en/en_US/ryan/low/en_US-ryan-low.onnx.json\n```\n\nBrowse all available voices: [huggingface.co/rhasspy/piper-voices](https://huggingface.co/rhasspy/piper-voices/tree/main)\n\n## PocketBook audio\n\nOn PocketBook, the system ALSA configuration routes all audio through a Loopback card. The `tts_sm` PCM device (defined in `/etc/asound.conf`) chains through `softvol -\u003e dmix -\u003e hw:Loopback,0`. A system process (`alsaloop`) reads from `hw:Loopback,1` and plays to the physical codec (`hw:0`). The plugin bundles a small ALSA player (`wav-play`) that opens `tts_sm` directly, avoiding any dependency on `aplay` or GStreamer. Bluetooth output on PocketBook uses the standard BlueZ + `alsaloop` path managed by the firmware.\n\n## Bluetooth audio (Kobo)\n\nThe plugin outputs audio through a Bluetooth A2DP connection when a BT device is paired. The connection is managed through the plugin menu:\n\n**Tools \u003e Audiobook Read-Along \u003e Bluetooth settings**\n\nTwo Bluetooth stacks are supported, auto-detected at runtime:\n\n| Stack | Devices | Audio path |\n|-------|---------|------------|\n| **MTK** (mtkbtmwrpc) | Clara 2E, Sage, Libra Colour | GStreamer persistent pipeline |\n| **BlueZ** (bluetoothd) | Libra 2 / Io | aplay via ALSA |\n\nOn MTK devices the BT audio pipeline uses an exclusive abstract socket. If audio stops working after a crash, restart KOReader -- the plugin kills orphan processes on startup.\n\n\u003e On MTK Kobo devices, the mtkbtmwrpc daemon binds a single abstract socket. Only one GStreamer pipeline can hold it at a time. The plugin keeps one persistent pipeline alive across sentences to avoid reconnection gaps. On BlueZ devices, the plugin starts `bluetoothd` and resets the HCI adapter automatically when you power on Bluetooth.\n\u003e **Known issue on MTK devices:** MBROLA voices other than `mb-en1` (UK English Male 1) may produce mid-sentence audio repeats due to a firmware bug in the MTK Bluetooth SBC encoder. This affects all MBROLA voices except `mb-en1`. See [docs/MBROLA_MTK_REPEAT_BUG.md](docs/MBROLA_MTK_REPEAT_BUG.md) for the full diagnostic report.\n\nFor the full platform audio and Bluetooth architecture (Kobo generations, Kindle, Android), see [docs/PLATFORM_AUDIO.md](docs/PLATFORM_AUDIO.md).\n\n## Playback controls\n\n| Button | Action |\n|--------|--------|\n| Rewind | Previous sentence. Hold for 3x skip. |\n| Play/Pause | Toggle playback. |\n| Forward | Next sentence. Hold for 3x skip. |\n| Close | Stop reading and dismiss the bar. |\n\nReading pauses automatically when you open a menu and resumes when you close it.\n\n## Settings\n\nAll settings are under **Tools \u003e Audiobook Read-Along**:\n\n- **Start reading from current page** - begin read-along from the current page\n- **Bluetooth settings**\n  - **Bluetooth** - pair, connect, disconnect, scan\n  - **Headset media buttons** - use play/pause/next/prev on a Bluetooth headset or speaker to control TTS playback\n  - **Disconnect alert** - notify if all BT audio devices disconnect during playback\n- **Voice settings** - TTS engine, voice, speech rate, pitch, volume, sentence/paragraph pauses (espeak-ng), sentence/paragraph gaps (Piper), word gap, clause pause. Includes **Quick start with espeak** (Piper-only) which plays the first sentence with espeak-ng while Piper loads, avoiding the ~3s cold start silence.\n- **General settings**\n  - **Audio output (PocketBook)** - ALSA device selection for PocketBook firmware quirks\n  - **Keep playing when lid is closed** - prevents device suspend so audio continues with the case closed\n  - **Hide control bar while playing** - experimental; hides the playback bar during TTS so the page is fully visible\n  - **Highlight style** - background (default), invert (best for e-ink), underline, box\n  - **Auto-advance pages** - turn pages automatically\n  - **Highlight sentences** - draw highlight on the active sentence\n- **Generate bug report** - save a diagnostic report to share when reporting issues\n- **Run device benchmark** - run a TTS performance benchmark on this device\n- **Check for updates** - fetch and install a newer release from GitHub\n\n## Tweaking \u0026 advanced configuration\n\n### Changing espeak-ng language\n\nThe **Voice settings** menu only lists English accents, but espeak-ng supports [dozens of languages](https://github.com/espeak-ng/espeak-ng/blob/master/docs/languages.md). To read in another language, set the voice code manually:\n\n1. Close KOReader completely.\n2. Open KOReader's settings file (`settings.reader.lua` in the KOReader directory).\n3. Find the `audiobook_settings` table and set `tts_voice` to the desired code:\n\n```lua\n[\"audiobook_settings\"] = {\n    [\"tts_voice\"] = \"pt-br\",\n    [\"tts_voice_label\"] = \"Portuguese (Brazil)\",\n    -- ... other settings ...\n},\n```\n\nRestart KOReader and start reading. The plugin will use the new voice immediately.\n\n\u003e **Tip:** You can also add a variant (e.g. `pt-br+f2` for female voice 2). See the [espeak-ng voice documentation](https://github.com/espeak-ng/espeak-ng/blob/master/docs/voices.md) for the full list.\n\n\n## Architecture\n\n```\naudiobook.koplugin/\n  main.lua             - entry point, menus, event hooks\n  synccontroller.lua   - coordinates audio timing with highlights\n  ttsengine.lua        - TTS synthesis, audio playback, backend detection\n  piperqueue.lua       - persistent Piper server management\n  textparser.lua       - sentence/word tokenization with positions\n  highlightmanager.lua - screen-coordinate highlight via crengine\n  playbackbar.lua      - transport controls widget\n  menubuilder.lua      - voice/highlight settings menus\n  btmanager.lua        - Bluetooth device scanning and pairing (MTK + BlueZ)\n  btui.lua             - BT menu UI and disconnect watcher\n  btmediacontrol.lua   - BT headset media buttons (AVRCP play/pause/skip)\n  benchmarkrunner.lua  - in-plugin TTS benchmark runner\n  wavutils.lua         - WAV file reading, writing, and manipulation\n  androidtts.lua       - Android TTS via JNI (DexClassLoader + TtsHelper)\n  utils.lua            - shared helpers\n  wav-play.c           - minimal ALSA WAV player for PocketBook (compiled to wav-play/wav-play)\n```\n\n### Design notes\n\n**Persistent Piper server.** On Kobo's single-core ARM, loading the ONNX model takes ~4.5 seconds. A persistent server process keeps the model in memory and accepts sentences over a FIFO. Combined with 3-sentence batching this brings the realtime factor from 0.085x (old 2-server config) to 0.329x. See [dev/benchmark/RESULTS.md](dev/benchmark/RESULTS.md) for the full analysis.\n\n**Binary-search highlight alignment.** CRe (crengine) snaps text selections to word boundaries, and proportional fonts make character-to-pixel estimates unreliable. The highlight manager uses the proportional estimate as an initial guess, then binary-searches the x coordinate by querying CRe until the selected text matches the target sentence. Converges in 2-4 queries.\n\n**Exclusive BT socket (MTK only).** Kobo's MediaTek BT firmware exposes a single abstract socket (`@kobo:mtkbtmwrpc`). The plugin keeps one GStreamer pipeline alive for the entire reading session and feeds audio through a FIFO. Orphan pipelines from crashes are killed on startup via PID files and `pkill`. On BlueZ devices (Libra 2, etc.) audio goes through standard ALSA and this socket management is not needed.\n\n**Long-sentence splitting.** Piper's attention mechanism scales quadratically with input length. On Kobo's 512 MB of RAM the server OOMs on sentences above ~1000 characters and throughput drops from ~7 ch/s at 300 chars to ~3 ch/s at 1400 chars. The text parser automatically splits any sentence longer than 300 characters at natural clause boundaries (`;` `:` `, and/but/or...` ` - `) then merges fragments shorter than 80 characters with a neighbour (below that, ~90% of synthesis time is wasted on per-request overhead) and re-splits anything still over 300 at word boundaries. See [dev/benchmark/RESULTS_LONG.md](dev/benchmark/RESULTS_LONG.md) for the full data.\n\n## Troubleshooting\n\n| Problem | Fix |\n|---------|-----|\n| Plugin not in menu | Folder must be `audiobook.koplugin` inside `plugins/`. The plugin only appears in the **Tools** menu when a book is open. Restart KOReader after copying. |\n| No sound | **Kobo/Linux:** Run `espeak-ng \"hello\" -w /tmp/t.wav \u0026\u0026 aplay /tmp/t.wav` over SSH. **PocketBook:** generate a bug report and check `wav_play_smoke_test` -- it runs wav-play against the `tts_sm` device and prints `PLAYING` on success. |\n| No audio player found (Kindle) | Pair BT headphones via the Kindle top-swipe menu **before** starting playback. If already paired, restart KOReader so the plugin re-detects the audio output. |\n| No TTS engine found | Install espeak-ng (see Quick start). |\n| No TTS engine found (Android) | Ensure `android/tts_helper.dex` is present inside the plugin folder. The pre-built release includes it; if you cloned from source, run `./build-dex.sh` in the `android/` directory. The device must also have a TTS engine installed (most do by default). See [Android support](#android-support). |\n| BT audio silent | Restart KOReader to kill orphan pipelines. Check BT is paired in the plugin menu. |\n| SSH refused on port 22 | KOReader uses port 2222: `ssh root@\u003cip\u003e -p 2222` |\n| `.adds` not visible | Enable hidden files on your OS. The folder starts with a dot. |\n\n### Filing a bug report\n\nWhen reporting a problem, please attach **both** files described below. The bug report captures your device environment (hardware, audio, settings) while the crash log captures KOReader's runtime behavior (errors, warnings, timing). Together they give the full picture needed to diagnose an issue.\n\n1. Reproduce the problem (use the plugin normally until the issue occurs).\n2. Generate the plugin bug report (see below).\n3. Locate the KOReader crash log (see below).\n4. Attach both files to your [GitHub issue](https://github.com/stradichenko/audiobook.koplugin/issues).\n\n\u003e **Tip:** Generate the report and grab the crash log **before** restarting KOReader. The crash log is truncated on every launch, so restarting may discard the relevant entries.\n\n---\n\n#### 1. Plugin bug report\n\nThe plugin's diagnostic report captures device info, TTS engine detection, audio configuration, Bluetooth status, and plugin settings. There are two ways to generate it:\n\n**Option A: From the plugin menu**\n\n**Tools \u003e Audiobook Read-Along \u003e Generate bug report**\n\nThis saves a `.txt` file to your device's root storage (see locations below).\n\n**Option B: Standalone script (when the plugin menu is not visible)**\n\nIf the plugin doesn't appear in the KOReader menu at all, you can run the report generator directly via SSH or KOReader's built-in terminal emulator (Menu \u003e More tools \u003e Terminal emulator):\n\n```bash\nsh /mnt/onboard/.adds/koreader/plugins/audiobook.koplugin/generate-report.sh   # Kobo\nsh /mnt/us/koreader/plugins/audiobook.koplugin/generate-report.sh              # Kindle\nsh /sdcard/koreader/plugins/audiobook.koplugin/generate-report.sh              # Android\n```\n\nThe report is printed to the terminal and also saved to a file. If using the terminal emulator, you can scroll up to read it on screen.\n\n**Report location:**\n\n| Platform | Report location |\n|----------|----------------|\n| Kobo | `/mnt/onboard/audiobook-bug-report-*.txt` |\n| Kindle | `/mnt/us/audiobook-bug-report-*.txt` |\n| Android | `/sdcard/audiobook-bug-report-*.txt` |\n| Linux | `~/audiobook-bug-report-*.txt` |\n\n**What the report contains:**\n\n- Device model, platform, screen size, kernel version\n- KOReader version\n- TTS engine detection results (which backends were found/missing)\n- Audio player availability (aplay, GStreamer, etc.)\n- Plugin settings (speech rate, highlight style, etc.)\n- Full ALSA configuration (`asound.conf` contents, sound card list)\n- Audio process list (alsaloop, bluealsa, etc. with PIDs)\n- wav-play binary details and smoke test result (opens `tts_sm`, plays silence, checks for `PLAYING`)\n- ALSA mixer state\n- Bluetooth hardware details (HCI devices, paired/connected devices, adapter info)\n- Memory and disk info\n\n**What the report does NOT contain:**\n\n- Book titles, content, or reading positions\n- File paths with usernames (sanitized automatically)\n- Highlights, bookmarks, or notes\n- Network information or credentials\n\n---\n\n#### 2. KOReader crash log\n\nKOReader logs all warnings, errors, and debug output to a file called `crash.log` in its installation directory. This is **not** generated by the plugin -- it is KOReader's own runtime log and captures everything that happens during a session, including TTS process spawning, fallback events, and Lua errors.\n\n**Crash log location:**\n\n| Platform | Path |\n|----------|------|\n| Kobo | `/mnt/onboard/.adds/koreader/crash.log` |\n| Kindle | `/mnt/us/koreader/crash.log` |\n| PocketBook | `/mnt/ext1/applications/koreader/crash.log` |\n| Linux | Inside the KOReader installation directory |\n| Android | No `crash.log` file -- use `adb logcat` to capture KOReader output |\n\nConnect your device via USB and copy the file. On Kobo the `.adds` folder is hidden -- enable hidden files in your file manager to see it.\n\n\u003e KOReader truncates `crash.log` to ~500 KB on every launch. If you restart KOReader before copying the file, earlier entries may be lost. Copy it while KOReader is still running or immediately after the issue occurs.\n\n---\n\n#### Why both files matter\n\n| Diagnostic question | Bug report | Crash log |\n|---------------------|:----------:|:---------:|\n| Device model, hardware specs, KOReader version, plugin version, TTS engines installed (espeak, Piper, Android), plugin settings (rate, highlight, voice) | yes | no |\n| Full ALSA configuration (asound.conf, sound cards, PCM devices), audio process list (alsaloop, bluealsa PIDs), ALSA mixer state, wav-play smoke test result | yes | no |\n| Bluetooth pairing and connection state, HCI devices, adapter info | yes | no |\n| Lua errors and stack traces, TTS process spawning and fallback events, sentence progression and page turns, timing of operations (delays, freezes), Piper server startup and delivery, device freeze or resource exhaustion | no | yes |\n\n## Device benchmark\n\nThe plugin includes a built-in benchmark that measures TTS synthesis speed on your device. It runs a fixed set of test sentences through each available engine (espeak-ng, Piper) and saves a report you can share on GitHub to help document device performance.\n\n### Running the benchmark\n\n**Tools \u003e Audiobook Read-Along \u003e Generate bug report \u003e Run device benchmark**\n\nThe benchmark synthesizes five sentences of varying length (short dialogue, narrative prose, technical text, academic text, and short fragments) with each engine and model it finds. espeak-ng tests finish in seconds; Piper tests may take several minutes on slow devices like Kobo.\n\nA progress message is shown between engine runs. The screen may appear unresponsive during individual synthesis calls -- this is expected.\n\n### Output\n\nWhen complete, a `.txt` report is saved to your device's root storage:\n\n| Platform | Report location |\n|----------|----------------|\n| Kobo | `/mnt/onboard/audiobook-benchmark-*.txt` |\n| Kindle | `/mnt/us/audiobook-benchmark-*.txt` |\n| Android | `/sdcard/audiobook-benchmark-*.txt` |\n| Linux | `~/audiobook-benchmark-*.txt` |\n\nThe report contains:\n\n- Device info (platform, model, CPU cores, RAM, kernel)\n- Plugin version\n- Per-sentence synthesis time, audio duration, file size, and realtime factor for each engine/model\n- Aggregate totals and average realtime factor\n\nNo book content, highlights, or personal data is included.\n\n### Example output\n\n```\n=== Audiobook TTS Benchmark (v0.1.5.65) ===\nGenerated: 2026-03-27T12:00:00Z\n\n── Device ──\n  platform: kobo\n  model: Kobo Clara 2E\n  cpu_cores: 1\n  memory: 510396 kB\n  kernel: 4.1.15\n\n── Test sentences ──\n  [1] short_dialogue (57 chars)\n  [2] medium_narrative (268 chars)\n  [3] medium_technical (254 chars)\n  [4] long_academic (362 chars)\n  [5] short_fragments (79 chars)\n\n── espeak-ng ──\n  short_dialogue          synth=   82ms  audio= 3200ms  size= 102444B  rt=0.03x\n  medium_narrative        synth=  310ms  audio=15800ms  size= 505244B  rt=0.02x\n  ...\n\n── Piper danny-low  (size=15.8MB, sr=16000Hz) ──\n  short_dialogue          synth= 4200ms  audio= 3100ms  size=  99244B  rt=1.35x\n  medium_narrative        synth=18200ms  audio=16800ms  size= 537644B  rt=1.08x\n  ...\n\n=== End of Benchmark ===\n```\n\nA realtime factor below 1.0x means synthesis is faster than playback (good). Above 1.0x means the user will hear pauses between sentences while the engine catches up.\n\n### Sharing your results\n\nAttach the report file to a [GitHub issue](https://github.com/stradichenko/audiobook.koplugin/issues) or include it in a bug report. Benchmark data from different devices helps the project tune batch sizes, choose default voices, and set realistic expectations for each platform.\n\n## Android support\n\nAndroid TTS is supported via a JNI bridge to the device's built-in `TextToSpeech` engine (Google, Samsung, etc.). No Termux, no extra APKs, no root required.\n\n| Feature | Status |\n|---------|--------|\n| Plugin loads in KOReader | ![Works](https://img.shields.io/badge/-works-brightgreen) |\n| Text parsing \u0026 highlighting | ![Works](https://img.shields.io/badge/-works-brightgreen) |\n| Android system TTS | ![Works](https://img.shields.io/badge/-works-brightgreen) Via JNI bridge to `TextToSpeech` API |\n| Audio playback | ![Works](https://img.shields.io/badge/-works-brightgreen) Via Android `MediaPlayer` |\n| Bundled espeak-ng / Piper | ![No](https://img.shields.io/badge/-not%20supported-red) Linux binaries, won't run on Android |\n| espeak-ng via Termux | ![Untested](https://img.shields.io/badge/-untested-yellow) May work if `espeak-ng` is in PATH |\n\n### Setup\n\nThe pre-built release from [GitHub Releases](https://github.com/stradichenko/audiobook.koplugin/releases/latest) includes `android/tts_helper.dex`. Just unzip and copy:\n\n1. Download the release zip and extract it.\n2. Copy `audiobook.koplugin/` to `/sdcard/koreader/plugins/`.\n3. Restart KOReader. The plugin auto-detects Android and initializes the JNI bridge to the device's TTS engine.\n\nIf you cloned the repo instead of using a release, build the `.dex` first (requires Android SDK + Java):\n\n```bash\ncd audiobook.koplugin/android/\n./build-dex.sh\n```\n\n### How it works\n\nThe plugin loads a small `.dex` file (`tts_helper.dex`, ~4KB) at runtime via Android's `DexClassLoader`. This helper wraps `android.speech.tts.TextToSpeech` with a polling-friendly API (since LuaJIT cannot implement Java callback interfaces). Synthesis produces standard WAV files that feed into the same pipeline used by espeak-ng and Piper.\n\nAudio playback uses Android's `MediaPlayer` instead of `aplay` or GStreamer. Pause, resume, and stop all work through the MediaPlayer API.\n\nFor the full technical analysis, see [docs/ANDROID_TTS.md](docs/ANDROID_TTS.md).\n\n### Limitations\n\n- Uses the device's default TTS voice (voice picker UI not yet implemented)\n- Word timing is estimated (Android TTS does not provide per-word callbacks when synthesizing to file)\n- First sentence may have a brief delay while the TTS engine initializes\n\n### Neural TTS engines (offline)\n\nThe plugin uses whatever engine you set as Android's default TTS. The factory default (Google or Samsung) is decent, but installing a free, open-source neural engine gives you offline voices comparable to Piper on Linux e-readers.\n\n#### Quick setup\n\n1. Install one of the engines below.\n2. Open **Android Settings → System → Languages \u0026 input → Text-to-speech output** (path varies by manufacturer skin).\n3. Set \"Preferred engine\" to the new engine, pick a voice, and tap \"Listen to an example\" to confirm.\n4. Restart KOReader. The plugin will route synthesis through the new engine automatically.\n\n| Engine | Distribution | Min Android | Models | Notes |\n|--------|--------------|-------------|--------|-------|\n| [SherpaTTS](https://f-droid.org/packages/org.woheller69.ttsengine/) | F-Droid (signed, audited) | 10+ | Piper / VITS via Sherpa-ONNX, downloaded on first launch | Single app with built-in model picker. Easiest, most trustworthy install. |\n| [VoxSherpa TTS](https://github.com/CodeBySonu95/VoxSherpa-TTS) | GitHub APK (sideload) | 11+ | Piper / VITS plus Kokoro 82M; imports any Sherpa-ONNX `.onnx` | Newest. Pick this if you want Kokoro or to drop in your own `.onnx` voices. |\n| [Sherpa-ONNX engine APKs](https://k2-fsa.github.io/sherpa/onnx/tts/apk-engine.html) | Direct APK from k2-fsa | varies | One voice per APK | Use only if you want a specific pre-bundled model and nothing else. |\n\nIf you're unsure, start with **SherpaTTS** from F-Droid. It is signed by F-Droid (no sideloading from random hosts), works on Android 10+, lets you pick models inside the app, and has a longer track record. Move to VoxSherpa later if you want Kokoro or custom `.onnx` imports.\n\n\u003e Android only allows one default TTS engine system-wide, so switching engines for KOReader changes it for every app that uses TTS (TalkBack, navigation, other readers).\n\n## Building from source\n\nThe `package-for-kobo.sh` script cross-compiles espeak-ng and wav-play for ARM and bundles the plugin into a ready-to-deploy directory. It targets ARMv7 and works for both Kobo and PocketBook. It requires [Nix](https://nixos.org/download) for the cross-compilation toolchain.\n\n```bash\n# Plugin + espeak-ng only\nbash package-for-kobo.sh\n\n# Plugin + espeak-ng + Piper neural TTS\nbash package-for-kobo.sh --with-piper\n\n# Use a specific Piper voice (default: en_US-danny-low)\nbash package-for-kobo.sh --piper-voice en_US-ryan-low\n```\n\nThe output is placed in `kobo-tts-bundle/audiobook.koplugin/`. Copy it to your device:\n\n```bash\nscp -P 2222 -r kobo-tts-bundle/audiobook.koplugin root@\u003ckobo-ip\u003e:/mnt/onboard/.adds/koreader/plugins/\n```\n\n### Installing the Piper binary manually\n\nIf you don't want to use the packaging script, you can assemble the Piper runtime yourself:\n\n1. Download the **armv7l** binary from [Piper releases (2023.11.14-2)](https://github.com/rhasspy/piper/releases/tag/2023.11.14-2).\n2. Extract `piper`, its `lib/` directory, and `espeak-ng-data/` into `audiobook.koplugin/piper/`.\n3. Download a voice model (`.onnx` + `.onnx.json`) as described in [Downloading additional voices](#downloading-additional-voices) and place them in the same `piper/` directory.\n\n\u003e The [rhasspy/piper](https://github.com/rhasspy/piper) repository was archived in October 2025. The binaries on the releases page still work and are what this plugin ships. The project continues under [OHF-Voice/piper1-gpl](https://github.com/OHF-Voice/piper1-gpl) but those newer builds have not been tested with this plugin.\n\n## To Do\n\n- Implement real word-level timing from TTS engines (SSML / phoneme callbacks)\n- Add PDF/DjVu highlight support (currently EPUB only)\n- Voice picker for Android TTS engines and voices\n- Integrate more TTS backends\n- Improve accessibility\n- Support whole audiobook production with hash-based verification\n- Evaluate plugin with other TTS models (e.g., KittenTTS)\n- Test and optimize for ultralow-quality/size voice models\n\n## License\n\nCopyright 2025-2026 gespitia - AGPL-3.0. See [LICENSE](LICENSE).\n\n| Bundled component | License |\n|-------------------|---------|\n| [KOReader](https://github.com/koreader/koreader) | AGPL-3.0 |\n| [espeak-ng](https://github.com/espeak-ng/espeak-ng) | GPL-3.0+ |\n| [Piper](https://github.com/rhasspy/piper) | MIT |\n| [Piper voices](https://huggingface.co/rhasspy/piper-voices) | MIT |\n| glibc (bundled .so) | LGPL-2.1 |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstradichenko%2Faudiobook.koplugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstradichenko%2Faudiobook.koplugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstradichenko%2Faudiobook.koplugin/lists"}