初始提交: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 模板
This commit is contained in:
SoundGame Dev
2026-08-29 13:00:34 +08:00
commit f0f0a9b50e
446 changed files with 2627836 additions and 0 deletions
+225
View File
@@ -0,0 +1,225 @@
# SoundGame — 从零环境搭建手册
本文档描述在一台全新的 WSL2(Ubuntu)机器上,如何以**纯用户态(无 sudo)**方式
复现本项目的全部开发环境:Android 构建链、Qwen3-TTS 对白生成、Stable Audio 3
音效生成、ffmpeg 音频处理。
前置条件:
- WSL2 + Ubuntu,能访问外网(部分站点需走镜像,见文末速查表)
- NVIDIA GPU(本项目用 RTX 3090 24GB)+ Windows 侧已装 NVIDIA 驱动
(WSL2 透传 CUDA,无需在 WSL 内装驱动,只需 `nvidia-smi` 能跑通)
- 项目放在 `/home/ubuntu/SoundGame`,下文所有路径以此为准
## 为什么不用 apt
- 本机**没有 sudo 权限**,`apt install` 直接不可用;
- 即使可用,Ubuntu 仓库的 JDK / Android SDK / ffmpeg 版本也偏旧,
且会污染系统目录,不利于把整个环境收进项目目录随仓库一起搬走;
- 所有工具因此都装在 `/home/ubuntu/SoundGame/tools/` 或用户目录下,
通过 `env.d/*.sh` 注入 PATH 使用,不开 shell 不污染环境。
## 1. uv(Python 包/环境管理)
```bash
curl -LsSf https://astral.sh/uv/install.sh | sh # 装到 ~/.local/bin
~/.local/bin/uv --version # 实测 0.12.7 (x86_64-unknown-linux-gnu)
```
uv 自带 `python` 管理和虚拟环境管理,后续两个 venv 都由它创建。
注意 uv 不在默认 PATH,`env.d/sfx.sh` 里有 `export PATH="$HOME/.local/bin:$PATH"`。
## 2. JDK 17(用户态)
```bash
# 来源:华为云镜像的 Oracle OpenJDK 17.0.2(Adoptium 官方源在本机过慢)
# https://repo.huaweicloud.com/openjdk/17.0.2/openjdk-17.0.2_linux-x64_bin.tar.gz
cd /home/ubuntu/SoundGame/tools
curl -LO https://repo.huaweicloud.com/openjdk/17.0.2/openjdk-17.0.2_linux-x64_bin.tar.gz
tar xzf openjdk-17.0.2_linux-x64_bin.tar.gz
mv jdk-17.0.2 jdk17
tools/jdk17/bin/java -version # openjdk 17.0.2
```
## 3. Android SDK(cmdline-tools,无 Android Studio)
```bash
cd /home/ubuntu/SoundGame/tools
# 来源:Google 官方 dl.google.com(commandlinetools-linux-15859902_latest.zip)
curl -LO https://dl.google.com/android/repository/commandlinetools-linux-15859902_latest.zip
unzip commandlinetools-linux-15859902_latest.zip -d android-sdk-tmp
# 官方要求目录结构必须是 cmdline-tools/latest/,否则 sdkmanager 报路径错误
mkdir -p android-sdk/cmdline-tools
mv android-sdk-tmp/cmdline-tools android-sdk/cmdline-tools/latest
rm -rf android-sdk-tmp commandlinetools-linux-15859902_latest.zip
source /home/ubuntu/SoundGame/env.d/android.sh # 注入 JAVA_HOME/ANDROID_HOME/PATH
yes | sdkmanager --licenses
sdkmanager "platform-tools" "platforms;android-36" "build-tools;36.0.0"
```
安装结果(与 `env.d/android.md` 一致):platform-tools 37.0.1、android-36、
build-tools 36.0.0。
## 4. ffmpeg / ffprobe(静态构建)
```bash
# 来源:BtbN/FFmpeg-Builds 的 linux-x86_64 静态版(crosstool-NG 构建,零依赖)
# https://github.com/BtbN/FFmpeg-Builds/releases (ffmpeg-master-latest-linux64-gpl.tar.xz)
mkdir -p /home/ubuntu/SoundGame/tools/bin
# 解压后把 ffmpeg / ffprobe 两个二进制放进 tools/bin/ 即可
/home/ubuntu/SoundGame/tools/bin/ffmpeg -version
# 实测版本 N-126303-g9f35e220ff-20260827,含 libvorbis/libmp3lame/libopus
```
必须用含 `libvorbis` 的构建(资产出片格式是 ogg vorbis),GPL 版静态包自带。
## 5. Gradle
不需要单独安装:项目用 Gradle Wrapper,首次 `./gradlew` 自动下载。
本机 dl.google.com / services.gradle.org 均较慢,wrapper 已指向腾讯镜像:
```
# gradle/wrapper/gradle-wrapper.properties
distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.13-bin.zip
```
首次构建:
```bash
source /home/ubuntu/SoundGame/env.d/android.sh
cd /home/ubuntu/SoundGame
./gradlew assembleDebug # 首次下载依赖较慢属正常,daemon 有缓存
```
## 6. Qwen3-TTS 对白环境(.venv-tts)
```bash
cd /home/ubuntu/SoundGame
~/.local/bin/uv venv .venv-tts --python 3.12 # 实测 Python 3.12.14
# PyPI 走阿里云镜像,torch 需 cu128 轮子
~/.local/bin/uv pip install --python .venv-tts/bin/python \
--index-url https://mirrors.aliyun.com/pypi/simple/ \
qwen-tts soundfile transformers
~/.local/bin/uv pip install --python .venv-tts/bin/python \
torch torchaudio --index-url https://download.pytorch.org/whl/cu128
```
实测版本:`torch 2.11.0+cu128`、`torchaudio 2.11.0+cu128`、`qwen-tts 0.1.1`、
`transformers 4.57.3`。
模型下载(共 3 个仓库,缓存在 `models/hf`,由 `HF_HOME` 指定):
```bash
source /home/ubuntu/SoundGame/env.d/tts.sh # HF_HOME + HF_ENDPOINT=https://hf-mirror.com
.venv-tts/bin/python -c "
from huggingface_hub import snapshot_download
for repo in ['Qwen/Qwen3-TTS-12Hz-1.7B-CustomVoice',
'Qwen/Qwen3-TTS-12Hz-1.7B-VoiceDesign',
'Qwen/Qwen3-TTS-Tokenizer-12Hz']:
snapshot_download(repo); print('ok', repo)
"
```
**镜像注意事项**:本机连不通 huggingface.co,公开模型必须走
`HF_ENDPOINT=https://hf-mirror.com`(tts.sh 已设好)。Qwen 三个仓库均为公开
仓库,经镜像下载无障碍;gated 模型则不能走镜像,见下节。
冒烟测试:
```bash
source env.d/tts.sh
.venv-tts/bin/python tools/tts_smoke_test.py
# 输出 tools/samples/tts_test.wav(约 2s,24kHz)
```
详细用法(CustomVoice / VoiceDesign / 预置音色表)见 `env.d/tts.md`。
## 7. Stable Audio 3 音效环境(gated 模型)
```bash
cd /home/ubuntu/SoundGame/tools
git clone <stable-audio-3 仓库> stable-audio-3 # 项目内已有副本
cd stable-audio-3
cp /home/ubuntu/SoundGame/env.d/sfx.example.sh /home/ubuntu/SoundGame/env.d/sfx.sh
# 编辑 sfx.sh 填入真实 HF_TOKEN(见下)
source /home/ubuntu/SoundGame/env.d/sfx.sh
uv sync --extra ui # Python 3.10 venv,PyPI 走阿里云镜像(sfx.sh 已设)
```
实测:Python 3.10.6,`torch 2.7.1+cu126`,CUDA 验证通过。
### gated 模型 token 获取流程
`stabilityai/stable-audio-3-small-sfx` 是 **gated(auto 批准)** 仓库:
1. 注册/登录 HuggingFace 账号;
2. 打开 https://huggingface.co/stabilityai/stable-audio-3-small-sfx
接受 **Stable Audio Community License**(auto 模式立即通过,无需人工审核);
3. 在 https://huggingface.co/settings/tokens 创建 **read** 权限 token;
4. 填入 `env.d/sfx.sh` 的 `HF_TOKEN`(该文件已被 .gitignore 忽略,不会入库)。
### 坑:hf-mirror 对 gated 模型的 308 重定向
**gated 模型不能走 hf-mirror**:镜像会把带 token 的请求 308 重定向回
huggingface.co,本机直连官方又不可达时会直接失败。因此 `env.d/sfx.sh` 里
**故意不设 `HF_ENDPOINT`**(直连官方端点,当前实测 huggingface.co 对该域名
可达)。如果以后直连失效且只下公开模型,可临时取消脚本里的镜像注释。
Qwen3-TTS(公开)走镜像、Stable Audio 3(gated)走直连——这就是
`tts.sh` 与 `sfx.sh` 的 `HF_ENDPOINT` 配置相反的原因。两个环境不要同时 source。
## 8. Mureka BGM API(可选,需付费 key)
```bash
cp env.d/mureka.example.sh env.d/mureka.sh # 填入 https://platform.mureka.ai 的 key
source env.d/mureka.sh
python3 tools/mureka_gen.py --prompt "..." --out tools/mureka_out/xxx
```
`env.d/mureka.sh` 含真实 API key,已被 .gitignore 忽略。计费与调用记录见
`tools/mureka_log.md`,完整流程见 `docs/asset-pipeline.md`。
## 网络镜像速查表
| 用途 | 镜像 | 配置位置 |
|---|---|---|
| HuggingFace 公开模型 | `https://hf-mirror.com` | `HF_ENDPOINT`(tts.sh / gen 脚本内) |
| HuggingFace gated 模型 | **不可用**,直连官方 | sfx.sh 故意不设 HF_ENDPOINT |
| PyPI | `https://mirrors.aliyun.com/pypi/simple/` | `UV_DEFAULT_INDEX` / `uv pip --index-url` |
| Gradle 发行包 | `https://mirrors.cloud.tencent.com/gradle/` | `gradle/wrapper/gradle-wrapper.properties` |
| JDK | `https://repo.huaweicloud.com/openjdk/` | 手动下载 |
## 常见故障排查
**`sdkmanager` 提示路径/找不到**
cmdline-tools 必须位于 `android-sdk/cmdline-tools/latest/`,多一层少一层都会报错。
**Gradle 下载卡住**
确认 wrapper 用的是腾讯镜像(见上);依赖仓库(google/mavenCentral)本机直连可用,
如不行可在 `settings.gradle.kts` 临时加阿里云 maven 镜像。
**`qwen-tts` 打印 sox 警告**
系统无 `sox` 二进制(无 sudo 装不了),警告可忽略,不影响生成;
只有用到 sox 音频处理链路时才需要它。
**HF 下载 403 / 401**
模型是 gated 的(Stable Audio 3):先接受许可再带 token;且 gated 模型经
hf-mirror 会被 308 回官网,见第 7 节。
**HF 下载卡住不动**
确认 `HF_ENDPOINT=https://hf-mirror.com` 已生效(`source env.d/tts.sh`),
并关掉 hf_transfer(`HF_HUB_ENABLE_HF_TRANSFER=0`,tts.sh 已设)。
**TTS / SFX 同时抢 GPU**
所有 GPU 任务必须用 `flock /home/ubuntu/SoundGame/.gpu.lock` 串行
(各 gen_voice.py 头部注释都有标准命令)。Stable Audio 3 small 峰值显存约
2.4GB,Qwen3-TTS 1.7B bf16 也远低于 24GB,理论上可共存,但仍建议串行省心。
**WSL2 里 `adb devices` 看不到手机**
WSL2 不能直接访问 USB。用无线调试(`adb pair` + `adb connect`)或让 adb server
跑在 Windows 侧,详见 `env.d/android.md`。
**真机上第一个音效没声音**
SoundPool 加载是异步的,首个音效会被吞。三个游戏都已在 `onStart` 里用
音量 0 预播预热(搜索源码里的 `prewarm`),新增音效记得加进预热清单。