跳转至

项目结构

每个文件夹都有单一职责。根目录下的每个文件都应有其存在价值。

目录结构

VoiceStudio/
│
├── README.md ⟵ user-facing overview (translations: docs/readme/README_*.md)
├── CHANGELOG.md                 ⟵ release history; Electron releases use the tagged section
├── CLAUDE.md / AGENTS.md        ⟵ matching copies of the agent operating rules
├── LICENSE / LICENSE-NOTICE.md / SPONSORS.md   ⟵ legal terms, required notices, supporters
│
├── pyproject.toml               ⟵ Python metadata plus the pytest and lint settings
├── uv.lock                      ⟵ Python lockfile
├── package.json                 ⟵ monorepo manifest (Bun workspaces) and THE app
│                                   version (pyproject.toml + backend/core/version.py mirror it)
├── bun.lock                     ⟵ JS lockfile — repo-root, covers the electron/ workspace
├── flake.nix, flake.lock        ⟵ community Nix dev shells + NixOS FHS env (docs/install/nix.md)
│
├── .coderabbit.yaml / greptile.json   ⟵ bot-review setup; CLAUDE.md supplies both rule sets
├── skills-lock.json             ⟵ records the origin and digest of each .agents/skills/ copy
├── .gitleaks.toml               ⟵ repository secret-detection policy
├── .gitmodules                  ⟵ registers omnivoice-gallery
├── .python-version              ⟵ interpreter selection for Python tooling
├── .dockerignore                ⟵ Docker build context filter
├── alembic.ini                  ⟵ DB migration config (stays at root by alembic convention)
│
├── .gitignore                   ⟵ excludes a checkout-local .env; Settings persists user choices in
│                                   ~/.config/omnivoice/env through backend/core/user_env.py
│
├── backend/                     ⟵ FastAPI server
│   ├── main.py                  sole process entry; its annotated startup sequence must retain its order
│   ├── api/routers/             44 routers, auto-included; HTTP/WS adaptation stays thin here
│   │   └── setup/               setup-wizard endpoints and model acquisition
│   ├── core/                    shared infrastructure: configuration, persistence, job/event plumbing,
│   │                            auth and CSRF, safe paths, analytics consent, version and diagnostics
│   ├── services/                116 modules of business logic spanning speech, dubbing, DSP, GPU dispatch,
│   │                            engine selection and loaded-model ownership
│   ├── engines/                 per-engine adapters: audiocpp, confucius4, cosyvoice_gguf,
│   │                            cosyvoice_subprocess, dots_tts, indextts, moss_tts_nano_subprocess,
│   │                            moss_tts_v15, omnivoice_gguf, omnivoice_subprocess, pockettts,
│   │                            supertonic3, voxcpm2_subprocess, whisper_cpp, _asr_sidecar, _echo
│   ├── schemas/                 Pydantic types at the request/response boundary
│   ├── config/models.yaml       catalogue of selectable models
│   ├── migrations/versions/     mandatory Alembic home for database evolution
│   ├── plugins/                 extension landing area; contract lives in services/plugin_sdk.py
│   ├── mcp_shim/                MCP launch surface documented by docs/mcp.md
│   ├── speech_client/           client entry for the speech sidecar
│   └── tests/                   separately collected backend test session (details below)
│
├── electron/                    ⟵ the only desktop app and web UI (Electron + React 19)
│   ├── src/main/                lifecycle, backend supervisor, runtime setup, updater, native IPC
│   ├── src/preload/             typed contextBridge → window.voicestudio
│   ├── src/renderer/            desktop React app: routes/, features/, components/, i18n/locales/
│   ├── src/shared/              modules shared by the desktop and browser builds (api/, i18n/,
│   │                            store/, ui/, utils/) — not a runnable app
│   ├── tests/                   packaged-app, installer and workflow smoke tests
│   ├── build/                   packaging inputs: icons, entitlements, Info.plist
│   ├── scripts/                 dev launcher, AppImage update-info embedding
│   ├── vite.web.config.ts       browser build (`bun run build:web`) → frontend/dist/
│   └── electron-builder.config.mjs   installers: DMG/zip, NSIS, AppImage + deb
│
├── native/desktop-bridge/       ⟵ Rust helper used by Electron
│
├── frontend/dist/               ⟵ build output of `bun run build:web` (gitignored): the web UI
│                                   the backend serves in Docker and, from Electron packages, to LAN devices
│
├── omnivoice/                   ⟵ the underlying TTS model package
│   ├── models/
│   ├── cli/                     CLI entry points (omnivoice-infer, etc.)
│   ├── data/                    data utilities used by the model
│   ├── eval/                    evaluation scripts
│   ├── scripts/                 one-off utilities that ship with the package
│   ├── training/
│   └── utils/
│
├── tests/                       ⟵ default pytest collection selected by pyproject.toml `testpaths`
│   ├── conftest.py              redirects OMNIVOICE_DATA_DIR to disposable state for the whole session
│   ├── backend/ / scripts/      path-shaped coverage for those source areas
│   ├── smoke/                   quick end-to-end gates; isolated CI job runs with HF_HUB_OFFLINE=1
│   ├── evals/                   evals.yml-driven output-quality checks
│   ├── probe/ / fixtures/       diagnostic probes and reusable inputs
│   └── frontend/                retained node:test suite for utilities and developer tooling
│
├── scripts/                     ⟵ development, packaging and release commands (sh, Python, mjs)
│   ├── install.sh / install.ps1 installers delivered from voicestudio.sh/install
│   ├── dev-backend.mjs          supervisor behind `bun run dev:api`
│   ├── setup.py                 platform finishing step for `bun run setup:api`, including ROCm opt-in
│   ├── electron-smoke-test.mjs  packaged-launch probe invoked by `bun run smoke-test`
│   ├── prepare_electron_release.py, check_electron_release_assets.py   artifact verification
│   ├── check-docs-drift.py      checks docs-drift.yml against authoritative docs/features.yaml
│   └── build-omnivoice-tts.sh   produces the sidecars stored under bin/
│
├── bin/                         ⟵ one precompiled omnivoice-tts sidecar for each supported platform
├── .agents/skills/              ⟵ real-file canonical skills whose revisions are locked in skills-lock.json
├── skills/                      ⟵ distributable voicestudio and voicestudio-maintainer skill packages
│
├── deploy/                      ⟵ container delivery plus the hosted installer worker
│   ├── Dockerfile               CUDA baseline; BASE_IMAGE and GPU_FLAVOR let CI build ROCm too
│   ├── docker-compose.yml       local one-command stack
│   ├── torch-constraints.txt    image-specific torch-family lock
│   ├── dockerhub-overview.md    release-synchronised Docker Hub description
│   └── install-worker/          Cloudflare worker serving voicestudio.sh/install; embeds both installers
│                                from scripts/ (see docs/install/script.md)
│
├── docs/                        ⟵ engineering references, product imagery and brand material
│   ├── STRUCTURE.md             this map
│   ├── ROADMAP.md               planned direction
│   ├── RELEASING.md             complete multi-channel shipping checklist
│   ├── features.yaml            source inventory consumed by docs-drift.yml
│   ├── adr/                     durable architectural decisions
│   ├── agents/                  tracker, triage-role and domain instructions for agents
│   ├── engines/ dubbing/ install/ setup/ migration/ features/ playbooks/ specs/
│   ├── media/ screenshots/      supporting media and captured UI
│   ├── preview.png / logo.*     repository preview and logo assets
│   └── languages.md training.md data_preparation.md evaluation.md voice-design.md
│
├── examples/                    ⟵ executable samples and inputs, including agentic/ and config/
├── notebooks/                   ⟵ contains OmniVoice_Studio_Colab.ipynb
├── omnivoice-gallery/           ⟵ submodule that publishes the voice gallery
│
├── omnivoice_data/              ⟵ Docker bind-mount target (gitignored)
│                                   DB + HF cache live here when running via compose
│
├── .github/workflows/           ⟵ ci, electron-build, electron-release, docker, security,
│                                   docs-drift, evals, install-smoke, build-omnivoice-tts,
│                                   cla, commit-identity, cosyvoice-dependencies
└── .git/

