Document the scene-break rule and verify the 2 s silence

Scene-break rows must carry speaker_name='Narrator'. The system requires a
speaker on every utterance row, so 'scene_break' was never a valid authorial
value - it was a generator artifact. Normalized 74 rows book-wide (81 total).

The value is inert for rendering: is_scene_break() keys off the <<<>>> text and
the scene_break type, never speaker_name, and both generation paths
short-circuit before voice resolution. Verified 62/62 existing scene-break WAVs
are exactly 2.000 s, matching SCENE_BREAK_SILENCE_MS.

Recorded so the transient 'scene_break' speaker value is not mistaken for a
deliberate authorial choice again.
This commit is contained in:
B.D. Murphy
2026-09-26 07:51:44 -07:00
parent e8944fcd88
commit 6ca8f80087

View File

@@ -108,6 +108,26 @@ voices/narrator_ref.wav (voice for new narration) ─▶ 1. synth opening/annou
| `umbraaudio/web/templates/index.html` | "Build Final Audiobook (MP3)" card + stats table + download links |
| `tests/test_ar_export.py` | Unit tests with mocked TTS + ffmpeg |
## 5a. Scene breaks (`<<<>>>`)
A scene break is a segmentation row whose `text` is exactly `<<<>>>`. It renders as
**2.000 s of silence**, never as speech.
- **Author rule:** every scene-break utterance must carry `speaker_name = 'Narrator'`.
The system requires a speaker on every utterance row, and `Narrator` is the correct
value. A `speaker_name` of `scene_break` is **not** valid data — it was a transient
artifact of the generator, not an authorial choice. Normalized book-wide on
2026-09-26 (74 rows changed; 81 total).
- **The speaker value is inert for rendering.** `is_scene_break(text, utt_type)`
(`umbraaudio/generation/scene_break.py:31`) keys off the `<<<>>>` text and the
`scene_break` type only, never `speaker_name`. Both generation paths short-circuit
before voice resolution — `generate_all_audio.py:167` and
`chapter_builder.py:514` (`write_scene_break_audio(out)` then `continue`, ahead of
`_resolve_voice_ref` at `:520`). So the value is required by the schema but cannot
affect the audio.
- **Duration constant:** `SCENE_BREAK_SILENCE_MS = 2000` (`scene_break.py:26`).
Verified 2026-09-26: 62/62 existing scene-break WAVs are exactly 2.000 s.
## 6. Quality gates before upload
- All tracks: 44.1 kHz, mono, 192 kbps CBR MP3 (ffprobe report in manifest).