aboutsummaryrefslogtreecommitdiff
path: root/app/backends/audiocpp/catalog.py
diff options
context:
space:
mode:
authorhistoria <historiavg@proton.me>2026-08-26 20:43:05 -0400
committerhistoria <historiavg@proton.me>2026-08-26 20:43:05 -0400
commit65c6f737f1545ef225768af897acd20f163a4fb4 (patch)
tree9c0974944191e50b9caa90591dfcb7f97c659770 /app/backends/audiocpp/catalog.py
parent975bd960fd07e75799b8e3adc4c0033046b34792 (diff)
downloadtts-audiobook-generator-65c6f737f1545ef225768af897acd20f163a4fb4.tar.gz
fix: settings menu only prompts to save after change
Diffstat (limited to 'app/backends/audiocpp/catalog.py')
-rw-r--r--app/backends/audiocpp/catalog.py46
1 files changed, 46 insertions, 0 deletions
diff --git a/app/backends/audiocpp/catalog.py b/app/backends/audiocpp/catalog.py
index f1989e9..2892b9c 100644
--- a/app/backends/audiocpp/catalog.py
+++ b/app/backends/audiocpp/catalog.py
@@ -10,6 +10,52 @@ from .constants import TASK_TTS
DESIGN_PACKAGE_RE = re.compile(r"voice[\s_\-]?design", re.IGNORECASE)
+def request_options_families(audiocpp_dir: Path) -> Dict[str, dict]:
+ """Map the families whose spec defines per-request options.
+
+ Reads every ``model_specs/<family>.json`` in AUDIOCPP_DIR once and
+ returns ``{family_key: {"display_name": ...}}`` for the specs that
+ list request options (a non-empty ``options.request`` array) — the
+ families a "Request options" field makes sense for. The key is the
+ spec's ``family`` field (falling back to the file stem), matching
+ what ``GET /v1/models`` reports, so callers can look an entry up by
+ its family id. A missing or unreadable specs directory yields {}
+ (every family then counts as unknown rather than unsupported).
+ """
+ specs_dir = audiocpp_dir / "model_specs"
+ if not specs_dir.is_dir():
+ return {}
+ families: Dict[str, dict] = {}
+ for spec_path in sorted(specs_dir.glob("*.json")):
+ try:
+ spec = json.loads(spec_path.read_text(encoding="utf-8"))
+ except (OSError, ValueError):
+ continue
+ options = spec.get("options")
+ request = options.get("request") if isinstance(options, dict) else None
+ if not isinstance(request, list) or not request:
+ continue
+ family = str(spec.get("family") or spec_path.stem)
+ families[family] = {
+ "display_name": str(spec.get("display_name") or family),
+ }
+ return families
+
+
+def supports_request_options(families: Dict[str, dict],
+ family: str) -> Optional[bool]:
+ """Whether FAMILY accepts per-request options — None when unknown.
+
+ True only when FAMILIES (from request_options_families) lists the
+ family; False when it was read but does not define request options;
+ None when support cannot be determined from the local specs (no
+ checkout, or a family the specs do not describe).
+ """
+ if not families:
+ return None
+ return family in families
+
+
_BACKEND_DESCRIPTIONS = (
("cuda", "NVIDIA GPUs (fastest)"),
("vulkan", "cross-vendor GPU"),