Convert Ebooks to Audiobooks with [custom] voice samples
Project description
kenkui
Ebook-to-audiobook conversion engine. No GPU. No nonsense.
kenkui is a Python library that converts ebooks into high-quality M4B audiobooks using Kyutai's pocket-tts, running entirely on CPU.
Looking for the interactive CLI? Install kentui — it's the interactive front-end built on top of this library.
Install
pip install kenkui
Or with uv:
uv add kenkui
Quick Start
import kenkui
# Load config (creates default at ~/.config/kenkui/config.toml on first run)
config = kenkui.load_config()
# Build a ProcessingConfig
proc = kenkui.ProcessingConfig(
ebook_path="book.epub",
output_path=".",
voice="alba",
)
# Run the conversion
ok = kenkui.run_job(proc)
Features
- Freaky fast M4B audiobook generation — 100% CPU, no GPU
- Multithreaded chapter processing
- Supports EPUB, MOBI/AZW/AZW3/AZW4, and FB2
- Multi-voice narration via NLP speaker attribution (Ollama, Anthropic, OpenAI, Google)
- Voice pool template for automatic voice assignment by role + gender + rank
- Chapter-voice mode: distinct voice per chapter
- Broadcast-quality audio post-processing chain
- Credits chapter: synthesized audio appended to every m4b
- Flexible chapter selection (presets + manual override)
- Series support: cross-book character roster with pinned voice assignments
API Reference
Config
config = kenkui.load_config() # default config
config = kenkui.load_config("fast-mode") # named config
config = kenkui.load_config("/path/to/cfg.toml")
kenkui.save_config(config)
kenkui.save_config(config, "fast-mode")
names: list[str] = kenkui.list_configs()
Book parsing
result = kenkui.parse_book("book.epub")
# result.chapters, result.metadata, result.book_hash
filtered = kenkui.filter_chapters(result.book_hash, selection)
NLP
# Stage 1-2: entity scan + character clustering
scan = kenkui.fast_scan("book.epub", nlp_model="llama3.2")
# scan.characters: list[CharacterInfo]
# Stages 1-4: full pipeline with speaker attribution
result = kenkui.full_analysis(
"book.epub",
nlp_model="llama3.2",
progress_callback=lambda pct, msg: print(f"{pct}% {msg}"),
)
# result.characters, result.chapters (annotated)
Voices
voices = kenkui.list_voices()
voices = kenkui.list_voices(gender="Female", accent="British", source="compiled")
voice = kenkui.get_voice("alba") # VoiceInfo | None
cast = kenkui.suggest_cast(
roster=scan.characters,
excluded_voices=["alba"],
default_voice="sarah",
)
# cast.speaker_voices: dict[str, str]
narrator = kenkui.recommend_narrator(scan.characters, default_voice="alba")
result = kenkui.exclude_voice("marius") # ExcludeResult
result = kenkui.include_voice("marius") # IncludeResult
preview = kenkui.audition_voice("alba", text="Hello world.")
# preview.audio_path, preview.duration_ms
dl = kenkui.download_voice(force=False) # DownloadResult
dl = kenkui.fetch_voice(repo_id="user/repo")
Series
series_list = kenkui.list_series()
entry = kenkui.get_series("my-series")
entry = kenkui.create_series("My Series")
kenkui.update_series(entry)
HuggingFace auth
result = kenkui.authenticate_huggingface("hf_token_here")
# result.authenticated, result.username
Job runner
from kenkui import ProcessingConfig, NarrationMode
config = ProcessingConfig(
ebook_path="book.epub",
output_path=".",
voice="alba",
narration_mode=NarrationMode.SINGLE,
chapter_filters=[FilterOperation(type="preset", value="content-only")],
)
ok: bool = kenkui.run_job(config)
ok: bool = kenkui.run_job(
config,
progress_callback=lambda pct, chapter, eta: print(f"{pct:.0f}% {chapter}"),
)
Voice System
Voices come in three tiers:
| Tier | Source | Auth required? |
|---|---|---|
| Compiled | Downloaded from HuggingFace on first run | No |
| Built-in | 8 pocket-tts defaults | No |
| Custom | .wav files (user-provided or fetched) |
Yes (HuggingFace) |
Built-in voices: alba, marius, javert, jean, fantine, cosette, eponine, azelma
Configuration
kenkui uses TOML config files stored at ~/.config/kenkui/ (XDG).
| Key | Default | Description |
|---|---|---|
workers |
cpu_count - 2 |
Parallel TTS worker processes |
m4b_bitrate |
96k |
Output audio bitrate |
temp |
0.7 |
Sampling temperature |
lsd_decode_steps |
1 |
LSD decode steps |
default_voice |
alba |
Fallback voice |
nlp_provider |
ollama |
NLP backend |
nlp_model |
llama3.2 |
Model for speaker attribution |
credits_enabled |
true |
Append synthesized credits audio |
Non-Goals
kenkui is not a general-purpose TTS framework, a GUI app, or an MP3 generator. The focus is narrow: fast, high-quality audiobook generation from ebooks.
🙏 Special Thanks
Thanks to Project Gutenberg for providing some of the public-domain books included with kenkui.
Voice Dataset Credits
kenkui's compiled voices are derived from two publicly available speech corpora.
CSTR VCTK Corpus
Veaux, Christoph; Yamagishi, Junichi; MacDonald, Kirsten. (2019). CSTR VCTK Corpus: English Multi-speaker Corpus for CSTR Voice Cloning Toolkit. University of Edinburgh. The Centre for Speech Technology Research (CSTR).
Licensed under Creative Commons Attribution 4.0 (CC BY 4.0). Commercial use is permitted with attribution.
EARS Dataset
Licensed under Creative Commons Attribution-NonCommercial 4.0 (CC BY-NC 4.0).
Note: Compiled voices sourced from EARS (identifiable by
EARSin the voice name viakenkui.list_voices()) may not be used for commercial purposes. If you are building a commercial product with kenkui, use only VCTK-sourced or built-in voices.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file kenkui-2.0.0.tar.gz.
File metadata
- Download URL: kenkui-2.0.0.tar.gz
- Upload date:
- Size: 10.8 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.11 {"installer":{"name":"uv","version":"0.11.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ed6a09707c421c75ab7a22cb5d9d699f9e2c74aa19b7f72ff80ae89eabffd6b9
|
|
| MD5 |
e455a0fd0911b364eecf7acbc83f8976
|
|
| BLAKE2b-256 |
86f70343fe7860cc67300a432dfb48396100347e9b6b9a52e04a67f1873fdb23
|
File details
Details for the file kenkui-2.0.0-py3-none-any.whl.
File metadata
- Download URL: kenkui-2.0.0-py3-none-any.whl
- Upload date:
- Size: 10.8 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.11 {"installer":{"name":"uv","version":"0.11.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4a4a02b7f03e3c220b33a8ce1594ca637ad1b6ba902b657f2ead58481eaba082
|
|
| MD5 |
c1fc867117e75db2423a5b01601488ca
|
|
| BLAKE2b-256 |
69521023eb1b0b71ca3ec4e4e491a9493cd2fc52d3cc437f8c5f04b4767085b5
|