OmniVoice-Studio / docs /STRUCTURE.md
LΓͺ Phi Nam
Deploy to HF Space
94004a2
|
Raw
History Blame Contribute Delete
8.71 kB
# Project Structure
Every folder has a single job. Every file at the root earns its place.
## Layout
```
OmniVoice/
β”‚
β”œβ”€β”€ README.md ⟡ user-facing overview
β”œβ”€β”€ CHANGELOG.md ⟡ release history
β”œβ”€β”€ LICENSE
β”‚
β”œβ”€β”€ pyproject.toml ⟡ Python project manifest
β”œβ”€β”€ uv.lock ⟡ Python lockfile
β”œβ”€β”€ package.json ⟡ monorepo manifest (Bun workspaces + Turborepo)
β”œβ”€β”€ bun.lock ⟡ JS lockfile
β”œβ”€β”€ turbo.json ⟡ turborepo pipeline
β”‚
β”œβ”€β”€ .dockerignore ⟡ Docker build context filter
β”œβ”€β”€ backend.spec ⟡ pyinstaller spec (stays at root by pyinstaller convention)
β”œβ”€β”€ alembic.ini ⟡ DB migration config (stays at root by alembic convention)
β”‚
β”œβ”€β”€ .env ⟡ user config; gitignored, .env.example is the template
β”œβ”€β”€ .gitignore
β”‚
β”œβ”€β”€ backend/ ⟡ FastAPI server
β”‚ β”œβ”€β”€ main.py
β”‚ β”œβ”€β”€ api/routers/ HTTP endpoints (thin)
β”‚ β”œβ”€β”€ core/ config, db, task queue, metrics
β”‚ β”œβ”€β”€ services/ business logic
β”‚ └── schemas/ pydantic request/response shapes
β”‚
β”œβ”€β”€ frontend/ ⟡ React 19 + Vite + Tauri desktop
β”‚ β”œβ”€β”€ src/
β”‚ β”‚ β”œβ”€β”€ pages/ one file per top-level view
β”‚ β”‚ β”œβ”€β”€ components/ reusable UI
β”‚ β”‚ β”œβ”€β”€ api/ typed API clients
β”‚ β”‚ β”œβ”€β”€ store/ Zustand slices
β”‚ β”‚ β”œβ”€β”€ hooks/ custom React hooks
β”‚ β”‚ └── utils/
β”‚ β”œβ”€β”€ src-tauri/ Rust desktop shell
β”‚ └── public/
β”‚
β”œβ”€β”€ 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/ ⟡ all tests live here, no exceptions
β”‚ β”œβ”€β”€ conftest.py
β”‚ β”œβ”€β”€ test_api.py
β”‚ β”œβ”€β”€ test_dub_*.py
β”‚ β”œβ”€β”€ test_job_queue.py
β”‚ β”œβ”€β”€ test_segmentation.py
β”‚ └── frontend/ Node-based frontend tests
β”‚
β”œβ”€β”€ scripts/ ⟡ dev / build / release shell + python scripts
β”‚ β”œβ”€β”€ install.sh universal installer
β”‚ β”œβ”€β”€ run.sh universal launcher
β”‚ β”œβ”€β”€ smoke-test.sh end-to-end validation
β”‚ └── desktop-prod.sh production desktop build
β”‚
β”œβ”€β”€ deploy/ ⟡ Docker deployment configs
β”‚ β”œβ”€β”€ Dockerfile single-stage CUDA image
β”‚ └── docker-compose.yml one-click local deployment
β”‚
β”œβ”€β”€ docs/ ⟡ developer docs, screenshots, branding
β”‚ β”œβ”€β”€ ROADMAP.md where this project is going
β”‚ β”œβ”€β”€ STRUCTURE.md you are here
β”‚ β”œβ”€β”€ mcp.json MCP config template
β”‚ β”œβ”€β”€ preview.png README hero image
β”‚ β”œβ”€β”€ logo.png, logo.svg branding assets
β”‚ β”œβ”€β”€ screenshot-*.png feature screenshots
β”‚ β”œβ”€β”€ languages.md
β”‚ β”œβ”€β”€ training.md
β”‚ β”œβ”€β”€ data_preparation.md
β”‚ β”œβ”€β”€ evaluation.md
β”‚ └── voice-design.md
β”‚
β”œβ”€β”€ design/ ⟡ ASCII mockups of the target UX
β”‚ β”œβ”€β”€ README.md
β”‚ └── 00–08-*.md per-feature specs
β”‚
β”œβ”€β”€ research/ ⟡ reference material, competitor analysis, archived code
β”‚ β”œβ”€β”€ LEARNINGS.md competitive analysis, what to absorb
β”‚ β”œβ”€β”€ TheWhisper/ vendored reference (read-only)
β”‚ β”œβ”€β”€ voice-pro/ vendored reference
β”‚ └── legacy_gradio/ archived Gradio UI (pre-React rewrite)
β”‚
β”œβ”€β”€ examples/ ⟡ runnable demos + sample inputs
β”‚
β”œβ”€β”€ omnivoice_data/ ⟡ Docker bind-mount target (gitignored)
β”‚ DB + HF cache live here when running via compose
β”‚
└── .git/
```
## Rules of the root
1. **Nothing at the root is a runtime artifact.** Outputs, temp files, local DBs, crash logs β€” all go to `~/Library/Application Support/OmniVoice/` (or the OS equivalent), *never* into the repo. The one exception is `omnivoice_data/`, which exists as a bind-mount anchor for Docker.
2. **No ad-hoc scripts at the root.** One-off debug scripts live in `scripts/`. Tests live in `tests/`. Benchmarks live in `scripts/benchmarks/` (when we create them).
3. **Each subdirectory owns one concern.** If you can't describe what goes in a directory in one sentence, it's wrong.
4. **Every package has a manifest.** `backend/`, `frontend/`, `omnivoice/` each have their own deps declared via `pyproject.toml` / `package.json` β€” they are independently testable.
## What lives where
| Kind of thing | Goes in |
|---|---|
| User-facing product code | `backend/`, `frontend/` |
| The TTS model (independent of the studio) | `omnivoice/` |
| Everything executable but not user-facing | `scripts/` |
| Tests | `tests/` |
| Developer + user docs (Markdown) | `docs/` |
| Target-state mockups | `design/` |
| Competitor clones, legacy code, ref material | `research/` |
| Runnable demos and sample data | `examples/` |
| Runtime data (never committed) | `~/Library/Application Support/OmniVoice/` on Mac |
## What *doesn't* live at the root anymore
Removed in the cleanup pass:
| File | Why it was there | Where it went |
|---|---|---|
| `test_crash.py`, `test_server.py`, `test_whisper.py`, `test_mock.py`, `test_pyannote.py` | One-off debug scripts from an April 14 crash investigation. Imported symbols that no longer exist after the router refactor. | Deleted (already gitignored, referenced dead code). |
| `benchmark.py` | Another stale debug script; imported `backend.main._get_db` which no longer exists. | Deleted. |
| `output.wav`, `test.wav` | Runtime artifacts. | Deleted / moved out. |
| `crash_log.txt` | Runtime log. Now written to `$DATA_DIR/crash_log.txt`. | Deleted. |
| `omnivoice.zip` (148 MB) | Offline reference archive of the project itself. | Moved out of the repo to `../omnivoice.zip.bak`. |
| `data/` | Only contained `.DS_Store`. | Deleted. |
| `legacy_gradio/` | The pre-React Gradio UI. Kept for historical reference. | Archived to `research/legacy_gradio/`. |
| Scattered `.DS_Store` files | macOS Finder droppings. | Deleted from every non-ignored directory. |
## Scaling path (proposed, not yet executed)
The current flat layout works fine for the current size. If the project grows to include additional apps (a mobile companion, a plugin SDK, multiple backends), migrate to a Turborepo-style monorepo:
```
OmniVoice/
β”œβ”€β”€ apps/
β”‚ β”œβ”€β”€ api/ ← was backend/
β”‚ β”œβ”€β”€ web/ ← was frontend/
β”‚ └── desktop/ ← could extract src-tauri/ here later
β”œβ”€β”€ packages/
β”‚ β”œβ”€β”€ omnivoice-model/ ← was omnivoice/
β”‚ └── tts-adapters/ ← new; the pluggable TTS interface from ROADMAP phase 3
β”œβ”€β”€ config/
β”‚ β”œβ”€β”€ docker/
β”‚ └── pyinstaller/
β”œβ”€β”€ tests/
β”œβ”€β”€ docs/
β”œβ”€β”€ design/
└── research/
```
**Do not execute this migration without a dedicated PR.** It breaks:
- `pyproject.toml` `[tool.hatch.build.targets.{sdist,wheel}]` paths
- `package.json` workspaces and scripts
- `turbo.json`, `Dockerfile`, `docker-compose.yml` paths
- `backend.spec` (`['backend/main.py']`, `pathex=['.']`)
- `frontend/src-tauri/tauri.*.conf.json` sidecar paths
- every import that reads `from backend.main import …` (tests, scripts)
Migrate when adding the second `apps/*` or the second `packages/*`. Not before.
## Conventions
- **Filenames:** snake_case for Python, kebab-case or PascalCase for JS/TS components, lowercase for Markdown.
- **Tests mirror source paths.** `backend/services/dub_pipeline.py` β†’ `tests/services/test_dub_pipeline.py`.
- **One-off scripts** go into `scripts/` with a descriptive name, not `test_*.py` at the root.
- **New top-level directories** require a PR that updates *this file*.