Add combined all-languages chapter to the renderer

Writes _ALL_LANGUAGES_full_sample.wav alongside the per-language chapters,
English first then the operator's list order, so the whole 10-language set
can be heard in one pass (17.8 min for the sample chapter).

Root cause found while rendering with 1.7B: the ICL prompt path is what
blows up memory, not model size or uptime. A single prompt_slug request
added ~14 GB (7.2 -> 21.6 GB) and wedged the server, after which the
otherwise-stable ref_audio path also hung. A fresh 1.7B loads in 8s at
5.4 GB, generates in 9-16s per clip, and settles at ~37 MB per additional
clip (13.1 GB after 120) with no restart needed between languages.

The 0.6B render is kept in Lang_test_0p6B for comparison; the 1.7B render
is in Lang_test.

Suite: 721 passed, 8 pre-existing.
This commit is contained in:
B.D. Murphy
2026-10-12 22:28:21 -07:00
parent fe6337d3e5
commit d73cdf5442

View File

@@ -10,6 +10,10 @@ per-language file, which is what you actually listen to.
Qwen3-TTS auto-detects language from the text - ``/v1/tts`` takes no language
argument - so there is nothing to set per clip.
Also writes ``_ALL_LANGUAGES_full_sample.wav`` - every language back to back,
in the operator's list order with English first - for listening to the whole
set in one pass.
Voice is supplied two ways:
``--voice-mode ref`` (default) sends ``ref_audio`` + ``ref_text`` and lets the
@@ -168,6 +172,33 @@ def stitch(parts: list[Path], out: Path, gap_ms: int = 400) -> None:
listing.unlink(missing_ok=True)
# English first, then the operator's stated order for the languages rendered.
COMBINED_ORDER = ["EN", "ZH", "JA", "KO", "DE", "ES", "FR", "RU", "IT", "PT"]
def build_combined(out_root: Path) -> Path | None:
"""Concatenate every per-language chapter into one listenable file."""
import subprocess
lines = []
for lang in COMBINED_ORDER:
f = out_root / lang / f"_full_sample_{lang}.wav"
if f.exists():
lines.append(f"file '{f.resolve()}'")
if not lines:
return None
listing = out_root / "._combined.txt"
listing.write_text("\n".join(lines) + "\n")
out = out_root / "_ALL_LANGUAGES_full_sample.wav"
subprocess.run(
["ffmpeg", "-y", "-f", "concat", "-safe", "0", "-i", str(listing),
"-c", "copy", str(out)],
check=True, capture_output=True,
)
listing.unlink(missing_ok=True)
return out
def main() -> int:
ap = argparse.ArgumentParser(description=__doc__)
ap.add_argument("--project")
@@ -270,7 +301,10 @@ def main() -> int:
except Exception as e: # stitching is a convenience, not the deliverable
print(f" {suffix}: stitch failed: {e}")
combined = build_combined(out_root)
print(f"\n done: {ok} rendered, {failed} failed")
if combined:
print(f" combined: {combined}")
return 0 if ok else 1