aboutsummaryrefslogtreecommitdiff
path: root/app/backends/audiocpp/wizard.py
diff options
context:
space:
mode:
authorhistoria <historiavg@proton.me>2026-08-26 18:39:33 -0400
committerhistoria <historiavg@proton.me>2026-08-26 18:39:33 -0400
commitdf95e7034df683c38fde67890430ab4c2abfa4ba (patch)
treef46d3eb393e605e82a4d058a2290061b77403649 /app/backends/audiocpp/wizard.py
parent544486a374cd5cae7acce1302648d8dad079db48 (diff)
downloadtts-audiobook-generator-df95e7034df683c38fde67890430ab4c2abfa4ba.tar.gz
feat: in-place toggle field, updated transcription tui to use new field
Diffstat (limited to 'app/backends/audiocpp/wizard.py')
-rw-r--r--app/backends/audiocpp/wizard.py99
1 files changed, 23 insertions, 76 deletions
diff --git a/app/backends/audiocpp/wizard.py b/app/backends/audiocpp/wizard.py
index 831ae3d..bfc0eb7 100644
--- a/app/backends/audiocpp/wizard.py
+++ b/app/backends/audiocpp/wizard.py
@@ -143,33 +143,14 @@ def _write_and_advise(audiocpp_dir: Path, wav_dir: Optional[Path],
f"{'entry' if count == 1 else 'entries'}.")
-def _transcription_choices(wav_files: list, existing: Dict[str, str],
- prompt_exists: bool) -> Tuple[list, str]:
- """Shape the transcription question for the setup form.
-
- Returns ``(choices, default_mode)`` where MODE is ``"all"``
- (re-transcribe everything), ``"missing"`` (only .wavs without an
- existing transcript) or ``"keep"`` (reuse prompt_text untouched).
- Plain choice pairs the combined config form can show on one row.
- """
- if not prompt_exists:
- return [("Re-transcribe all", "all")], "all"
- missing = [wav for wav in wav_files
- if not existing.get(wav.stem, "").strip()]
- if not missing:
- return ([("Keep the existing transcripts", "keep"),
- ("Re-transcribe all", "all")], "keep")
- return ([("Only transcribe new voices", "missing"),
- ("Re-transcribe all", "all")], "missing")
-
-
def _plan_from_mode(mode: str, wav_files: list,
existing: Dict[str, str]) -> dict:
"""Build the transcription PLAN for the chosen form MODE.
The plan dict is what ``voices._transcribe`` consumes: "missing"
- carries the .wavs lacking a transcript plus the existing mapping;
- "all"/"keep" name the mode and reuse the mapping read while asking.
+ carries the .wavs lacking a transcript plus the existing mapping,
+ "all" re-transcribes everything; both reuse the mapping read while
+ applying the form.
"""
if mode == "missing":
missing = [wav for wav in wav_files
@@ -365,18 +346,6 @@ def _wizard(stdscr, args: argparse.Namespace, parser: argparse.ArgumentParser
return next((f["value"] for f in fields_list
if f.get("key") == key), default)
- def _transcription_state(wav_dir):
- """(wav_files, existing transcripts, prompt_text exists) or None."""
- if wav_dir is None:
- return None
- wav_files = find_wav_files(Path(wav_dir))
- if not wav_files:
- return None
- prompt_path = Path(wav_dir) / PROMPT_TEXT_FILENAME
- prompt_exists = bool(prompt_path.exists()) and not args.force
- existing = read_prompt_text(prompt_path) if prompt_exists else {}
- return wav_files, existing, prompt_exists
-
def _apply_form(result: dict) -> dict:
"""Fold the form's answers into the settings and finalize."""
# Backend/build: the interactive combination. A backend whose
@@ -400,15 +369,18 @@ def _wizard(stdscr, args: argparse.Namespace, parser: argparse.ArgumentParser
# Transcription plan (transcription itself runs in the tail).
s["plan"] = None
if s["include_clone"]:
- state = _transcription_state(s["wav_dir"])
- if state is not None:
- wav_files, existing, prompt_exists = state
- choices, default_mode = _transcription_choices(
- wav_files, existing, prompt_exists)
- mode = result.get("transcription")
- if mode not in [candidate for _label, candidate in choices]:
- mode = default_mode
- s["plan"] = _plan_from_mode(mode, wav_files, existing)
+ wav_files = find_wav_files(Path(s["wav_dir"])) \
+ if s["wav_dir"] is not None else []
+ prompt_path = Path(s["wav_dir"]) / PROMPT_TEXT_FILENAME \
+ if s["wav_dir"] is not None else None
+ existing = {}
+ if prompt_path is not None and prompt_path.exists() \
+ and not args.force:
+ existing = read_prompt_text(prompt_path)
+ mode = result.get("transcription")
+ if mode not in ("missing", "all"):
+ mode = "missing"
+ s["plan"] = _plan_from_mode(mode, wav_files, existing)
s["download"] = bool(result.get("download")) and (
_models.download_applicable(s["audiocpp_dir"],
@@ -499,41 +471,16 @@ def _wizard(stdscr, args: argparse.Namespace, parser: argparse.ArgumentParser
}
fields.append(wav_field)
- def state_of(fs):
- return _transcription_state(_field_val(fs, "wav_dir"))
-
- initial_state = state_of([wav_field])
- initial_default = _transcription_choices(*initial_state)[1] \
- if initial_state is not None else "missing"
-
- def transcription_choices(fs):
- state = state_of(fs)
- if state is None:
- return [("Re-transcribe all", "all")]
- return _transcription_choices(*state)[0]
-
- def transcription_visible(fs) -> bool:
- return state_of(fs) is not None
-
- def reset_transcription(fs_list) -> None:
- # The directory changed: snap the stale choice to a valid one.
- field = next((f for f in fs_list
- if f.get("key") == "transcription"), None)
- if field is not None:
- modes = [mode for _label, mode in transcription_choices(
- fs_list)]
- if field["value"] not in modes:
- state = state_of(fs_list)
- field["value"] = _transcription_choices(*state)[1] \
- if state is not None else "missing"
-
+ # Voice transcript handling: a plain in-place toggle, always
+ # offered whenever any clone-capable model is hosted (no
+ # dependency on what the picked directory currently holds).
fields.append({
"key": "transcription", "label": "Voice transcripts",
- "kind": "choice", "value": initial_default,
- "choices": transcription_choices,
- "visible": transcription_visible,
+ "kind": "toggle", "value": "missing",
+ "choices": [("Transcribe new voices", "missing"),
+ ("Re-transcribe all voices", "all")],
+ "visible": lambda fs: bool(s["include_clone"]),
})
- wav_field["on_change"] = reset_transcription
if _models.download_applicable(s["audiocpp_dir"], s["model_entries"]):
fields.append({
@@ -575,7 +522,7 @@ def _wizard(stdscr, args: argparse.Namespace, parser: argparse.ArgumentParser
result = tui.form(
stdscr, "Configure audio.cpp", fields,
buttons=("Continue", "Cancel"),
- start_on_buttons=False, back_value=tui.Wizard.BACK)
+ start_on_buttons=True, back_value=tui.Wizard.BACK)
if result is tui.Wizard.BACK:
return tui.Wizard.BACK
return _apply_form(result)