Content-addressed, resumable pipeline that converts novel-length text into a
verified, mastered audiobook using local or rented-GPU neural TTS. Feed it a
.txt/.epub/.html source; it extracts, dedupes, figures out who's
speaking, casts voices, synthesizes, verifies against ASR, and masters a
final .m4b — with every expensive step cached by content hash so nothing
gets redone unless its actual inputs changed.
Full spec: docs/audiobook-pipeline.md.
Everything you can customize, in plain language:
docs/customization-guide.md. Build order:
docs/TODO.md. AI-agent conventions:
CLAUDE.md + docs/dev-log.md.
Every milestone in the original build order (M0 through M12) has shipped, as
of 2026-08-01. Two items remain not-started: M9 Phase B (IndexTTS2/
VibeVoice eval pilot arms — blocked on validating those engines against a
real install) and the Dashboard Rebuild Phase 1 (React/TS/Vite SPA
replacing the current single-page abp ui). See docs/TODO.md for the
authoritative per-item build status before assuming a feature exists.
| Milestone | State |
|---|---|
| M0 Spine (manifest, config, hashing, CLI skeleton, gates) | done |
| M1 First audio (txt → chatterbox → verify → m4b) | done |
| M2 Real intake (epub/html, dedup, ordering, lexicon) | done |
| M3 Intelligence (attribution, registry, casting, duet) | done |
| M4 Full cast + rental workflow (kokoro preview engine, plan/work/gc) | done |
M4.5 Dashboard (abp ui) | done |
| M4.75 Realism layer (pause jitter, crossfades, room tone, breaths) | done |
| M5 Voice training | done |
| M6 Mood + music | done |
M7 Book adapter / customization layer (book_adapter.yaml) | done |
| M8 Register assignment | done |
| M8.1 Register assignment amendments | done |
| M9 Evaluation harness — Phase A (Chatterbox pilot) | done |
| M9 Evaluation harness — Phase B (IndexTTS2/VibeVoice pilot arms) | not started |
| M10 Multi-engine synthesis (IndexTTS2 real, VibeVoice stubbed) | done |
| M12 Cross-chapter consistency (fingerprint, loudness, voice freeze, timbre) | done |
| Dashboard Rebuild Phase 1 (React/TS/Vite SPA) | not started |
PATH (mastering, resampling)abp analyze) — see
Environment variables below. Every LLM-touching
stage sits behind an explicit review gate; nothing paid runs without you
opting in (spec §2, "gates before money")git clone <this-repo-url>
cd abp
python -m venv .venv
.venv/Scripts/activate # .venv/bin/activate on macOS/Linux
pip install -e ".[dev,chatterbox,asr]"
abp --help
pyproject.toml defines the installable extras — mix and match what you
actually need:
| Extra | Adds | Needed for |
|---|---|---|
chatterbox | chatterbox-tts | the default/main TTS engine (M1) |
kokoro | kokoro | the fast preview/draft engine (M4) |
asr | faster-whisper | abp verify (ASR-vs-text comparison) |
eval | transformers, librosa, torchaudio | abp voice eval (M9 — identity/drift/naturalness metrics; also needs chatterbox+asr) |
dev | pytest, pytest-cov, ruff, mypy | running the test suite / linting |
IndexTTS2 (M10) isn't a pyproject.toml extra — it's installed and pointed
at via ABP_INDEXTTS2_MODEL_DIR (see below); read
src/abp/engines/indextts2.py's module docstring before using it for real.
VibeVoice is a deliberate stub (src/abp/engines/vibevoice.py) — no
maintained upstream inference code exists to build against yet.
Two more tools live in this repo but are fully standalone (their own
venv, their own CLI, zero imports from abp core) — see
Companion tools below.
mkdir myproject && cd myproject
abp init # scaffolds project.yaml + folder layout
cp /path/to/book.txt dump/ # or .epub / .html
abp intake # extract, dedupe, order-reconstruct -> book.json
abp clean # normalize + source profile + optional LLM clean pass
abp segment # sentence split, dialogue/narration spans, chunk pack
abp detect # propose quote convention (review before casting)
abp annotate --pass attribution # who-speaks-what
abp sheet # ranked casting sheet -> casting.review gate
abp cast # resolve voice_id per span
abp annotate --pass register # delivery register assignment (spec §7 S8b)
abp annotate --pass mood # scene mood/intensity/music tagging
abp synth # drain pending chunks (chatterbox default, kokoro preview)
abp verify # ASR compare, retry loop
abp mix --chapter <id> # mood-driven music bed (if mix.enabled)
abp master # concat, loudnorm, encode -> m4b (--book for cross-chapter)
# → out/*.m4b
Every stage picks up exactly where it left off — re-running abp synth
after adding a new chapter only synthesizes the new chunks; editing a
lexicon.yaml entry only re-renders the chunks containing that word. See
docs/customization-guide.md for every way to steer a specific book's
output (pronunciation fixes, inline directives, source profiles, and the
full book_adapter.yaml rule vocabulary) without ever touching pipeline
code.
Longer-running or paid-resource work is queued and reviewed rather than run inline:
abp plan # pending work, GPU-hour/cost estimate, gate check
abp work --class gpu # class-scoped queue drainer (rental-friendly)
abp voice add / audition / train / freeze / unlock / timbre-check / eval
abp gc --dry-run # orphaned chunk cleanup
abp ui # single-page dashboard: status, verify review, casting review
abp adapter diff # dry-run book_adapter.yaml rules against current state
abp analyze # quirk report with drafted glossary/profile/adapter fixes
abp stress parser # dev-only harness: hammer S1-S8b against curated fixtures/real books
abp gate list|close|waive
abp register sheet|freeze
abp lexicon add|suggest
Every subcommand in abp --help reflects the full CLI surface — see
src/abp/cli.py.
| Variable | Purpose |
|---|---|
ABP_INDEXTTS2_MODEL_DIR | Path to a local IndexTTS2 checkpoint directory (default checkpoints/indextts2). Used by both inference (abp synth) and voice_train's install-checkpoint. |
ABP_TEST_REAL_TTS | Opt into real chatterbox synthesis in the test suite (downloads weights, slow). |
ABP_TEST_REAL_TRAINING | Opt into real chatterbox training in the test suite. |
ABP_TEST_REAL_KOKORO | Opt into real kokoro synthesis in the test suite. |
ABP_TEST_REAL_INDEXTTS2 | Opt into real IndexTTS2 synthesis in the test suite (needs the indextts package + downloaded checkpoints). |
ABP_TEST_REAL_LLM / ABP_TEST_REAL_PROJECT | Opt into a real-LLM-backed milestone test against an already-intake/clean/segment'd project (real API cost). |
ABP_TEST_REAL_EVAL_MODELS | Opt into real WavLM-TDNN / SQUIM model downloads for voice_eval tests. |
ABP_TEST_REAL_TIMBRE | Opt into a real WavLM embedder load for the webapi voices test. |
Every ABP_TEST_REAL_* flag is off by default — the full test suite runs
without any of them, real models, or network access.
Two packages ship in this repo but are fully standalone — their own
virtualenv, their own CLI entry point, no imports from abp's core
pipeline. Neither is required to use abp itself; both exist to build a
custom cloned/trained voice to feed into abp's voice bank.
| Tool | Turns | Into | Docs |
|---|---|---|---|
voice_dataset_prep | raw episode video/audio + subtitles | a clean, per-character voice dataset (manifest.jsonl) | full setup, command reference, review-UI workflow |
voice_train | voice_dataset_prep's manifest.jsonl | a trained IndexTTS2 GPT checkpoint, installable via ABP_INDEXTTS2_MODEL_DIR | full setup, vendored-repo pinning, rental-box handoff |
The chain end to end: voice_dataset_prep → manifest.jsonl →
voice_train → a checkpoint → abp's existing IndexTTS2 adapter. Each
README documents its own venv because both packages pull in heavy,
version-sensitive ML dependencies (torch, pyannote.audio,
audio-separator) that don't need to collide with the core pipeline's own
environment.
pytest -q
Runs the full suite (tests/ + voice_train/tests/, per
pyproject.toml's testpaths) with every ABP_TEST_REAL_* flag off by
default — no real model downloads, no network calls, no GPU required.
voice_dataset_prep/tests/ runs the same way from inside its own venv
(voice_dataset_prep/README.md has the setup). Config/hashing/manifest-DDL
changes need a test that fails before the change and passes after — see
CLAUDE.md's non-negotiable invariants before touching any of those.
Every design decision follows the spec's binding principles (see §2):
cpu, api, or gpu; the pipeline runs unchanged on any host.Because the core is book-agnostic by design, no book-specific content
(character names, source text, lexicon entries, profiles tuned to one
book) ever belongs in this repo — see CLAUDE.md. Real projects,
profiles/<source>.yaml, and book_adapter.yaml files live outside this
repo (or gitignored inside it), never committed here.
src/abp/
├── config.py # project.yaml loader
├── manifest.py # SQLite state (§5.2)
├── model.py # canonical book.json dataclasses (§5.1)
├── gates.py # review-gate machinery
├── hashing.py # chunk identity (§5.3), voice_hash (§9.4)
├── cli.py # click-based CLI (§11.5)
├── engines/ # TTS adapter plugins (§10.1) — chatterbox (default/main), kokoro (preview), indextts2, vibevoice (stub)
├── llm/ # provider adapters (§10.2) — deepseek, gemini, anthropic, openai_compatible
├── stages/ # S1–S11 stage implementations
├── voice/ # voice bank, training, breaths, freeze (§9)
├── voice_eval/ # evaluation harness (§16) — identity/drift/boundary/intelligibility/level/naturalness metrics
├── stress/ # dev-only parser stress harness — curated fixtures + real-book runs against S1-S8b
├── adapter*.py # book_adapter.yaml matching engine, loader, diff, analyze (§15)
├── register*.py # delivery register assignment cascade (§7 S8b)
├── fingerprint.py # render-fingerprint drift detection (§8.6 Layer 1)
├── voice_freeze.py # per-voice content-addressed freeze/unlock (§8.6 Layer 3)
└── timbre_tracking.py # per-voice book-wide timbre drift (§8.6 Layer 4)
voice_dataset_prep/ # standalone: episode audio/subtitles -> per-character voice dataset
voice_train/ # standalone: voice dataset -> trained IndexTTS2 checkpoint
tests/ # unit tests — one file per module, hash stability, config parsing, gate transitions
docs/ # spec + build TODO + dev log + index + customization guide
Runtime project layout lives outside this repo (spec §4). See
docs/INDEX.md for a full map from "where does X live" to file/symbol.
| Doc | What's in it |
|---|---|
docs/audiobook-pipeline.md | the authoritative spec — every stage, schema, and invariant |
docs/customization-guide.md | plain-language guide to every way to steer a specific book's output |
docs/TODO.md | milestone build order and per-item status (source of truth over this README's table) |
docs/INDEX.md | "where does X live" — file/symbol lookup |
docs/dev-log.md | rolling log of what changed and why, newest first |
docs/realism-notes.md | mastering-chain realism layer companion (pause jitter, crossfades, room tone, breaths) |
docs/ab-testing.md | A/B listening protocol for realism-layer changes |
docs/indextts2-voice-training-research.md | research behind voice_train — which fork, VRAM, what fine-tuning changes |
CLAUDE.md | non-negotiable invariants and workflow conventions for AI-assisted development |
MIT — see pyproject.toml.
Python
100.0%
Content-addressed, resumable pipeline that converts novel-length text into a
verified, mastered audiobook using local or rented-GPU neural TTS. Feed it a
.txt/.epub/.html source; it extracts, dedupes, figures out who's
speaking, casts voices, synthesizes, verifies against ASR, and masters a
final .m4b — with every expensive step cached by content hash so nothing
gets redone unless its actual inputs changed.
Full spec: docs/audiobook-pipeline.md.
Everything you can customize, in plain language:
docs/customization-guide.md. Build order:
docs/TODO.md. AI-agent conventions:
CLAUDE.md + docs/dev-log.md.
Every milestone in the original build order (M0 through M12) has shipped, as
of 2026-08-01. Two items remain not-started: M9 Phase B (IndexTTS2/
VibeVoice eval pilot arms — blocked on validating those engines against a
real install) and the Dashboard Rebuild Phase 1 (React/TS/Vite SPA
replacing the current single-page abp ui). See docs/TODO.md for the
authoritative per-item build status before assuming a feature exists.
| Milestone | State |
|---|---|
| M0 Spine (manifest, config, hashing, CLI skeleton, gates) | done |
| M1 First audio (txt → chatterbox → verify → m4b) | done |
| M2 Real intake (epub/html, dedup, ordering, lexicon) | done |
| M3 Intelligence (attribution, registry, casting, duet) | done |
| M4 Full cast + rental workflow (kokoro preview engine, plan/work/gc) | done |
M4.5 Dashboard (abp ui) | done |
| M4.75 Realism layer (pause jitter, crossfades, room tone, breaths) | done |
| M5 Voice training | done |
| M6 Mood + music | done |
M7 Book adapter / customization layer (book_adapter.yaml) | done |
| M8 Register assignment | done |
| M8.1 Register assignment amendments | done |
| M9 Evaluation harness — Phase A (Chatterbox pilot) | done |
| M9 Evaluation harness — Phase B (IndexTTS2/VibeVoice pilot arms) | not started |
| M10 Multi-engine synthesis (IndexTTS2 real, VibeVoice stubbed) | done |
| M12 Cross-chapter consistency (fingerprint, loudness, voice freeze, timbre) | done |
| Dashboard Rebuild Phase 1 (React/TS/Vite SPA) | not started |
PATH (mastering, resampling)abp analyze) — see
Environment variables below. Every LLM-touching
stage sits behind an explicit review gate; nothing paid runs without you
opting in (spec §2, "gates before money")git clone <this-repo-url>
cd abp
python -m venv .venv
.venv/Scripts/activate # .venv/bin/activate on macOS/Linux
pip install -e ".[dev,chatterbox,asr]"
abp --help
pyproject.toml defines the installable extras — mix and match what you
actually need:
| Extra | Adds | Needed for |
|---|---|---|
chatterbox | chatterbox-tts | the default/main TTS engine (M1) |
kokoro | kokoro | the fast preview/draft engine (M4) |
asr | faster-whisper | abp verify (ASR-vs-text comparison) |
eval | transformers, librosa, torchaudio | abp voice eval (M9 — identity/drift/naturalness metrics; also needs chatterbox+asr) |
dev | pytest, pytest-cov, ruff, mypy | running the test suite / linting |
IndexTTS2 (M10) isn't a pyproject.toml extra — it's installed and pointed
at via ABP_INDEXTTS2_MODEL_DIR (see below); read
src/abp/engines/indextts2.py's module docstring before using it for real.
VibeVoice is a deliberate stub (src/abp/engines/vibevoice.py) — no
maintained upstream inference code exists to build against yet.
Two more tools live in this repo but are fully standalone (their own
venv, their own CLI, zero imports from abp core) — see
Companion tools below.
mkdir myproject && cd myproject
abp init # scaffolds project.yaml + folder layout
cp /path/to/book.txt dump/ # or .epub / .html
abp intake # extract, dedupe, order-reconstruct -> book.json
abp clean # normalize + source profile + optional LLM clean pass
abp segment # sentence split, dialogue/narration spans, chunk pack
abp detect # propose quote convention (review before casting)
abp annotate --pass attribution # who-speaks-what
abp sheet # ranked casting sheet -> casting.review gate
abp cast # resolve voice_id per span
abp annotate --pass register # delivery register assignment (spec §7 S8b)
abp annotate --pass mood # scene mood/intensity/music tagging
abp synth # drain pending chunks (chatterbox default, kokoro preview)
abp verify # ASR compare, retry loop
abp mix --chapter <id> # mood-driven music bed (if mix.enabled)
abp master # concat, loudnorm, encode -> m4b (--book for cross-chapter)
# → out/*.m4b
Every stage picks up exactly where it left off — re-running abp synth
after adding a new chapter only synthesizes the new chunks; editing a
lexicon.yaml entry only re-renders the chunks containing that word. See
docs/customization-guide.md for every way to steer a specific book's
output (pronunciation fixes, inline directives, source profiles, and the
full book_adapter.yaml rule vocabulary) without ever touching pipeline
code.
Longer-running or paid-resource work is queued and reviewed rather than run inline:
abp plan # pending work, GPU-hour/cost estimate, gate check
abp work --class gpu # class-scoped queue drainer (rental-friendly)
abp voice add / audition / train / freeze / unlock / timbre-check / eval
abp gc --dry-run # orphaned chunk cleanup
abp ui # single-page dashboard: status, verify review, casting review
abp adapter diff # dry-run book_adapter.yaml rules against current state
abp analyze # quirk report with drafted glossary/profile/adapter fixes
abp stress parser # dev-only harness: hammer S1-S8b against curated fixtures/real books
abp gate list|close|waive
abp register sheet|freeze
abp lexicon add|suggest
Every subcommand in abp --help reflects the full CLI surface — see
src/abp/cli.py.
| Variable | Purpose |
|---|---|
ABP_INDEXTTS2_MODEL_DIR | Path to a local IndexTTS2 checkpoint directory (default checkpoints/indextts2). Used by both inference (abp synth) and voice_train's install-checkpoint. |
ABP_TEST_REAL_TTS | Opt into real chatterbox synthesis in the test suite (downloads weights, slow). |
ABP_TEST_REAL_TRAINING | Opt into real chatterbox training in the test suite. |
ABP_TEST_REAL_KOKORO | Opt into real kokoro synthesis in the test suite. |
ABP_TEST_REAL_INDEXTTS2 | Opt into real IndexTTS2 synthesis in the test suite (needs the indextts package + downloaded checkpoints). |
ABP_TEST_REAL_LLM / ABP_TEST_REAL_PROJECT | Opt into a real-LLM-backed milestone test against an already-intake/clean/segment'd project (real API cost). |
ABP_TEST_REAL_EVAL_MODELS | Opt into real WavLM-TDNN / SQUIM model downloads for voice_eval tests. |
ABP_TEST_REAL_TIMBRE | Opt into a real WavLM embedder load for the webapi voices test. |
Every ABP_TEST_REAL_* flag is off by default — the full test suite runs
without any of them, real models, or network access.
Two packages ship in this repo but are fully standalone — their own
virtualenv, their own CLI entry point, no imports from abp's core
pipeline. Neither is required to use abp itself; both exist to build a
custom cloned/trained voice to feed into abp's voice bank.
| Tool | Turns | Into | Docs |
|---|---|---|---|
voice_dataset_prep | raw episode video/audio + subtitles | a clean, per-character voice dataset (manifest.jsonl) | full setup, command reference, review-UI workflow |
voice_train | voice_dataset_prep's manifest.jsonl | a trained IndexTTS2 GPT checkpoint, installable via ABP_INDEXTTS2_MODEL_DIR | full setup, vendored-repo pinning, rental-box handoff |
The chain end to end: voice_dataset_prep → manifest.jsonl →
voice_train → a checkpoint → abp's existing IndexTTS2 adapter. Each
README documents its own venv because both packages pull in heavy,
version-sensitive ML dependencies (torch, pyannote.audio,
audio-separator) that don't need to collide with the core pipeline's own
environment.
pytest -q
Runs the full suite (tests/ + voice_train/tests/, per
pyproject.toml's testpaths) with every ABP_TEST_REAL_* flag off by
default — no real model downloads, no network calls, no GPU required.
voice_dataset_prep/tests/ runs the same way from inside its own venv
(voice_dataset_prep/README.md has the setup). Config/hashing/manifest-DDL
changes need a test that fails before the change and passes after — see
CLAUDE.md's non-negotiable invariants before touching any of those.
Every design decision follows the spec's binding principles (see §2):
cpu, api, or gpu; the pipeline runs unchanged on any host.Because the core is book-agnostic by design, no book-specific content
(character names, source text, lexicon entries, profiles tuned to one
book) ever belongs in this repo — see CLAUDE.md. Real projects,
profiles/<source>.yaml, and book_adapter.yaml files live outside this
repo (or gitignored inside it), never committed here.
src/abp/
├── config.py # project.yaml loader
├── manifest.py # SQLite state (§5.2)
├── model.py # canonical book.json dataclasses (§5.1)
├── gates.py # review-gate machinery
├── hashing.py # chunk identity (§5.3), voice_hash (§9.4)
├── cli.py # click-based CLI (§11.5)
├── engines/ # TTS adapter plugins (§10.1) — chatterbox (default/main), kokoro (preview), indextts2, vibevoice (stub)
├── llm/ # provider adapters (§10.2) — deepseek, gemini, anthropic, openai_compatible
├── stages/ # S1–S11 stage implementations
├── voice/ # voice bank, training, breaths, freeze (§9)
├── voice_eval/ # evaluation harness (§16) — identity/drift/boundary/intelligibility/level/naturalness metrics
├── stress/ # dev-only parser stress harness — curated fixtures + real-book runs against S1-S8b
├── adapter*.py # book_adapter.yaml matching engine, loader, diff, analyze (§15)
├── register*.py # delivery register assignment cascade (§7 S8b)
├── fingerprint.py # render-fingerprint drift detection (§8.6 Layer 1)
├── voice_freeze.py # per-voice content-addressed freeze/unlock (§8.6 Layer 3)
└── timbre_tracking.py # per-voice book-wide timbre drift (§8.6 Layer 4)
voice_dataset_prep/ # standalone: episode audio/subtitles -> per-character voice dataset
voice_train/ # standalone: voice dataset -> trained IndexTTS2 checkpoint
tests/ # unit tests — one file per module, hash stability, config parsing, gate transitions
docs/ # spec + build TODO + dev log + index + customization guide
Runtime project layout lives outside this repo (spec §4). See
docs/INDEX.md for a full map from "where does X live" to file/symbol.
| Doc | What's in it |
|---|---|
docs/audiobook-pipeline.md | the authoritative spec — every stage, schema, and invariant |
docs/customization-guide.md | plain-language guide to every way to steer a specific book's output |
docs/TODO.md | milestone build order and per-item status (source of truth over this README's table) |
docs/INDEX.md | "where does X live" — file/symbol lookup |
docs/dev-log.md | rolling log of what changed and why, newest first |
docs/realism-notes.md | mastering-chain realism layer companion (pause jitter, crossfades, room tone, breaths) |
docs/ab-testing.md | A/B listening protocol for realism-layer changes |
docs/indextts2-voice-training-research.md | research behind voice_train — which fork, VRAM, what fine-tuning changes |
CLAUDE.md | non-negotiable invariants and workflow conventions for AI-assisted development |
MIT — see pyproject.toml.
Python
100.0%