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:
@@ -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).
|
||||
|
||||
Reference in New Issue
Block a user