Runs after a reviewer finishes a book and answers the two questions that
gate the next stage:
1. Are there utterances with no speaker?
2. Now that speakers have been defined, renamed, merged or deleted, are
there utterances that should change?
Read-only - it never edits the database, and a test asserts the files are
byte-identical afterwards. Output is a markdown table and a CSV, one row per
finding with chapter, utterance number and a text preview, so each item is
locatable rather than a count.
Deal Hunter, after the completed review (56 speakers, 0 still needing
review, 4319 utterances):
- Dialogue with no speaker: 0. The 1803 speakerless rows are narration
and scene breaks, which is correct and is reported as a number rather
than silently dropped.
- Utterances attributed to a deleted speaker: 0.
- One speaker stored under two spellings: 6 rows across 3 speakers
(narrator/Narrator, Kainda/Princess Kainda, Willamina Wake/Captain).
All resolve to one voice so the audio is correct, but a per-speaker
export would split them into six - caught before the translation stage,
not after.
- 6 speech-tag mismatches where the narration immediately before the line
names a different speaker.
- 10 dialogue rows voiced by the narrator: 9 are quoted labels ("Reactor.",
"operations") that are correctly read by the narrator, 1 (ch28 utt46) is
a real segmentation error. Classified advisory so the one real defect is
not buried under nine false positives.
build_alias_map moved from scripts/qa_attribution.py into attribution_qa.py
so the CLI and the audit cannot disagree about what a speech tag resolves to;
qa_attribution output verified byte-identical.
13 new tests. Suite: 721 passed, 8 pre-existing.
UmbraAudio
Quality-first multi-pass audiobook generation from English manuscripts.
Features
- 5-pass pipeline: Analysis → Voice Design → Mapping → Test → Generate
- Multi-engine TTS: Chatterbox (primary), Qwen3-TTS (secondary)
- LLM-enhanced: BookNLP for NLP, LLM for profiling/emotion/pronunciation
- Web review: FastAPI + HTMX at checkpoints for human approval
Quick Start
python -m umbraaudio.cli init <manuscript.epub> --name 'My Book'
python -m umbraaudio.cli analyze
python -m umbraaudio.cli voices
python -m umbraaudio.cli review
Requirements
- Python 3.11+
- NVIDIA GPU with CUDA support (RTX 3060 or better recommended)
- ffmpeg
Development
pip install -e ".[dev]"
ruff check umbraaudio/
pytest tests/ -v
Commit cadence: commit at least once every Sunday. Never leave a week (let alone a month) of work uncommitted — a single accidental
git checkouton 2026-09-20 wiped out a month of changes toumbraaudio/web/routes.py. SeeAGENTS.md→ Commit Cadence.
scripts/commit_check.sh enforces the nudge: it exits non-zero once the tree has been dirty
longer than a week. The LaunchAgent com.umbraaudio.commitcheck runs it every Sunday at
18:00 and posts a macOS notification when there is uncommitted work.
scripts/commit_check.sh # warn if dirty > 7 days
scripts/commit_check.sh --days 3 # tighter threshold
scripts/commit_check.sh --any # warn on any uncommitted change
Rebuilding from source
The repo tracks source only; large runtime data is reconstructed as needed.
-
Models: weights are not committed (see
.gitignore). Download them:bash scripts/download_models.sh # ~9 GB, targets ./models -
Qwen3-TTS is a git submodule pinned to upstream commit
022e286:git submodule update --init --recursiveThe
tts_server/web-demo backend includes a local UI customization toqwen_tts/cli/demo.py. It is preserved as a patch — reapply it after checking out the submodule:cd Qwen3-TTS && git apply ../scripts/qwen3_tts_demo_umbra_patch.patch -
Environment: copy/keep
.env(contains secrets) and setUMBRA_TTS__*model paths undermodels/.
Book projects (e.g. DealHunterShip_...) are committed separately under their
own project directories and are not part of this program repository.