223 lines
12 KiB
Markdown
223 lines
12 KiB
Markdown
# CARLA BRIDGE — NATIVE GUI VSTi (Windows) + DUAL-MODE RUNTIME (Desktop / Docker Headless)
|
|
|
|
> Tài liệu kỹ thuật & vận hành: tích hợp Carla làm host native GUI cho VSTi trên
|
|
> Windows, tự phát hiện môi trường (desktop / headless), thư viện preset
|
|
> (.vstpreset) làm cầu nối Carla → pedalboard, và Plugin Manager quản lý
|
|
> soundfont + instrument.
|
|
>
|
|
> Phạm vi code: `app/core/runtime.py`, `app/api/v1/system.py`,
|
|
> `app/api/v1/presets.py`, `app/api/v1/plugins.py`, `app/core/vst_engine.py`,
|
|
> `app/core/render_engine.py`, `app/static/js/services/runtime.js`, `app.jsx`.
|
|
|
|
---
|
|
|
|
## 1. Bối cảnh & quyết định kiến trúc
|
|
|
|
| Vấn đề | Quyết định |
|
|
|---|---|
|
|
| `pedalboard` **cố tình headless** — không mở được native GUI VSTi | Không thay thế pedalboard; dùng **Carla làm host GUI ngoài** (preview + chỉnh preset), pedalboard giữ nguyên làm **render engine** (offline, cùng code path cho preview & export) |
|
|
| Browser không chạy được binary `.vst3` (Windows/Linux) | Preview realtime thật chỉ có trong **cửa sổ Carla**; trong web UI dùng **quick-render preview** (pedalboard render clip ngắn → wav — **âm thật = âm export**) |
|
|
| App chạy 2 môi trường: **Windows desktop** (server+client 1 máy) và **Docker headless** (server + browser UI) | **Runtime profile tự phát hiện** → bật/tắt tính năng theo môi trường (nút Carla Bridge chỉ hiện trên desktop có Carla) |
|
|
| Carla Windows là **bộ zip portable** — không installer, không PATH | **User tự định vị** thư mục chứa `carla.exe` (Plugin Manager → Định vị Carla...) + tìm kiếm dự phòng (registry, Program Files, quét nông Downloads/Desktop) |
|
|
|
|
```
|
|
┌────────────────────────── Windows Desktop (1 máy) ──────────────────────────┐
|
|
│ Browser/Tauri UI ──► FastAPI (localhost:8000) ──► pedalboard (render VST3) │
|
|
│ │ │ ▲ │
|
|
│ ▼ ▼ │ load_preset │
|
|
│ Nút "Carla Bridge" ──► spawn carla.exe (native GUI) │ │
|
|
│ │ chọn VSTi, chỉnh âm, Save .vstpreset │
|
|
│ └──────────────► Upload preset ──► storage/presets ─┘ │
|
|
└─────────────────────────────────────────────────────────────────────────────┘
|
|
┌────────────────────────── Docker Headless (server) ─────────────────────────┐
|
|
│ Browser UI ──► FastAPI (container :8000) ──► pedalboard (VSTi Linux) │
|
|
│ Soundfont + VSTi mở được: mount volumes (docker-compose.prod.yml) │
|
|
│ Preset .vstpreset: user chỉnh ở máy desktop → upload qua web UI │
|
|
└─────────────────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## 2. Runtime tự phát hiện môi trường (`app/core/runtime.py`)
|
|
|
|
### 2.1 Nguyên tắc
|
|
|
|
- **Heuristic + override**: `SF_RUNTIME=auto|desktop|headless` **thắng tuyệt đối**
|
|
(WSL / docker-in-docker / remote desktop có thể làm heuristic sai).
|
|
- `SF_DOCKER=1` hoặc tồn tại `/.dockerenv` → nhận diện container.
|
|
- Linux: không có `DISPLAY` hoặc trong docker → `headless`; ngược lại `desktop`.
|
|
- Windows/macOS → luôn `desktop`.
|
|
|
|
### 2.2 Capabilities API (frontend gọi 1 lần lúc boot)
|
|
|
|
```
|
|
GET /api/v1/system/capabilities (public — cần trước khi đăng nhập)
|
|
```
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"runtime": "desktop", // "desktop" | "headless"
|
|
"platform": "windows", // "windows" | "linux" | "darwin"
|
|
"docker": false,
|
|
"features": {
|
|
"carla_local": true, // có Carla trên máy → hiện nút "Carla Bridge"
|
|
"carla_path": "D:/Tools/Carla/carla.exe",
|
|
"preset_upload": true, // luôn true (upload .vstpreset qua web UI)
|
|
"vst_render": true, // pedalboard khả dụng
|
|
"tauri_bridge": false,
|
|
"preview_mode": "quick_render" // "quick_render" | "wasm"
|
|
},
|
|
"default_dirs": { "vst": [...], "soundfont": [...], "preset": "..." }
|
|
}
|
|
```
|
|
|
|
### 2.3 Bảng hành vi theo môi trường
|
|
|
|
| Tính năng | Windows desktop | Docker headless |
|
|
|---|---|---|
|
|
| Render VSTi | pedalboard `VST3Plugin` + `load_preset` | giống hệt (VSTi **bản Linux**) |
|
|
| Scan VST/SF | thư mục chuẩn Windows + `plugin_dirs.json` | mount volumes + `plugin_dirs.json` |
|
|
| Preview VSTi | quick-render (âm thật); realtime trong Carla | quick-render |
|
|
| Nút "Carla Bridge" (nút Synth) | **Hiện** → spawn `carla.exe` | **Ẩn** (không có GUI local) |
|
|
| Preset | picker local / upload → thư viện | upload → thư viện |
|
|
| SoundFont preview | FluidSynth WASM (browser) | giống hệt |
|
|
|
|
---
|
|
|
|
## 3. Cài đặt Carla trên Windows (bản portable zip)
|
|
|
|
Carla phát hành dạng **zip** (`Carla-2.5.x-win64.zip`) — **không có installer,
|
|
không ghi PATH**. Không bundle Carla vào installer của app (license GPL-2.0+,
|
|
xem §8).
|
|
|
|
1. Tải: <https://github.com/falkTX/Carla/releases> (bản `win64`).
|
|
2. Giải nén ra bất kỳ đâu (VD `D:\Tools\Carla\`, chứa `carla.exe`).
|
|
3. Mở app → **Plugin Manager** → section **"Carla Bridge (VSTi native GUI)"** →
|
|
nút **"Định vị Carla..."** → chọn thư mục chứa `carla.exe` (hoặc chính file
|
|
`carla.exe`).
|
|
4. App lưu vào `storage/carla_path.json` → cache detect bị xóa → nút
|
|
**"Carla Bridge"** hiện trong dropdown nút Synth.
|
|
|
|
### 3.1 Thứ tự phát hiện `carla_local`
|
|
|
|
| Ưu tiên | Nguồn |
|
|
|---|---|
|
|
| 1 | **Config user** (`storage/carla_path.json`) — kênh chính cho bản portable |
|
|
| 2 | PATH (`shutil.which`) |
|
|
| 3 | Registry (`HKLM/HKCU\SOFTWARE\Carla\InstallPath`) — nếu cài qua installer |
|
|
| 4 | Thư mục chuẩn (`Program Files\Carla`, `%LOCALAPPDATA%\Programs\Carla`) |
|
|
| 5 | **Quét nông** Downloads/Desktop/Documents (độ sâu ≤ 3, bỏ qua `node_modules`, `AppData`, `Windows`...) — không bao giờ quét toàn ổ đĩa |
|
|
|
|
```
|
|
POST /api/v1/system/carla-path (auth) — lưu vị trí Carla
|
|
body: { "carla_path": "D:/Tools/Carla" } (thư mục HOẶC file exe)
|
|
→ trả { success, carla_path, ...capabilities }
|
|
```
|
|
|
|
---
|
|
|
|
## 4. Luồng sử dụng end-to-end (Windows)
|
|
|
|
1. **Nút Synth** (track strip / btnSynth) → chọn **"🎛 Carla Bridge (mở Carla.exe)"**
|
|
→ app spawn `carla.exe` (ưu tiên `carla-single <plugin>` nếu chọn kèm plugin).
|
|
2. Trong Carla: **Add Plugin** → chọn VSTi (Kontakt, Nexus, Vital...) → native GUI
|
|
hiện ra → chỉnh âm, chọn bank/preset của plugin.
|
|
3. **Save preset** bằng nút của CHÍNH plugin (không dùng project save của Carla)
|
|
→ file `.vstpreset`.
|
|
4. Trong app: dropdown Synth → **"⬆ Upload preset (từ Carla...)"** → chọn file
|
|
`.vstpreset` → nằm trong **thư viện preset** → chọn preset trong danh sách
|
|
**"VST Presets"** → gán vào track (`synth_engine.preset_id`).
|
|
5. **Render**: `render_engine.py` nạp plugin qua `load_vst()` rồi
|
|
`apply_preset_to_plugin()` → **âm render = âm đã chỉnh trong Carla**
|
|
(điều kiện: cùng sample rate — xem §7).
|
|
|
|
Lưu ý: danh sách VSTi trong dropdown vẫn cần thiết — dùng để **map tên →
|
|
đường dẫn khi pedalboard nạp plugin lúc render** (không phải để mở GUI).
|
|
|
|
---
|
|
|
|
## 5. Thư viện preset — cầu nối Carla ↔ pedalboard
|
|
|
|
- Thư mục: `{STORAGE_DIR}/presets` (Windows: `%APPDATA%\SonicForgeDAW\storage\presets`;
|
|
Docker: nằm trong volume `sf_db` → `/app/app/storage/presets`).
|
|
- Định dạng hỗ trợ: `.vstpreset` (VST3 — chuẩn), `.fxp`/`.fxb` (VST2, chỉ
|
|
preview trong Carla), `.dspreset` (DecentSampler/Pianobook).
|
|
- `synth_engine` của track có thể chứa 1 trong 3 dạng (ưu tiên giảm dần):
|
|
|
|
```json
|
|
{ "type": "vst3", "plugin_id": "Kontakt 7",
|
|
"preset_data": "<base64 bytes .vstpreset nhúng — project tự chứa state, portable>",
|
|
"preset_id": "a1b2c3....vstpreset", // thư viện storage/presets
|
|
"preset_path": "D:/presets/Piano.vstpreset" }
|
|
```
|
|
|
|
### API
|
|
|
|
```
|
|
GET /api/v1/presets (public) — danh sách
|
|
POST /api/v1/presets/upload (auth) — multipart file + plugin_hint
|
|
GET /api/v1/presets/{id}/download
|
|
DELETE /api/v1/presets/{id} (auth)
|
|
```
|
|
|
|
### Quick-render preview (âm thật = âm export)
|
|
|
|
```
|
|
POST /api/v1/plugins/preview
|
|
body: { instrument_id, notes:[{pitch,start_beat,duration_beats,velocity}],
|
|
bpm, sample_rate, preset_id?, preset_path?, preset_data? }
|
|
→ { success, url: "/static/audio/processed/preview_xxx.wav", duration_sec }
|
|
```
|
|
|
|
Cùng code path với export (pedalboard + `load_preset`) → **preview nghe đúng
|
|
plugin/preset** (khác "Preview Synth WASM" cũ — âm giả).
|
|
|
|
---
|
|
|
|
## 6. Plugin Manager — SoundFont: Add Directory → Scan → Instrument → Synth
|
|
|
|
1. **Add Directory** (folder picker native / in-app browser) → thư mục vào
|
|
danh sách (lưu `plugin_dirs.json`).
|
|
2. **Scan** → quét soundfont trong các thư mục (catalog qua
|
|
`SoundFontAutoScanner`) + liệt kê VST.
|
|
3. Bấm vào **một soundfont** (▸) → expand danh sách **instrument bên trong**
|
|
(Bank/Program/Tên) qua `GET /api/v1/plugins/soundfont-instruments/{sf_id}`.
|
|
4. Nút **"Chèn vào Synth"** → gán instrument (bank/program) vào **track đang
|
|
chọn** (`setTrackInstrumentWithProgram`) và đóng Plugin Manager.
|
|
|
|
> SF3: instrument đọc sau khi chuyển đổi SF3→SF2 (endpoint download tự chuyển
|
|
> đổi khi cần). Nếu thiếu libfluidsynth, danh sách trả `[]` (graceful).
|
|
|
|
---
|
|
|
|
## 7. Lưu ý kỹ thuật & hạn chế (đã xác minh)
|
|
|
|
1. **Sample rate**: Carla chạy theo audio device (thường 48 kHz), pedalboard
|
|
render mặc định 44.1 kHz → plugin phụ thuộc SR (delay/chorus/oversampling)
|
|
nghe khác. **Render đúng SR của thiết bị Carla** để preview = export.
|
|
2. **VST2**: pedalboard 0.10+ **đã gỡ hỗ trợ VST2** (chỉ còn VST3) → chỉ preset
|
|
VST3 (`.vstpreset`) round-trip được. Plugin VST2 cũ: preview được trong
|
|
Carla nhưng **không render** được qua pedalboard.
|
|
3. **VSTi trên Docker**: chỉ chạy được plugin có bản **Linux** (`.vst3`/`.so`);
|
|
plugin Windows-only (`.dll`) không chạy trên server Linux (không khuyến nghị
|
|
Wine bridge trong container).
|
|
4. **License Carla GPL-2.0+**: app **không bundle/nhúng** Carla — chỉ spawn
|
|
tiến trình ngoài + trao đổi file preset (không link code) → không dính
|
|
copyleft. User tự tải zip.
|
|
5. **Preview WASM ≠ âm thật**: Preview Synth trong browser không phải plugin
|
|
thật — dùng quick-render (`/plugins/preview`) nếu cần nghe đúng âm.
|
|
|
|
---
|
|
|
|
## 8. Checklist QA
|
|
|
|
- [ ] Windows: cài Carla zip → Định vị Carla → nút "Carla Bridge" hiện ở nút Synth
|
|
- [ ] Bấm Carla Bridge → `carla.exe` chạy, mở được VSTi + native GUI
|
|
- [ ] Save `.vstpreset` từ GUI plugin → Upload trong app → gán vào track → render ra âm đúng preset
|
|
- [ ] Render cùng SR với Carla → preview (Carla) nghe = âm export
|
|
- [ ] Plugin Manager: Add Directory → Scan → expand soundfont → "Chèn vào Synth" gán đúng bank/program vào track đang chọn
|
|
- [ ] Docker (`SF_DOCKER=1`): capabilities `runtime=headless`, không hiện Carla Bridge, preset upload hoạt động, render VSTi Linux + soundfont từ mount OK
|
|
- [ ] `SF_RUNTIME=desktop` trên Linux có DISPLAY → chạy như desktop
|
|
- [ ] pytest: `86 passed, 7 skipped`
|