aboutsummaryrefslogtreecommitdiff
path: root/app/backends/audiocpp/wizard.py
diff options
context:
space:
mode:
authorhistoria <historiavg@proton.me>2026-09-01 12:12:35 -0400
committerhistoria <historiavg@proton.me>2026-09-01 12:12:35 -0400
commitdc6e7cd43029da62dabe2513fb5aa8a34df1bd6d (patch)
tree0eb951f174d91d6b4c96c9b4ea4e978d1bdfc8cd /app/backends/audiocpp/wizard.py
parentd15adb490b634dd22a65a1c8d7f4ec9fa74816b4 (diff)
downloadtts-audiobook-generator-dc6e7cd43029da62dabe2513fb5aa8a34df1bd6d.tar.gz
fix: spec santizer for glm, outetts, miotts, minimax.
Diffstat (limited to 'app/backends/audiocpp/wizard.py')
-rw-r--r--app/backends/audiocpp/wizard.py62
1 files changed, 45 insertions, 17 deletions
diff --git a/app/backends/audiocpp/wizard.py b/app/backends/audiocpp/wizard.py
index 97f50a5..a1a2a6a 100644
--- a/app/backends/audiocpp/wizard.py
+++ b/app/backends/audiocpp/wizard.py
@@ -26,10 +26,12 @@ from . import configsync as _configsync
from . import models as _models
from . import prebuilt as _prebuilt
from . import voices as _voices
-from .catalog import (_backend_options, build_model_entry,
- build_server_config, detect_backend, hosting_task,
+from .catalog import (_backend_options, build_model_entry, build_server_config,
+ detect_backend, entry_model_path, hosting_task,
load_model_catalog, load_server_config,
- package_dir_options, server_config_selections)
+ MIOTTS_CODEC_DISPLAY_NAME, MIOTTS_CODEC_INSTALL_ID,
+ package_dir_options, server_config_selections,
+ apply_entry_session_options)
from .constants import (AUDIOCPP_DIR_NAME, AUDIOCPP_GIT_URL, BACKENDS,
DEFAULT_HOST, TASK_TTS, TASK_VDES)
@@ -80,7 +82,7 @@ def _build_entries(family_keys: List[str], chosen: Dict[str, List[dict]],
task_picker: Callable[[str], str],
known_tasks: Optional[Dict[Tuple[str, str], str]] = None
) -> Tuple[List[dict], List[str], List[Tuple[str, str]],
- List[str], bool]:
+ List[Tuple[str, str]], List[str], bool]:
"""Build server.json model entries from the selected families/packages.
TASK_PICKER is called for each design package to choose vdes/tts.
@@ -89,12 +91,18 @@ def _build_entries(family_keys: List[str], chosen: Dict[str, List[dict]],
was hosted instead of re-asking. Each entry's server id is its package
``target_directory`` (flattened to a token), so packages from the same
family never collide; an id that does collide (across families) is
- auto-suffixed without prompting. Returns (model_entries, entry_ids,
- install_guidance, design_entry_ids, include_clone).
+ auto-suffixed without prompting. Entry paths come from the catalog
+ (``entry_model_path``): normally ``models/<target_directory>``, or the
+ package's first GGUF file when the package ships several GGUFs into one
+ directory (audio.cpp refuses multi-GGUF directories). COMPANION_GUIDANCE
+ carries the companion packages hosted models require but the TTS catalog
+ never offers (MioCodec for MioTTS). Returns (model_entries, entry_ids,
+ install_guidance, companion_guidance, design_entry_ids, include_clone).
"""
model_entries: List[dict] = []
entry_ids: List[str] = []
install_guidance: List[Tuple[str, str]] = []
+ companion_guidance: List[Tuple[str, str]] = []
design_entry_ids: List[str] = []
include_clone = False
for family in family_keys:
@@ -120,12 +128,16 @@ def _build_entries(family_keys: List[str], chosen: Dict[str, List[dict]],
model_id = f"{base_id}-{n}"
entry_ids.append(model_id)
model_entries.append(build_model_entry(
- family, model_id, f"models/{opt['target_directory']}",
+ family, model_id,
+ entry_model_path(entry, opt["target_directory"]),
task=task))
install_guidance.append((entry["display_name"], opt["install_id"]))
if task == TASK_VDES:
design_entry_ids.append(model_id)
- return (model_entries, entry_ids, install_guidance,
+ if any(str(e.get("family")) == "miotts" for e in model_entries):
+ companion_guidance.append(
+ (MIOTTS_CODEC_DISPLAY_NAME, MIOTTS_CODEC_INSTALL_ID))
+ return (model_entries, entry_ids, install_guidance, companion_guidance,
design_entry_ids, include_clone)
@@ -139,7 +151,11 @@ def _write_and_advise(audiocpp_dir: Path, wav_dir: Optional[Path],
After a successful run the console output is the path of the written
server.json. The model install commands (and optional automatic
download) are handled separately by _install_models, called by both
- UI modes once the user has decided whether to download.
+ UI modes once the user has decided whether to download. Before the
+ document is written, apply_entry_session_options bakes in the
+ per-entry session options heavy families need (MioTTS's codec path;
+ a VoxCPM AudioVAE encoder capacity sized to the voice directory's
+ longest reference), reported as one summary line.
"""
voice_dir: Optional[str] = None
if transcripts:
@@ -149,6 +165,11 @@ def _write_and_advise(audiocpp_dir: Path, wav_dir: Optional[Path],
print(f"[OK] Wrote {prompt_path}")
voice_dir = str(wav_dir.resolve())
+ configured = apply_entry_session_options(model_entries, wav_dir,
+ audiocpp_dir)
+ if configured:
+ print(f"[OK] Added family session options to: {', '.join(configured)}")
+
server_config = build_server_config(
host=host, port=port, backend=backend, lazy_load=lazy_load,
model_entries=model_entries, voice_dir=voice_dir)
@@ -269,7 +290,7 @@ def _wizard(stdscr, args: argparse.Namespace, parser: argparse.ArgumentParser
raise _GoBack()
return result
- model_entries, entry_ids, install_guidance, \
+ model_entries, entry_ids, install_guidance, companion_guidance, \
design_entry_ids, include_clone = _build_entries(
s["family_keys"], s["chosen"], s["catalog_by_family"],
task_picker, known_tasks=s["existing_tasks"])
@@ -277,6 +298,7 @@ def _wizard(stdscr, args: argparse.Namespace, parser: argparse.ArgumentParser
"model_entries": model_entries,
"entry_ids": entry_ids,
"install_guidance": install_guidance,
+ "companion_guidance": companion_guidance,
"design_entry_ids": design_entry_ids,
"include_clone": include_clone,
})
@@ -299,6 +321,7 @@ def _wizard(stdscr, args: argparse.Namespace, parser: argparse.ArgumentParser
"model_entries": s["model_entries"],
"entry_ids": s["entry_ids"],
"install_guidance": s["install_guidance"],
+ "companion_guidance": s["companion_guidance"],
"design_entry_ids": s["design_entry_ids"],
"include_clone": s["include_clone"],
"host": host,
@@ -419,8 +442,9 @@ def _wizard(stdscr, args: argparse.Namespace, parser: argparse.ArgumentParser
s["plan"] = _plan_from_mode(mode, wav_files, existing)
s["download"] = bool(result.get("download")) and (
- _models.download_applicable(s["audiocpp_dir"],
- s["model_entries"]))
+ _models.download_applicable(
+ s["audiocpp_dir"], s["model_entries"],
+ companions=s.get("companion_guidance")))
s["delete_unused"] = bool(result.get("delete_unused")) \
and bool(s["unused_entries"])
return _finalize()
@@ -540,7 +564,9 @@ def _wizard(stdscr, args: argparse.Namespace, parser: argparse.ArgumentParser
"visible": lambda fs: bool(s["include_clone"]),
})
- if _models.download_applicable(s["audiocpp_dir"], s["model_entries"]):
+ if _models.download_applicable(
+ s["audiocpp_dir"], s["model_entries"],
+ companions=s.get("companion_guidance")):
fields.append({
"key": "download",
"label": "Download the selected models automatically?",
@@ -718,7 +744,8 @@ def _execute_lanes(settings: dict,
def install(emit, cancel):
_models._install_models(audiocpp_dir, settings["install_guidance"],
settings["download"], emit=emit, cancel=cancel,
- model_entries=settings["model_entries"])
+ model_entries=settings["model_entries"],
+ companions=settings.get("companion_guidance"))
_build._print_launch_hint(audiocpp_dir, settings["output_path"])
return 0
# Everything already on disk: the install step just reports it, so the
@@ -992,9 +1019,9 @@ def _collect_from_flags(args: argparse.Namespace,
def task_picker(install_id: str) -> str:
return TASK_VDES
- model_entries, entry_ids, install_guidance, design_entry_ids, include_clone = \
- _build_entries(family_keys, chosen, catalog_by_family,
- task_picker)
+ model_entries, entry_ids, install_guidance, companion_guidance, \
+ design_entry_ids, include_clone = _build_entries(
+ family_keys, chosen, catalog_by_family, task_picker)
# Server settings. Host is always 127.0.0.1 and the port comes from
# AUDIOCPP_API_URL in app/converter/config.py (the Settings screen) —
@@ -1056,6 +1083,7 @@ def _collect_from_flags(args: argparse.Namespace,
"model_entries": model_entries,
"entry_ids": entry_ids,
"install_guidance": install_guidance,
+ "companion_guidance": companion_guidance,
"design_entry_ids": design_entry_ids,
"include_clone": include_clone,
"host": host,