aboutsummaryrefslogtreecommitdiff
path: root/app/backends/audiocpp/wizard.py
diff options
context:
space:
mode:
authorhistoria <historiavg@proton.me>2026-08-28 18:44:32 -0400
committerhistoria <historiavg@proton.me>2026-08-28 18:44:32 -0400
commit03ed68bafec56ef8bb690440d796c1a742042907 (patch)
tree9f80e1848ca8c141f49875ffdbe462527ab0a9c3 /app/backends/audiocpp/wizard.py
parent3c9b7e12029f6accdaabb6f60e01bce88156db98 (diff)
downloadtts-audiobook-generator-03ed68bafec56ef8bb690440d796c1a742042907.tar.gz
feat(audio.cpp): if github binary download fails, automatically start building from source
Diffstat (limited to 'app/backends/audiocpp/wizard.py')
-rw-r--r--app/backends/audiocpp/wizard.py96
1 files changed, 60 insertions, 36 deletions
diff --git a/app/backends/audiocpp/wizard.py b/app/backends/audiocpp/wizard.py
index 5b237c4..f35aac1 100644
--- a/app/backends/audiocpp/wizard.py
+++ b/app/backends/audiocpp/wizard.py
@@ -303,6 +303,7 @@ def _wizard(stdscr, args: argparse.Namespace, parser: argparse.ArgumentParser
"backend": backend,
"build": build,
"build_mode": s.get("build_mode"),
+ "prebuilt_forced": False,
"lazy_load": True,
"sync_port": None,
"wav_dir": s["wav_dir"],
@@ -621,39 +622,44 @@ def _execute_lanes(settings: dict,
if build:
mode = settings.get("build_mode") or "source"
+ forced = bool(settings.get("prebuilt_forced"))
+
+ def source_build_step(emit, cancel) -> int:
+ """Build from source, warning-and-continue like the setup."""
+ rc = _build.build_audiocpp(audiocpp_dir, settings["backend"],
+ emit=emit, cancel=cancel)
+ if rc == 124:
+ print("[WARNING] build went silent and was stopped; the "
+ "server.json was still written — build "
+ "audiocpp_server manually before starting it")
+ elif rc != 0:
+ print(f"[WARNING] build exited with code {rc}; the "
+ "server.json was still written — build "
+ "audiocpp_server manually before starting it")
+ else:
+ print("[OK] build complete")
+ return rc
+
if mode == "prebuilt":
def build_step(emit, cancel):
rc = _prebuilt.install_prebuilt(
audiocpp_dir, settings["backend"],
emit=emit, cancel=cancel)
- if rc == 130:
- return rc
- if rc != 0:
- print(f"[WARNING] prebuilt download failed (exit {rc}); "
- "the server.json was still written — build "
- "audiocpp_server from source ('Build audio.cpp "
- "Server', or re-run with --prebuilt no) before "
- "starting it")
- else:
+ if rc == 0:
print("[OK] prebuilt audiocpp_server installed")
- return rc
- build_title = (f"Download prebuilt audiocpp_server "
- f"({settings['backend']})")
+ return 0
+ if rc == 130 or forced:
+ # A cancelled download, or one the user explicitly
+ # forced with --prebuilt yes: fail fast.
+ return rc
+ # The usual failure is GitHub's API rate limit — recover
+ # in place instead of leaving the setup half-installed.
+ print(f"[WARNING] prebuilt download failed (exit {rc}); "
+ "falling back to a source build...")
+ return source_build_step(emit, cancel)
+ build_title = f"Install audiocpp_server ({settings['backend']})"
else:
- def build_step(emit, cancel):
- rc = _build.build_audiocpp(audiocpp_dir, settings["backend"],
- emit=emit, cancel=cancel)
- if rc == 124:
- print("[WARNING] build went silent and was stopped; the "
- "server.json was still written — build "
- "audiocpp_server manually before starting it")
- elif rc != 0:
- print(f"[WARNING] build exited with code {rc}; the "
- "server.json was still written — build "
- "audiocpp_server manually before starting it")
- else:
- print("[OK] build complete")
- return rc
+ build_step = source_build_step
build_title = f"Build audiocpp_server ({settings['backend']})"
lanes.append(taskview.TaskLane(
"Build",
@@ -831,14 +837,25 @@ def build_screen(stdscr) -> int:
if mode is _GO_BACK:
return 1
+ outcome: dict = {"prebuilt": False}
+
def build_step(emit, cancel):
if mode == "prebuilt":
- return _prebuilt.install_prebuilt(checkout, backend,
- emit=emit, cancel=cancel)
+ rc = _prebuilt.install_prebuilt(checkout, backend,
+ emit=emit, cancel=cancel)
+ if rc == 0:
+ outcome["prebuilt"] = True
+ return 0
+ if rc == 130:
+ return rc
+ # The usual failure is GitHub's API rate limit — recover in
+ # place instead of sending the user back to the menus.
+ print(f"[WARNING] prebuilt download failed (exit {rc}); "
+ "falling back to a source build...")
return _build.build_audiocpp(checkout, backend, emit=emit,
cancel=cancel)
- action = "Download prebuilt audiocpp_server" if mode == "prebuilt" \
+ action = f"Install audiocpp_server ({backend})" if mode == "prebuilt" \
else f"Build audiocpp_server ({backend})"
lanes = [taskview.TaskLane("Build", [taskview.TaskStep(action,
build_step)])]
@@ -858,15 +875,15 @@ def build_screen(stdscr) -> int:
"Download models",
[taskview.TaskStep("Download missing models", download_step)]))
- install_title = ("Download prebuilt audiocpp_server"
- if mode == "prebuilt" else "Build audiocpp_server")
+ install_title = ("Install audiocpp_server" if mode == "prebuilt"
+ else "Build audiocpp_server")
title = f"{install_title} & download models" if len(lanes) == 2 \
else install_title
rc = taskview.run_lanes(stdscr, title, lanes)
if rc != 0:
return rc
if not _configsync.update_server_backend(backend):
- verb = "installed" if mode == "prebuilt" else "built"
+ verb = "installed" if outcome["prebuilt"] else "built"
tui.flash(stdscr, f"audiocpp_server {verb} for {backend}. (Could not "
"update server.json's backend field — reconfigure audio.cpp "
"if it was already configured.)", "warn")
@@ -995,8 +1012,12 @@ def _collect_from_flags(args: argparse.Namespace,
build = False
# How a pending install happens: the prebuilt release by default on
# macOS/Windows (``--prebuilt no`` forces the source build), always
- # the source build elsewhere.
+ # the source build elsewhere. A ``--prebuilt yes`` download that
+ # fails stays a failure (no source-build fallback) — the flag's
+ # whole point is "do not build".
build_mode = _flag_build_mode(args, backend) if build else None
+ prebuilt_forced = bool(build) and getattr(args, "prebuilt", "auto") \
+ == "yes"
port = _configsync.config_port()
lazy_load = True
@@ -1039,6 +1060,7 @@ def _collect_from_flags(args: argparse.Namespace,
"backend": backend,
"build": build,
"build_mode": build_mode,
+ "prebuilt_forced": prebuilt_forced,
"lazy_load": lazy_load,
"sync_port": None,
"wav_dir": wav_dir,
@@ -1088,9 +1110,11 @@ def build_parser() -> argparse.ArgumentParser:
default="auto",
help="How to install audiocpp_server when it is "
"missing: auto downloads the prebuilt release "
- "on macOS/Windows and builds from source "
- "elsewhere; yes forces the prebuilt download; "
- "no forces a source build")
+ "on macOS/Windows (falling back to a source "
+ "build if the download fails) and builds from "
+ "source elsewhere; yes forces the prebuilt "
+ "download and fails if it cannot; no forces a "
+ "source build")
parser.add_argument("--whisper-model", type=str, default="base",
help="Whisper model size for transcription "
"(default: base)")