#!/usr/bin/env bash # VoiceGrab — Linux build # ./installer/build_linux.sh → core app, onefile (dist/VoiceGrab) # WITH_AI=1 ./installer/build_linux.sh → AI voice separation (torch+demucs) # onedir (dist/VoiceGrab-AI/) # # Why onedir for the AI build: bundling torch into a onefile blob makes every # startup re-extract ~2 GB (60–120 s). A onedir app starts instantly and the # directory doubles as the plan's "sidecar" artifact. set -euo pipefail cd "$(dirname "$0")/.." PY="${PYTHON:-.venv/bin/python}" [ -x "$PY" ] || { echo "Create the venv first: python3 -m venv .venv && .venv/bin/pip install -r requirements.txt"; exit 1; } command -v ffmpeg >/dev/null || { echo "ffmpeg not found in PATH (needed to resolve the binary)"; exit 1; } "$PY" -m pip install -q pyinstaller if [ "${WITH_AI:-0}" = "1" ]; then echo "Building WITH AI voice separation (torch+demucs, onedir)…" "$PY" -m pip install -q -r requirements-ai.txt AI_FLAGS=(--collect-all demucs --collect-all torch) LAYOUT=--onedir NAME="VoiceGrab-AI" else AI_FLAGS=() LAYOUT=--onefile NAME="VoiceGrab" fi FFMPEG_BIN="$(command -v ffmpeg)" FFPROBE_BIN="$(command -v ffprobe || true)" EXTRA=() if [ -n "${FFPROBE_BIN:-}" ]; then EXTRA+=(--add-binary "$FFPROBE_BIN:.") fi "$PY" -m PyInstaller --noconfirm --clean --windowed \ --name "$NAME" $LAYOUT \ --add-binary "$FFMPEG_BIN:." \ ${EXTRA[@]+"${EXTRA[@]}"} \ ${AI_FLAGS[@]+"${AI_FLAGS[@]}"} \ --add-data "assets/icon.png:assets" \ --icon assets/icon.ico \ voicegrab.py echo if [ "$LAYOUT" = "--onedir" ]; then echo "App dir: dist/$NAME/" echo "Test: dist/$NAME/$NAME" else echo "Binary: dist/$NAME" echo "Test: ./dist/$NAME" fi # Optional: wrap in an AppImage if command -v linuxdeploy >/dev/null 2>&1; then echo "Building AppImage with linuxdeploy..." linuxdeploy --appimage --input dist/ --output appimage elif command -v appimagetool >/dev/null 2>&1; then echo "linuxdeploy not found; appimagetool present — build a .dir first, then run:" echo " appimagetool dist/VoiceGrab-Dir VoiceGrab-x86_64.AppImage" else echo "Tip: install linuxdeploy (or appimagetool) to produce an AppImage." fi