AI audiobook generation for a Russian-language bookstore
For Knigopoisk, a Russian-language e-book and audiobook store, we built an AI audiobook generation pipeline that turns a digital edition into a narrated audiobook product: text extraction and cleanup, optional character voices, speech synthesis, MP3 encoding, tagging and publishing to the catalog. Staff launch it from the admin panel, and it also starts automatically when a customer pays for an audiobook that has no audio file yet.
Step one: a Russian TTS benchmark
Before writing pipeline code, we compared Russian speech synthesis engines on CPU-only hardware, since a 4 GB Quadro T2000 was too small for GPU inference of the larger models. The same short Russian sample went through Russian-specialist engines (F5-TTS Russian, ESpeech, Silero v5, Vosk-TTS, Piper), multilingual models (CosyVoice3, Chatterbox, VibeVoice, XTTS-v2, Bark) and cloud baselines including Gemini 2.5 TTS, recording voices, synthesis time and license for each.
Three findings shaped the build:
- Stress marks matter. We produced a stressed copy of the sample with RUAccent and A/B-tested engines on it. ESpeech was the first engine in the set that actually consumed
+stress marks instead of reading them aloud or ignoring them. - Loudness checks miss gibberish. CosyVoice2 doesn't support Russian and emits random-letter speech that looks normal on a level meter, while CosyVoice3 works. We added Vosk ASR word-recall scoring to catch unintelligible output.
- Speed and licensing vary widely. Silero and Piper rendered the sample in about five seconds on CPU while F5-TTS Russian needed about an hour, and several of the best-sounding models carry non-commercial licenses.
Architecture of the production pipeline
Resumable generation jobs
Each render is a generation record that moves through pending → extracting → generating → encoding → done, with progress and an ETA in the Filament admin. Two engines sit behind the same model: a Gemini TTS path that synthesizes chunk by chunk into raw PCM and encodes one MP3 with FFmpeg, and a self-hosted Python rendering service, driven over HTTP, that produces one MP3 per chapter. Progress is saved after every chunk, long runs re-dispatch themselves before the queue times out, and a resubmitted job resumes from cached segments. Nothing is published until the whole book is rendered.
Text preparation and casting
A deterministic cleaner removes page numbers, running headers, captions, table-of-contents lines and footnote markers, repairs hyphenation, reflows paragraphs and restores the letter ё from a dictionary. An optional audit step shows DeepSeek a small sample of the book and applies the junk patterns it returns across the full text in PHP, so the AI cost stays at one cheap call regardless of length. For multi-voice narration, an LLM splits prose into speaker segments and voices are assigned per character by detected gender; any failure falls back to plain narration.
Quality control and delivery
Segments that fell back to silence or kept a persistently noisy take are counted per generation, so a render with warnings gets a listen-through. A chaptered render that comes out implausibly short for its word count is rejected as truncated: it isn't published, the buyer isn't emailed, and the team gets a Telegram alert. Finished files carry ID3 tags and cover art.
Automation and rollout
When an order becomes paid, a queued listener starts a single-voice narration pinned to the exact product the buyer purchased, and the buyer is emailed when it's ready. Every check is idempotent, so the same entry point serves the paid-order listener, a nightly backfill of paid audiobooks still missing files, retries and the admin assistant. By default, a book that fails three times in a row is left for a human.
The rollout was staged. A validation batch of five generations ran on production first, under a watch script that released the backlog only after a render finished with a full audio file attached and stopped at the first failure. The wider backfill then ran under a monitor that reported active, done and failed counts and halted past a failure threshold. An hourly job keeps render scratch space within a retention window and a size budget.
Related work
This pipeline is part of our AI integration and automation work for Knigopoisk. See also the large-print book pipeline and the Telegram order alerts that flag failed renders.