根目录规则

  1. 根目录中不应存在任何运行时产物。 输出文件、临时文件、本地 DB、崩溃日志——全部放入 ~/Library/Application Support/OmniVoice/(或操作系统等效路径),绝不放入仓库。唯一的例外是 omnivoice_data/,它作为 Docker 的绑定挂载锚点存在。

  2. 根目录不放置临时脚本或测试。 将一次性调试工具放入 scripts/;测试归属于下面三个归属地之一。

  3. 每个子目录只承担一种职责。 如果你无法用一句话说清某个目录里放什么,那这个目录就是错的。

  4. 各个包独立声明依赖。 backend/、electron/ 和 omnivoice/ 各有自己的 pyproject.toml 或 package.json,可以单独测试。Bun 工作区共享一个根级 bun.lock;Docker 使用冻结安装,宁可失败也不修改它。

测试的存放位置

ci.yml 中的单个 test 任务会调用三个独立的运行器。有意让它们的测试收集边界保持分离。

位置 运行器 为何独立
tests/ pytest tests/(同时也是 testpaths 的默认值) 主要 Python 测试收集位置。其 fixture 将 OMNIVOICE_DATA_DIR 重定向到临时存储,避免接触开发者数据(#878)。
backend/tests/ pytest backend/tests/;CI 步骤:“Run pytest (backend/tests, isolated)” 在全新会话中验证后端的 bare-import 模式,并使用自己的临时数据根目录。禁止在收集期伪造 sys.modules,因为这种伪造会逃出自身文件并污染合并运行。
electron/src/**/*.test.{ts,tsx} 使用 Vitest/jsdom 的 bun run test;CI 通过 bun run check:electron 进入 UI 测试与实现代码放在一起。打包和工作流冒烟测试覆盖属于 electron/tests/;较旧的辅助工具/开发脚本 node:test 用例位于 tests/frontend/,并使用 bun run test:frontend 运行。

内容存放位置

内容类型 存放位置
面向用户的产品代码 backend/、electron/
TTS 模型(独立于 VoiceStudio) omnivoice/
新的 TTS/ASR 引擎适配器 backend/engines/<engine>/
所有可执行但不面向用户的内容 scripts/
预构建的平台 sidecar bin/
Python 测试 tests/(或需要隔离时放入 backend/tests/)
Electron / UI 单元测试 与模块同处,命名为 *.test.ts(x)
开发者和用户文档(Markdown) docs/
架构决策记录(ADR) docs/adr/
面向 Agent 的文档 docs/agents/
可运行的演示与示例数据 examples/
运行时数据(绝不提交) Mac 上的 ~/Library/Application Support/OmniVoice/

不再位于根目录的内容

以下内容在清理过程中被移除:

文件 原本存在的原因 去向
test_crash.py, test_server.py, test_whisper.py, test_mock.py, test_pyannote.py 4 月 14 日崩溃调查期间的一次性调试脚本。导入的符号在 router 重构后已不存在。 已删除(原本已被 gitignore,且引用了死代码)。
benchmark.py 另一个过时的调试脚本;导入了已不存在的 backend.main._get_db。 已删除。
output.wav, test.wav 运行时产物。 已删除 / 已移出。
crash_log.txt 运行时日志。现在写入 $DATA_DIR/crash_log.txt。 已删除。
omnivoice.zip (148 MB) 项目自身的离线参考归档。 移出仓库,放到 ../omnivoice.zip.bak。
data/ 只包含 .DS_Store。 已删除。
legacy_gradio/ React 之前的 Gradio UI。保留作历史参考。 先归档到 research/legacy_gradio/,后在 2026-07-12 清理中移除(见 git 历史)。
散落的 .DS_Store 文件 macOS Finder 残留。 已从每个未被忽略的目录中删除。

在 2026-07-12 清理中移除(全部保留在 git 历史中):

目录 原本存在的原因 去向
.planning/ (74 files) GSD 时代的规划存档:阶段、快速计划、问题集群。GSD 工作流已于 2026-07-08 退役。 已删除;四份关键决策文档移至 docs/adr/。
design/ React 之前目标 UX 的 ASCII 线框图,已被正式发布的应用取代。 已删除。
research/ 归档的旧 Gradio UI + 2026 年 4 月竞争对手笔记。 已删除。
.agents/ 原先属于一个已退役的第三方 agent 工具。 已移除,后为 skills-lock.json 锁定的规范技能副本重建。

扩展路径(提议,尚未执行)

当前的扁平布局对当前规模来说运作良好。如果项目扩展到包含更多应用(移动端配套应用、插件 SDK、多个后端),则迁移到 Turborepo 风格的 monorepo:

VoiceStudio/
├── apps/
│   ├── api/                 ← was backend/
│   └── desktop/             ← was electron/ (desktop + browser UI)
├── packages/
│   ├── omnivoice-model/     ← was omnivoice/
│   └── tts-adapters/        ← new; the pluggable TTS interface from ROADMAP phase 3
├── config/
│   └── docker/
├── tests/
└── docs/

没有专门的 PR,不要执行此迁移。 它会破坏:

  • pyproject.toml 的 [tool.hatch.build.targets.{sdist,wheel}] 路径
  • package.json 的 workspaces 与 scripts
  • Dockerfile、docker-compose.yml 的路径
  • Electron Builder、native-helper、updater 和 packaged-smoke 路径
  • 所有 from backend.main import … 导入(测试、脚本)
  • 根级 package.json 作为版本事实来源及其镜像

在添加第二个 apps/* 或第二个 packages/* 时再迁移。不要提前。

约定

  • 文件名: Python 使用 snake_case,JS/TS 组件使用 kebab-case 或 PascalCase,Markdown 使用小写。
  • 一次性脚本 放入 scripts/,命名要具有描述性,而不是放在根目录下命名为 test_*.py。
  • 新增顶级目录 需要一个更新本文件的 PR。
  • 测试位置: 镜像测试套件跟随源码路径(tests/backend/ 镜像 api/、core/、engines/ 和 services/;例如,backend/services/ffmpeg_utils.py 对应 tests/backend/services/test_ffmpeg_utils.py)。否则,后端全局测试平铺在 tests/backend/,横切测试平铺在 tests/,React 组件测试与其组件放在一起。

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 om/VoiceStudio