A small command-line tool that lets KOReader (or any other program) read text
aloud through the ReadSpeaker voices your PocketBook e-reader already has. It
takes a sentence, hands it to the PocketBook engine that ships on the device,
and writes a plain .wav file back.
It ships nothing of PocketBook's — no voices, no engine libraries, no licence document. It only calls what is already installed on your own device using your own paid-for voices.
Works for me and one other tester across three physical devices. Not a polished product; expect to open a terminal.
Supported firmware (tested working): PocketBook U700 series, firmware
6.8.0 up to and including 6.8.3687.
Not supported (yet): 6.8.4083 and later, including 6.10.x. On those
versions the licence step is fixed (as of this build) but audio still plays
silent — a separate issue in the newer engine that has not been diagnosed. If
you are on a newer firmware and want to help, see Known issues below.
- A PocketBook e-reader on a supported firmware. (Era, Era Color, InkPad X have all been tested.)
- At least one ReadSpeaker voice installed via the PocketBook menu: Settings → Text-to-speech. Whichever voice PocketBook itself can read a book aloud with, this helper can use.
- If you intend to use it with KOReader specifically: any recent audiobook.koplugin that supports the platform-native backend (v0.1.17.7+). Adapter for that protocol is on the roadmap; for now the helper is a plain CLI that any caller can drive.
Over USB, copy pbtts from this repo onto the device somewhere the plugin can
reach it. If you are using it with audiobook.koplugin, the plugin looks in:
/mnt/ext1/applications/koreader/plugins/audiobook.koplugin/pbtts/pbtts
Copy pbtts there, unplug USB, and start KOReader. That is the whole install
— no jailbreak, no SSH, no compiling.
pbtts <out.wav> <text...> # synthesize text → mono 22 kHz WAV
pbtts --probe # list all installed voices + the chosen one
pbtts --genlicense # (re)generate the cached licence document
pbtts --selftest # synth a fixed sentence to /tmp/pbtts_selftest.wav
pbtts --daemon # long-lived daemon (engine loaded once)
The daemon accepts requests on /tmp/pbtts_req.fifo and writes replies to
/tmp/pbtts_resp.fifo. Line-based, tab-delimited:
<speed>\t<out.wav>\t<text> → ok
STOP → drop any buffered audio, keep engine loaded
QUIT → exit
First match wins:
PBTTS_VOICEenvironment variable — either a voice-pack directory (en_gb_bridget) or a speaker name (bridget). Explicit override.ttslanguage=in/mnt/ext1/system/config/global.cfg— whichever voice PocketBook's own reader is set to. This is the usual case.- If exactly one voice is installed, that one.
- Otherwise the alphabetically first installed voice, with a warning.
pbtts --probe shows what each rule would pick.
| variable | purpose | default |
|---|---|---|
PBTTS_VOICE |
force a specific voice (pack or speaker) | (auto-detect) |
PBTTS_VERBOSE / GUUS_VERBOSE |
print detailed diagnostics on stderr | off |
GUUS_SPEED |
speech rate, 100 = normal (50–300 clamped) | 100 |
GUUS_VOL |
software gain, 0–100 (100 = full engine output) | 100 |
PBTTS_RATE |
override sample rate (Hz) | from voice pack, else 22050 |
The GUUS_* names are historical — this project started life as a
Dutch-Guus-only helper. They still work; PBTTS_* aliases are on the list.
Requires a Zig-provided cross-compiler (grabs a matching glibc):
pip install --user ziglang
python3 -m ziglang cc \
-target arm-linux-gnueabi.2.19 -mfloat-abi=soft \
-O2 -s pbtts.c -o pbtts -ldl -lm
ABI flags must end up as 05000200 (soft-float EABI5):
od -An -tx4 -j36 -N4 pbtts # expect 05000200
Anything else, and it will not run on the device.
The PocketBook firmware ships the VoiceText / ReadSpeaker engine, engine libraries, and — after you buy a voice — the voice data. It also ships a "licence document" (a device-locked signed blob) that the engine reads before producing audio. Without that document, the engine works but reads a demo watermark.
pbtts dlopens the vendor's own libraries by name and calls their public
functions to (a) ask the engine to mint the licence document via
VTAPI_SetUserKeyword("pocketbook"), cache it as verification.txt next to
the binary, and (b) load a voice and synthesize each sentence to a WAV via
VT_LOADTTS_EMB_<LANG> and VT_TextToFile_<LANG>. All the code the helper
runs is on the device already; the helper only knows which functions to call
and in which order.
- Firmware
6.8.4083and later — licence generation works (as of this build; see the version-suffixed symbol fix), but playback plays silent audio. Not yet diagnosed. If you have such a device and want to help: send the output ofPBTTS_VERBOSE=1 ./pbtts /tmp/t.wav "hello"and the contents of/ebrmain/cramfs/lib/libttspm.so.1.0.0and/ebrmain/cramfs/lib/libvtapi.so. - Voices with typographic punctuation (en-dashes, curly quotes) are
converted to CP1252 in the helper. The Arabic pack uses CP1256 and is
detected from its
vtpath.ini. - Word-level highlight timing is estimated, not real: the engine gives us no phoneme timing.
- Not a redistribution of any PocketBook code, voice data, engine library,
or licence document. The repo ships one C source file, one small ARM
binary that only calls into libraries already on your device, and this
README. If you do not own a PocketBook with a paid voice installed,
pbttscannot do anything. - Not affiliated with, endorsed by, or supported by PocketBook or ReadSpeaker. Please do not send them bug reports about it.
MIT — see LICENSE.