diff options
Diffstat (limited to 'producer.sh')
| -rwxr-xr-x | producer.sh | 35 |
1 files changed, 27 insertions, 8 deletions
diff --git a/producer.sh b/producer.sh index d2a139f..5814abc 100755 --- a/producer.sh +++ b/producer.sh @@ -8,7 +8,8 @@ # Trust boundary for downloads: official PyPI (uv, application wheels) and # Astral's managed CPython distribution. AI setup additionally trusts # download.pytorch.org, the pinned DeepFilterNet3 model host, and Hugging Face -# (ClearVoice MossFormer2_SE_48K weights). Host package-manager settings +# (ClearVoice MossFormer2_SE_48K weights), plus hash-checked Silero VAD +# weights from its pinned GitHub release. Host package-manager settings # (extra indexes, targets, constraints, config files) cannot add to or # redirect these sources. # @@ -29,8 +30,10 @@ RUNTIME="$LIB/runtime" APP="$RUNTIME/app" PROJECT="$LIB/project" READY="$RUNTIME/.producer-ready" -# Bump when the bootstrap recipe changes (python version, install steps...). -RUNTIME_VERSION="2" +GUI_READY="$RUNTIME/.producer-gui-ready" +# Bump when the bootstrap recipe or installed application contract changes. +# Version 4 adds the optional GUI command; only GUI launches install its extra. +RUNTIME_VERSION="4" usage() { cat <<'USAGE' @@ -43,6 +46,7 @@ Usage: ./producer.sh COMMAND [options], or simply: process RECORDING.wav... The same, with the explicit command keyword preview RECORDING.wav Render loudness-matched profile previews config Print resolved settings (TOML, or JSON with --json) + gui [--root PATH] [--port N] Open the optional local browser GUI (loopback only) doctor Check FFmpeg, data directory and CUDA driver setup --device cpu|cuda Install and self-test the AI backend (--denoiser clearvoice for the MossFormer2 backend) @@ -76,6 +80,9 @@ if [[ ${#ARGS[@]} -eq 1 && ( "${ARGS[0]}" == "-h" || "${ARGS[0]}" == "--help" ) exit 0 fi +WANT_GUI=0 +[[ "${ARGS[0]-}" == "gui" ]] && WANT_GUI=1 + # A config.toml next to this script is loaded automatically for every # command that accepts --config, unless one is given explicitly. Named CLI # flags and --set still override values from the file. @@ -87,7 +94,7 @@ if [[ $HAVE_CONFIG -eq 0 && -f "$ROOT/config.toml" ]]; then case "${ARGS[0]-}" in # After the command word: the CLI treats a leading non-command # argument as the implicit 'process' command and then as an input. - process|preview|config) + process|preview|config|gui) ARGS=("${ARGS[0]}" "--config=$ROOT/config.toml" "${ARGS[@]:1}") ;; # These commands take no --config (or no arguments at all). @@ -127,7 +134,9 @@ marker_current() { # a failed or interrupted rebuild leaves neither, forcing a repair. [[ -f "$READY" ]] \ && [[ "$(cat -- "$READY" 2>/dev/null)" == "$RUNTIME v$RUNTIME_VERSION" ]] \ - && [[ -x "$APP/bin/python" ]] + && [[ -x "$APP/bin/python" ]] \ + && { [[ "$WANT_GUI" -eq 0 ]] || { [[ -f "$GUI_READY" ]] \ + && [[ "$(cat -- "$GUI_READY" 2>/dev/null)" == "$RUNTIME v$RUNTIME_VERSION" ]]; }; } } bootstrap() { @@ -156,7 +165,7 @@ bootstrap() { # Invalidate the marker before any destructive work: if this bootstrap # fails or is interrupted, the next launch repairs instead of trusting # a half-built environment. - rm -f -- "$READY" "$READY.tmp" + rm -f -- "$READY" "$READY.tmp" "$GUI_READY" log "Preparing the contained runtime in lib/runtime (first run, or the directory moved)" local UV="" @@ -191,18 +200,28 @@ bootstrap() { || fail "Creating the managed Python 3.13 environment failed; check network access and free space." # The bundled FFmpeg wheel is preferred; where it does not exist (for # example musl systems), fall back to a system FFmpeg at runtime. + local bundled="$PROJECT[bundled-ffmpeg]" core="$PROJECT" + if [[ "$WANT_GUI" -eq 1 ]]; then + bundled="$PROJECT[bundled-ffmpeg,gui]" + core="$PROJECT[gui]" + fi if ! err="$("$UV" pip install --python "$APP/bin/python" --index-url https://pypi.org/simple \ - "$PROJECT[bundled-ffmpeg]" 2>&1 >/dev/null)"; then + "$bundled" 2>&1 >/dev/null)"; then log "Bundled FFmpeg wheel unavailable; installing core dependencies (a system FFmpeg is then required)." if [[ -n "$err" ]]; then sed 's/^/[producer] /' <<<"$err" >&2 fi - "$UV" pip install --python "$APP/bin/python" --index-url https://pypi.org/simple "$PROJECT" \ + "$UV" pip install --python "$APP/bin/python" --index-url https://pypi.org/simple "$core" \ || fail "Installing the application dependencies failed; check network access and free space." fi "$APP/bin/python" -I -c "import producer" >/dev/null 2>&1 \ || fail "The application environment failed verification." + if [[ "$WANT_GUI" -eq 1 ]]; then + "$APP/bin/python" -I -c "import fastapi, uvicorn" >/dev/null 2>&1 \ + || fail "The optional GUI environment failed verification." + printf '%s v%s\n' "$RUNTIME" "$RUNTIME_VERSION" > "$GUI_READY" + fi printf '%s v%s\n' "$RUNTIME" "$RUNTIME_VERSION" > "$READY.tmp" mv -f -- "$READY.tmp" "$READY" # Downgrade to the shared runtime lock for the application's lifetime. |
