Sonic Lab / AI Creative Studio 是一个集成式的 AI 创意内容生成平台,覆盖草图→图像、图像→3D、文字→音乐、音乐→音轨分离的完整创作管线。前端为 Vue 3 SPA,后端采用微服务架构(Flask),所有 GPU 推理通过统一的排队锁串行化。
外部访问 (port 7979)
│
├── serve.py (port 7979) ← 静态文件服务 + 反向代理
│ ├── 前端 dist/ (Vue 3 SPA)
│ ├── /vis/ (音乐可视化页面)
│ └── /api/* → main_server.py (port 5000)
│
└── main_server.py (port 5000) ← API 网关 + GPU 排队锁
│
├── /api/flux → flux_server.py (port 5001) [Qwen-Image-Edit-2509]
├── /api/sf3d → sf3d_server.py (port 5002) [Trellis2]
├── /api/acestep → acestep_server.py (port 5003) → upstream ACE-Step (port 8001)
├── /api/mucgen → mucgen_server.py (port 5004) [Demucs via subprocess]
│
├── /api/polish [DashScope Qwen-plus]
├── /api/glb2ply [trimesh]
├── /api/save-tracks
├── /api/gpu-status [nvidia-smi + queue state]
└── /backups/ [JSON 元数据 + PLY 文件]
| 决策 | 说明 |
|---|---|
| 单端口对外暴露 | serve.py 同时处理静态文件和 API 反向代理,容器只需暴露 7979 一个端口 |
| GPU 排队锁 | threading.Lock 串行化所有 GPU 请求(flux/sf3d/acestep/mucgen),避免 VRAM 争抢 |
| 前端 API 基址为空 | const API = '',所有请求走同源,由 serve.py 代理,无需 CORS 配置 |
| 独立 conda 环境 | 每个 AI 模型使用独立的 conda 环境,避免依赖冲突 |
frontend/
├── src/
│ ├── main.js # 入口:createApp(App).mount('#app')
│ ├── App.vue # 唯一 SPA 组件(全部 UI + 逻辑)
│ └── style.css # 基础样式
├── dist/ # Vite 构建输出
├── index.html # HTML 入口
├── serve.py # Flask 静态服务 + 反向代理(port 7979)
├── vite.config.js # Vite 配置
└── package.json # 依赖:vue ^3.5.30, three ^0.183.2
| 步骤 | 功能 | 关键技术 |
|---|---|---|
| 01 草图→图像 | Canvas 手绘 + 提示词 → 生成图像 | QwenImageEditPlusPipeline,POST /api/flux |
| 02 3D 模型 | 图像 → GLB 3D 模型 + PLY 导出 | Trellis2ImageTo3DPipeline,GLTFLoader + OrbitControls,POST /api/sf3d |
| 03 音乐生成 | 提示词 → WAV 音乐(30/60/90s) | ACE-Step,POST /api/acestep |
| 04 音轨分离 | 音乐 → 人声/鼓/贝斯/吉他/钢琴/其他 | Demucs v4,POST /api/mucgen |
setInterval 每 2s 轮询 /api/gpu-status,显示实时 GPU 利用率、温度、队列状态dispose3DModel() 在加载新模型前销毁旧的 renderer/scene/RAF 循环,防止 WebGL 上下文泄漏openVis() 调用 /api/save-tracks 保存音轨分配,跳转到 /vis/index.html?ply=...&bass=...&drums=...| 路由 | 行为 |
|---|---|
GET / | 返回 dist/index.html |
GET /<path> | 尝试 dist/ 中文件,不存在则返回 index.html(SPA 回退) |
GET/POST/... /api/<path> | 代理到 http://127.0.0.1:5000/api/<path> |
GET /backups/<path> | 代理到 http://127.0.0.1:5000/backups/<path> |
GET /health | 代理到 http://127.0.0.1:5000/health |
超时 1200 秒(20 分钟),以容纳长时间的 AI 推理。
_GpuSlot(基于 threading.Lock + deque 队列),所有 GPU 请求串行执行nvidia-smi 解析 + 内置队列状态,通过 /api/gpu-status 暴露POST /api/polish — DashScope Qwen-plus 润色提示词POST /api/glb2ply — GLB → PLY 格式转换(trimesh)POST /api/save-tracks — 保存可视化页面轨道分配GET /backups/<path> — 备份文件服务backups/ 下按类别(models/, music/, images/, tracks/, ply/)存储 JSON 元数据QwenImageEditPlusPipeline(diffusers),本地路径 /root/qwen_image_edit/models/Qwen-Image-Edit-2509torch, diffusers, PILTrellis2ImageTo3DPipeline,模型缓存 /root/.cache/trellis2_dlremesh=True, decimation_target=1_000_000, texture_size=4096)torch, trellis2.pipelines, o_voxel.postprocesshttp://127.0.0.1:8001,FastAPI + uvicorn)POST /release_task 提交 → POST /query_result 轮询(最长 30 分钟)proxy-audio?path=...)POST /api/acestep/generateGET /api/acestep/status/<task_id>GET /api/acestep/proxy-audio/root/musicBsubprocess 调用 /root/anaconda3/envs/demucs/bin/python -m demucs -n htdemucsaudio_url| 文件 | 说明 |
|---|---|
server.py | 旧版一体化服务器(所有模型进程内加载),不再使用 |
api_flux.py / api_sf3d.py / api_acestep.py / api_mucgen.py | 旧版模型包装类,不再使用 |
run_server.py | 旧版启动脚本,不再使用 |
位于 clients/ 目录,依赖仅有 requests,可直接通过 SSH 从外部机器调用:
| 脚本 | 端点 | 主要参数 |
|---|---|---|
generate_image.py | POST /api/flux | --input 草图, --prompt, --out |
generate_music.py | POST /api/acestep | --prompt, --duration, --instrumental, --out |
separate_music.py | POST /api/mucgen | --input 或 --url, --out-dir |
所有脚本内置 5 秒心跳线程,在等待时显示 GPU 队列状态。
qwen_image_edit conda 环境 | 端口:5001/root/qwen_image_edit/models/Qwen-Image-Edit-2509trellis2 conda 环境 | 端口:5002/root/Trellis2/ace_step conda 环境 | 上游端口:8001(uvicorn),包装端口:5003/root/musicgen/demucs conda 环境(子进程调用) | 端口:5004/root/musicB/openai.OpenAI),base_url=https://dashscope.aliyuncs.com/compatible-mode/v1POST /api/polish/root/full/muc-vis-comp/start.sh
按顺序启动 6 个进程 + 1 个前端服务。每个服务用 setsid + disown 后台运行,日志输出到 /tmp/muc-vis-comp/*.log。
# 健康检查
curl http://127.0.0.1:5000/health
curl http://127.0.0.1:7979/health
# GPU 状态
curl http://127.0.0.1:5000/api/gpu-status
# Mac 上建立 SSH 隧道
ssh -fN -o GatewayPorts=yes \
-L 0.0.0.0:7979:localhost:7979 \
-p 30230 root@10.15.171.204
# 浏览器访问 http://你Mac的IP:7979
/root/full/muc-vis-comp/backups/
├── images/ # 图像生成元数据 JSON
├── models/ # 3D 模型元数据 JSON
├── music/ # 音乐生成元数据 JSON(含 prompt, duration, audio_url, timestamp)
├── tracks/ # 音轨分配回放 JSON
└── ply/ # 导出的 PLY 文件
用户手绘草图 + 输入提示词
│
▼
[01] Qwen-Image-Edit-2509 → 照片级图像 (PNG)
│
▼
[02] Trellis2 → 3D 模型 (GLB) → GLB→PLY 转换
│
▼
[03] ACE-Step → 音乐 (WAV)
│
▼
[04] Demucs → 分离音轨 (人声/鼓/贝斯/吉他/钢琴/其他)
│
▼
音乐可视化页面 (Three.js 3D 场景 + 音轨播放)
1 commits
Python
38.6%
HTML
31.1%
Vue
25.1%
Shell
2.7%
CSS
2.3%
Sonic Lab / AI Creative Studio 是一个集成式的 AI 创意内容生成平台,覆盖草图→图像、图像→3D、文字→音乐、音乐→音轨分离的完整创作管线。前端为 Vue 3 SPA,后端采用微服务架构(Flask),所有 GPU 推理通过统一的排队锁串行化。
外部访问 (port 7979)
│
├── serve.py (port 7979) ← 静态文件服务 + 反向代理
│ ├── 前端 dist/ (Vue 3 SPA)
│ ├── /vis/ (音乐可视化页面)
│ └── /api/* → main_server.py (port 5000)
│
└── main_server.py (port 5000) ← API 网关 + GPU 排队锁
│
├── /api/flux → flux_server.py (port 5001) [Qwen-Image-Edit-2509]
├── /api/sf3d → sf3d_server.py (port 5002) [Trellis2]
├── /api/acestep → acestep_server.py (port 5003) → upstream ACE-Step (port 8001)
├── /api/mucgen → mucgen_server.py (port 5004) [Demucs via subprocess]
│
├── /api/polish [DashScope Qwen-plus]
├── /api/glb2ply [trimesh]
├── /api/save-tracks
├── /api/gpu-status [nvidia-smi + queue state]
└── /backups/ [JSON 元数据 + PLY 文件]
| 决策 | 说明 |
|---|---|
| 单端口对外暴露 | serve.py 同时处理静态文件和 API 反向代理,容器只需暴露 7979 一个端口 |
| GPU 排队锁 | threading.Lock 串行化所有 GPU 请求(flux/sf3d/acestep/mucgen),避免 VRAM 争抢 |
| 前端 API 基址为空 | const API = '',所有请求走同源,由 serve.py 代理,无需 CORS 配置 |
| 独立 conda 环境 | 每个 AI 模型使用独立的 conda 环境,避免依赖冲突 |
frontend/
├── src/
│ ├── main.js # 入口:createApp(App).mount('#app')
│ ├── App.vue # 唯一 SPA 组件(全部 UI + 逻辑)
│ └── style.css # 基础样式
├── dist/ # Vite 构建输出
├── index.html # HTML 入口
├── serve.py # Flask 静态服务 + 反向代理(port 7979)
├── vite.config.js # Vite 配置
└── package.json # 依赖:vue ^3.5.30, three ^0.183.2
| 步骤 | 功能 | 关键技术 |
|---|---|---|
| 01 草图→图像 | Canvas 手绘 + 提示词 → 生成图像 | QwenImageEditPlusPipeline,POST /api/flux |
| 02 3D 模型 | 图像 → GLB 3D 模型 + PLY 导出 | Trellis2ImageTo3DPipeline,GLTFLoader + OrbitControls,POST /api/sf3d |
| 03 音乐生成 | 提示词 → WAV 音乐(30/60/90s) | ACE-Step,POST /api/acestep |
| 04 音轨分离 | 音乐 → 人声/鼓/贝斯/吉他/钢琴/其他 | Demucs v4,POST /api/mucgen |
setInterval 每 2s 轮询 /api/gpu-status,显示实时 GPU 利用率、温度、队列状态dispose3DModel() 在加载新模型前销毁旧的 renderer/scene/RAF 循环,防止 WebGL 上下文泄漏openVis() 调用 /api/save-tracks 保存音轨分配,跳转到 /vis/index.html?ply=...&bass=...&drums=...| 路由 | 行为 |
|---|---|
GET / | 返回 dist/index.html |
GET /<path> | 尝试 dist/ 中文件,不存在则返回 index.html(SPA 回退) |
GET/POST/... /api/<path> | 代理到 http://127.0.0.1:5000/api/<path> |
GET /backups/<path> | 代理到 http://127.0.0.1:5000/backups/<path> |
GET /health | 代理到 http://127.0.0.1:5000/health |
超时 1200 秒(20 分钟),以容纳长时间的 AI 推理。
_GpuSlot(基于 threading.Lock + deque 队列),所有 GPU 请求串行执行nvidia-smi 解析 + 内置队列状态,通过 /api/gpu-status 暴露POST /api/polish — DashScope Qwen-plus 润色提示词POST /api/glb2ply — GLB → PLY 格式转换(trimesh)POST /api/save-tracks — 保存可视化页面轨道分配GET /backups/<path> — 备份文件服务backups/ 下按类别(models/, music/, images/, tracks/, ply/)存储 JSON 元数据QwenImageEditPlusPipeline(diffusers),本地路径 /root/qwen_image_edit/models/Qwen-Image-Edit-2509torch, diffusers, PILTrellis2ImageTo3DPipeline,模型缓存 /root/.cache/trellis2_dlremesh=True, decimation_target=1_000_000, texture_size=4096)torch, trellis2.pipelines, o_voxel.postprocesshttp://127.0.0.1:8001,FastAPI + uvicorn)POST /release_task 提交 → POST /query_result 轮询(最长 30 分钟)proxy-audio?path=...)POST /api/acestep/generateGET /api/acestep/status/<task_id>GET /api/acestep/proxy-audio/root/musicBsubprocess 调用 /root/anaconda3/envs/demucs/bin/python -m demucs -n htdemucsaudio_url| 文件 | 说明 |
|---|---|
server.py | 旧版一体化服务器(所有模型进程内加载),不再使用 |
api_flux.py / api_sf3d.py / api_acestep.py / api_mucgen.py | 旧版模型包装类,不再使用 |
run_server.py | 旧版启动脚本,不再使用 |
位于 clients/ 目录,依赖仅有 requests,可直接通过 SSH 从外部机器调用:
| 脚本 | 端点 | 主要参数 |
|---|---|---|
generate_image.py | POST /api/flux | --input 草图, --prompt, --out |
generate_music.py | POST /api/acestep | --prompt, --duration, --instrumental, --out |
separate_music.py | POST /api/mucgen | --input 或 --url, --out-dir |
所有脚本内置 5 秒心跳线程,在等待时显示 GPU 队列状态。
qwen_image_edit conda 环境 | 端口:5001/root/qwen_image_edit/models/Qwen-Image-Edit-2509trellis2 conda 环境 | 端口:5002/root/Trellis2/ace_step conda 环境 | 上游端口:8001(uvicorn),包装端口:5003/root/musicgen/demucs conda 环境(子进程调用) | 端口:5004/root/musicB/openai.OpenAI),base_url=https://dashscope.aliyuncs.com/compatible-mode/v1POST /api/polish/root/full/muc-vis-comp/start.sh
按顺序启动 6 个进程 + 1 个前端服务。每个服务用 setsid + disown 后台运行,日志输出到 /tmp/muc-vis-comp/*.log。
# 健康检查
curl http://127.0.0.1:5000/health
curl http://127.0.0.1:7979/health
# GPU 状态
curl http://127.0.0.1:5000/api/gpu-status
# Mac 上建立 SSH 隧道
ssh -fN -o GatewayPorts=yes \
-L 0.0.0.0:7979:localhost:7979 \
-p 30230 root@10.15.171.204
# 浏览器访问 http://你Mac的IP:7979
/root/full/muc-vis-comp/backups/
├── images/ # 图像生成元数据 JSON
├── models/ # 3D 模型元数据 JSON
├── music/ # 音乐生成元数据 JSON(含 prompt, duration, audio_url, timestamp)
├── tracks/ # 音轨分配回放 JSON
└── ply/ # 导出的 PLY 文件
用户手绘草图 + 输入提示词
│
▼
[01] Qwen-Image-Edit-2509 → 照片级图像 (PNG)
│
▼
[02] Trellis2 → 3D 模型 (GLB) → GLB→PLY 转换
│
▼
[03] ACE-Step → 音乐 (WAV)
│
▼
[04] Demucs → 分离音轨 (人声/鼓/贝斯/吉他/钢琴/其他)
│
▼
音乐可视化页面 (Three.js 3D 场景 + 音轨播放)
1 commits
Python
38.6%
HTML
31.1%
Vue
25.1%
Shell
2.7%
CSS
2.3%