First v0.3.x release on the Phase 0 cross-platform CI baseline. ## Cross-platform bug fixes (375ea4e) User-reported bugs from a Pinokio/Windows session: - Docker `compose --profile gpu up` no longer port-conflicts on 3900 — restored `profiles: ["cpu"]` that #49 wrongly reverted on CodeRabbit's advice. - Argos / pip install from the UI now works inside Docker — added `_in_virtualenv()` runtime check; `run_pip` injects `--system` automatically when on system Python. - Speaker diarization warning toast — when pyannote silently falls back to the silence-gap heuristic (missing HF_TOKEN, license not accepted, network blocked), `_diarize()` now returns `(segments, warning)`; `useDubWorkflow` renders an 8-second toast. ## Dub editor UX (d5df454) Six fixes per annotated screenshots: - Editable segment start times (`m:ss.s` or raw seconds; Esc reverts, Enter commits; rejects overlap with end). - Click a transcript row → seek the waveform/video (`WaveformTimeline` now forwardRef's `seekTo(time)`). - Speaker is datalist-backed (pulls from detected speaker clones; free text still allowed). - Scissors menu splits at cursor — uses live caret, then last caret, then sentence-boundary fallback. - Mouse-wheel scrolls the waveform; Cmd/Ctrl left alone for browser pinch-zoom. - Menu popover collision: added `avoidCollisions` + `collisionPadding=8` to Radix Content; removed `position: fixed` from `.ui-menu`. ## VRAM-aware GPU pool (73dbe18) `_gpu_pool` was hardcoded `ThreadPoolExecutor(max_workers=1)` since introduction — every TTS forward serialized through one thread. - CUDA / ROCm: `workers = clamp(1, free_GB // 2.5, 4)`. 16 GB card with ~14 GB free → 4 workers → ~4× throughput on multi-segment dubs. - MPS / CPU / unknown: 1 worker. - `OMNIVOICE_GPU_WORKERS` env var override (clamped 1..16). - Module `__getattr__` preserves the public `_gpu_pool` symbol for existing callers. ## Stories tab — wire-up + UX (f6bbc7a) The 264-line `StoriesEditor` component existed but was mounted nowhere. Now wired into NavRail + lazy-loaded on `mode === 'stories'`. Added Paste & Split panel (sentence-boundary chunking) and per-track `[pause 0.5s]` insertion. ## Stories — pauses + inline voice (edd3a1d) `frontend/src/utils/storyTokens.js` — tokenizer for `[pause X.Ys]` and `[voice:X]…[voice:default]` markers. Voice switches are stateful (carry forward). 13 new vitest cases (vitest now 24/24). ## Verified - 214 backend tests pass (3 skipped, 10 xfailed, 3 xpassed) - 23 router-smoke tests pass - 24/24 vitest cases pass (13 new) - All 7 Phase 0 CI checks green (Tauri shell + Smoke on macOS/Windows/Linux + Tests) 🤖 Generated with [Claude Code](https://claude.com/claude-code)
84 lines
3.0 KiB
YAML
84 lines
3.0 KiB
YAML
# ──────────────────────────────────────────────────────────────
|
|
# OmniVoice Studio — Docker Compose
|
|
#
|
|
# Quick start:
|
|
# docker compose -f deploy/docker-compose.yml --profile cpu up # CPU mode
|
|
# docker compose -f deploy/docker-compose.yml --profile gpu up # GPU mode
|
|
#
|
|
# Both services bind to port 3900, so they MUST be opt-in via profiles —
|
|
# otherwise `compose up` would race them and one would fail to bind.
|
|
#
|
|
# First run downloads ~4 GB of models. Progress is shown in logs.
|
|
# Open http://localhost:3900 once the health check passes.
|
|
#
|
|
# SECURITY: The port is bound to 127.0.0.1 by default — only this
|
|
# machine can reach the API. To expose OmniVoice on your LAN (or
|
|
# through a reverse proxy / tunnel), change the port mapping to
|
|
# "0.0.0.0:3900:3900" or "3900:3900". OmniVoice itself ships no
|
|
# authentication — if you expose it, put it behind a reverse proxy
|
|
# with auth (Caddy basic_auth, nginx + htpasswd, Tailscale, etc.).
|
|
# ──────────────────────────────────────────────────────────────
|
|
|
|
services:
|
|
# ── CPU mode (default) ──────────────────────────────────────
|
|
omnivoice:
|
|
image: ghcr.io/debpalash/omnivoice-studio:latest
|
|
# To build from source instead of pulling, comment out `image:` and
|
|
# uncomment the two lines below:
|
|
build:
|
|
context: ..
|
|
dockerfile: deploy/Dockerfile
|
|
container_name: omnivoice-studio
|
|
profiles: ["cpu"]
|
|
ports:
|
|
- "127.0.0.1:3900:3900"
|
|
volumes:
|
|
- omnivoice-data:/app/omnivoice_data
|
|
environment:
|
|
- HF_HOME=/app/omnivoice_data/huggingface
|
|
- HF_TOKEN=${HF_TOKEN:-}
|
|
- OMNIVOICE_DATA_DIR=/app/omnivoice_data
|
|
- PYTHONUNBUFFERED=1
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-sf", "http://localhost:3900/health"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 120s
|
|
restart: unless-stopped
|
|
|
|
# ── GPU mode — activate with: docker compose --profile gpu up
|
|
omnivoice-gpu:
|
|
image: ghcr.io/debpalash/omnivoice-studio:latest
|
|
build:
|
|
context: ..
|
|
dockerfile: deploy/Dockerfile
|
|
container_name: omnivoice-studio-gpu
|
|
profiles: ["gpu"]
|
|
ports:
|
|
- "127.0.0.1:3900:3900"
|
|
volumes:
|
|
- omnivoice-data:/app/omnivoice_data
|
|
environment:
|
|
- HF_HOME=/app/omnivoice_data/huggingface
|
|
- HF_TOKEN=${HF_TOKEN:-}
|
|
- OMNIVOICE_DATA_DIR=/app/omnivoice_data
|
|
- PYTHONUNBUFFERED=1
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-sf", "http://localhost:3900/health"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 180s
|
|
deploy:
|
|
resources:
|
|
reservations:
|
|
devices:
|
|
- driver: nvidia
|
|
count: 1
|
|
capabilities: [gpu]
|
|
restart: unless-stopped
|
|
|
|
volumes:
|
|
omnivoice-data:
|