Files
SoundGame Dev f0f0a9b50e 初始提交:3 款纯音频游戏 + 共享引擎 + 完整文档与资产管线
- 共享引擎(app/src/main):GestureEngine 6 手势识别、AudioEngine 三层音频
  (ExoPlayer BGM 交叉淡入 / 对白 ducking / SoundPool 低延迟)、Game/GameEngine
  状态机接口、MainActivity 全屏封面 + TalkBack
- 《声命线》storyline:末世互动广播剧,3 幕 8 抉择点 4 结局
- 《声东击西》reflex:听声辨位反应,12 波战斗 + BGM 三档 BPM 变速
- 《暗室》escape:3x3 网格密室逃脱,钥匙→铁柜→保险丝→电箱→大门谜题链
- 文档:setup(从零搭建)/ architecture(架构)/ engine-api(引擎 API)/
  asset-pipeline(资产流水线)/ games/*(三款游戏设计文档)
- 资产管线:Qwen3-TTS 对白 + 程序合成音效/BGM + Mureka BGM 的 gen 脚本与台账,
  全部 ogg 资产入库可复现
- env.d 环境脚本:android/tts 入库;sfx/mureka 含密钥不入库,仅提交 .example.sh 模板
2026-08-29 13:00:34 +08:00

182 lines
9.0 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# sa3_trt bootstrap — Stable Audio 3 inference on NVIDIA GPUs in one command.
#
# Hosted at:
# https://raw.githubusercontent.com/Stability-AI/stable-audio-3/main/optimized/tensorRT/bootstrap.sh
#
# Usage:
# curl -LsSf https://raw.githubusercontent.com/Stability-AI/stable-audio-3/main/optimized/tensorRT/bootstrap.sh | bash
# curl -LsSf https://raw.githubusercontent.com/Stability-AI/stable-audio-3/main/optimized/tensorRT/bootstrap.sh | bash -s -- --prompt "Death Metal" --dit medium --decoder same-l
#
# Default demo prompt is "Death Metal".
#
# What it does:
# 1. Verifies you're on Linux with an NVIDIA GPU.
# 2. Installs `git` via the system package manager if it's not already present,
# then shallow-clones github.com/Stability-AI/stable-audio-3.
# 3. cd's into optimized/tensorRT/ and runs ./install.sh -y (uv + Python +
# venv + arch-aware TRT engine downloads, or build-from-ONNX if no
# prebuilt engines exist for this arch).
# 4. Runs ./sa3 with whatever args you passed (default: "Death Metal" demo,
# medium DiT + SAME-L decoder, 120s).
#
set -euo pipefail
REPO_OWNER="Stability-AI"
REPO_NAME="stable-audio-3"
BRANCH="main"
SUBDIR_IN_REPO="optimized/tensorRT"
CLONE_DIR="$REPO_NAME" # full repo cloned here
WORKDIR="$CLONE_DIR/$SUBDIR_IN_REPO" # where install.sh + sa3 live
DEFAULT_ARGS=(--prompt "Death Metal" --dit medium --decoder same-l --seconds 120)
# ── colours ─────────────────────────────────────────────────────────────────
if [[ -t 1 ]]; then
BOLD=$'\033[1m'; CYAN=$'\033[1;36m'; RED=$'\033[1;31m'
YELLOW=$'\033[1;33m'; GREEN=$'\033[1;32m'; DIM=$'\033[2m'; RESET=$'\033[0m'
else
BOLD=""; CYAN=""; RED=""; YELLOW=""; GREEN=""; DIM=""; RESET=""
fi
step() { printf '\n%s→ %s%s\n' "$CYAN" "$1" "$RESET"; }
fail() { printf '\n%serror%s: %s\n' "$RED" "$RESET" "$1" >&2; exit 1; }
ok() { printf ' %s✓%s %s\n' "$GREEN" "$RESET" "$1"; }
warn() { printf '%swarning%s: %s\n' "$YELLOW" "$RESET" "$1" >&2; }
# ── 1. platform sanity ──────────────────────────────────────────────────────
OS="$(uname -s)"; ARCH="$(uname -m)"
if [[ "$OS" != "Linux" ]]; then
printf '\n%serror%s: this stack is Linux-only (TensorRT requires the NVIDIA Linux CUDA toolchain). Detected %s/%s.\n' "$RED" "$RESET" "$OS" "$ARCH" >&2
printf '\n For your platform use one of the other optimized routes:\n' >&2
printf ' CPU (macOS/Linux/Windows, x86/ARM):\n' >&2
printf ' curl -LsSf https://raw.githubusercontent.com/Stability-AI/stable-audio-3/main/optimized/tflite/bootstrap.sh | bash\n' >&2
printf ' (Windows: irm https://raw.githubusercontent.com/Stability-AI/stable-audio-3/main/optimized/tflite/bootstrap.ps1 | iex)\n' >&2
printf ' Apple Silicon GPU (fastest on Mac):\n' >&2
printf ' curl -LsSf https://raw.githubusercontent.com/Stability-AI/stable-audio-3/main/optimized/mlx/bootstrap.sh | bash\n' >&2
exit 1
fi
if [[ "$ARCH" != "x86_64" && "$ARCH" != "aarch64" ]]; then
warn "untested architecture $ARCH — TensorRT typically supports x86_64 and aarch64."
fi
ok "platform: $OS/$ARCH"
# ── 2. preflight: nvidia-smi ────────────────────────────────────────────────
command -v nvidia-smi >/dev/null 2>&1 || fail "nvidia-smi not found on PATH."
GPU_INFO=$(nvidia-smi --query-gpu=name,compute_cap --format=csv,noheader,nounits 2>/dev/null | head -1)
[[ -n "$GPU_INFO" ]] || fail "nvidia-smi ran but reported no GPUs."
ok "GPU: $GPU_INFO"
# ── 2b. shortcut: already inside a checkout? skip clone, run in place ──────
# If the user ran bootstrap from inside optimized/tensorRT/ of an existing
# clone (e.g. for a re-install or to pick up fresh code after a `git pull`),
# don't try to clone the repo into a subdir — just use the current dir.
if [[ -f ./install.sh && -x ./sa3 && -d ./build && -d ./scripts ]]; then
step "Already inside an optimized/tensorRT/ checkout — using ./ in place"
cd "$(pwd)" # no-op; just makes the path absolute for later messages
[[ -x ./install.sh ]] || fail "install.sh not executable in $(pwd)."
ok "running install.sh in $(pwd)"
./install.sh -y
if [[ $# -gt 0 ]]; then
step "Running ./sa3 $*"
exec ./sa3 "$@"
else
step "Running demo: ./sa3 ${DEFAULT_ARGS[*]}"
exec ./sa3 "${DEFAULT_ARGS[@]}"
fi
fi
# ── 3. ensure git (with tarball fallback) ──────────────────────────────────
# Try every common Linux package manager; if all fail (no sudo, locked-down
# container, exotic distro, network issue, etc.) fall back to a curl+tar
# download of the GitHub source tarball. Either path ends with the repo
# checked out at $CLONE_DIR/.
if ! command -v git >/dev/null 2>&1; then
step "git not found — trying system package managers"
SUDO=""; [[ "$(id -u)" -ne 0 ]] && SUDO="sudo"
INSTALLED=0
for pm in apt-get dnf yum apk pacman zypper; do
command -v "$pm" >/dev/null 2>&1 || continue
case "$pm" in
apt-get) cmd="$SUDO apt-get update -qq && $SUDO apt-get install -y git" ;;
dnf) cmd="$SUDO dnf install -y git" ;;
yum) cmd="$SUDO yum install -y git" ;;
apk) cmd="$SUDO apk add git" ;;
pacman) cmd="$SUDO pacman -Sy --noconfirm git" ;;
zypper) cmd="$SUDO zypper install -y git" ;;
esac
printf " %s%s%s\n" "$DIM" "trying: $cmd" "$RESET"
# Run under bash -c so the && chain works without trying to shell-parse it twice.
if bash -c "$cmd"; then
INSTALLED=1
break
else
warn "$pm couldn't install git — trying next"
fi
done
if [[ "$INSTALLED" -ne 1 ]] || ! command -v git >/dev/null 2>&1; then
warn "couldn't install git via package manager — falling back to tarball download"
fi
fi
HAVE_GIT=0
if command -v git >/dev/null 2>&1; then
HAVE_GIT=1
ok "git: $(git --version | awk '{print $3}')"
else
# Need curl + tar for the fallback path.
for tool in curl tar; do
command -v "$tool" >/dev/null 2>&1 || \
fail "$tool not found — required for the tarball fallback. Install git OR ($tool) manually."
done
ok "tarball fallback path (curl + tar both present)"
fi
# ── 4. download the repo (clone if we have git, else tarball) ──────────────
if [[ -d "$WORKDIR" && -x "$WORKDIR/install.sh" ]]; then
if [[ "$HAVE_GIT" -eq 1 ]]; then
step "Reusing existing $CLONE_DIR/ (delete or 'cd $CLONE_DIR && git pull' to refresh)"
else
step "Reusing existing $CLONE_DIR/ (delete to re-download)"
fi
else
if [[ -e "$CLONE_DIR" ]]; then
fail "./$CLONE_DIR exists but doesn't have $SUBDIR_IN_REPO/install.sh — remove or rename it."
fi
if [[ "$HAVE_GIT" -eq 1 ]]; then
step "Cloning $REPO_OWNER/$REPO_NAME ($BRANCH) → ./$CLONE_DIR"
git clone --depth 1 -b "$BRANCH" \
"https://github.com/$REPO_OWNER/$REPO_NAME.git" "$CLONE_DIR"
else
step "Downloading $REPO_OWNER/$REPO_NAME ($BRANCH) tarball → ./$CLONE_DIR"
TAR_URL="https://github.com/$REPO_OWNER/$REPO_NAME/archive/refs/heads/$BRANCH.tar.gz"
TMP_TAR="$(mktemp -t sa3_repo.XXXXXX).tar.gz"
TMP_EXTRACT="$(mktemp -d -t sa3_extract.XXXXXX)"
trap 'rm -rf "$TMP_TAR" "$TMP_EXTRACT"' EXIT
curl -fL --progress-bar "$TAR_URL" -o "$TMP_TAR"
tar -xz -f "$TMP_TAR" -C "$TMP_EXTRACT"
SRC="$TMP_EXTRACT/$REPO_NAME-$BRANCH"
[[ -d "$SRC" ]] || fail "expected $REPO_NAME-$BRANCH/ inside the tarball — repo layout may have changed."
mv "$SRC" "$CLONE_DIR"
warn "tarball checkout — updates require re-running bootstrap (no 'git pull')."
fi
[[ -d "$WORKDIR" ]] || fail "didn't find $SUBDIR_IN_REPO/ inside ./$CLONE_DIR."
ok "ready at ./$WORKDIR"
fi
# ── 5. install ──────────────────────────────────────────────────────────────
cd "$WORKDIR"
[[ -x ./install.sh ]] || fail "install.sh missing or not executable in ./$WORKDIR."
step "Running ./install.sh -y"
./install.sh -y
# ── 6. inference ────────────────────────────────────────────────────────────
if [[ $# -gt 0 ]]; then
step "Running ./sa3 $*"
exec ./sa3 "$@"
else
step "Running demo: ./sa3 ${DEFAULT_ARGS[*]}"
printf ' %s(pass your own args via: curl -LsSf https://raw.githubusercontent.com/Stability-AI/stable-audio-3/main/optimized/tensorRT/bootstrap.sh | bash -s -- --prompt "..." ...)%s\n' "$DIM" "$RESET"
exec ./sa3 "${DEFAULT_ARGS[@]}"
fi