- 共享引擎(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 模板
182 lines
9.0 KiB
Bash
Executable File
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
|