Two bugs from the v0.4.2 rename sweep:
- The lazy model import was rewritten to `from omnivoice.models.omnivoice import VoiceStudio`, a class the library does not export. ImportError is not ModuleNotFoundError, so the #564 source fallback never caught it and /generate 500'd on every default-engine request. The class keeps its library name — it is a checkpoint-referenced identifier, not branding.
- alembic resolved a bare relative script_location against the process cwd, and the desktop shell launches the backend from frontend/src-tauri, so a pending migration killed startup. script_location and prepend_sys_path are now anchored with %(here)s, with path_separator = os so Windows drive letters and paths with spaces survive. alembic floor raised to >=1.16.
Regression tests verified fail-before/pass-after for both.
Renames what users see. The app, the installers, the window title, the
docs and all 21 locales now say VoiceStudio, with "(previously
OmniVoice-Studio)" noted near the title of each doc surface so people
recognise it.
Deliberately NOT renamed, because renaming any of them silently breaks
an existing install — there is no legacy-path fallback anywhere in this
codebase:
- bundle identifier com.debpalash.omnivoice-studio (MSI UpgradeCode,
macOS TCC grants, managed venv, WebView localStorage, the
single-instance lock)
- data directories OmniVoice / .omnivoice and omnivoice.db
- the ~150 OMNIVOICE_* environment variables
- the X-OmniVoice-* HTTP headers (a wire protocol)
- the published Docker image paths
- the OmniVoice ENGINE, which is a model name and not this product
tests/test_identity_paths_survive_the_rename.py pins every one of those
so a future well-meaning sweep cannot orphan a user's library.
Linux .deb users install a new package name and should apt remove
omnivoice-studio; that note is in the changelog.
The repository was renamed. 724 references across 59 files now point at the new URL — README badges, docs, install guides, the updater's releases API call, CONTRIBUTING, the Colab link and the probe harness. GitHub redirects the old URLs, so nothing was broken in the meantime.
Deliberately NOT renamed, because each breaks something on a user's machine: the Tauri bundle identifier (the path to every existing user's data), /usr/lib/omnivoice-studio and the compose container names, and the published Docker image paths.
The image path needed a code change to STAY still: docker.yml derived it from github.repository, so the next build would have published to ghcr.io/debpalash/voicestudio while Docker Hub, a hardcoded literal, stayed put — everyone pulling the documented GHCR path would have kept receiving the last pre-rename image forever. It is now pinned, with a test that fails if it ever derives from the repo name again.
Also makes the probe's repo-name assertion shape-based: it hardcoded the old name and failed on every PR after the rename while the code it tests worked perfectly.
* fix(install): make the torch pin reach the Colab and Docker installs (#1357)
#1358 pinned the trio in `[tool.uv] constraint-dependencies`, which fixes
`uv sync` / `uv lock` / `uv run`. It does nothing for `uv pip install` --
that is the pip-compatible interface and ignores project-level uv
settings -- and `uv pip install --system --no-cache .` is exactly what
both the Colab notebook and deploy/Dockerfile run.
Measured on one Python 3.12 environment, same command, pin present:
without --constraint: torch 2.13.0 torchaudio 2.11.0 torchvision 0.28.0
with --constraint: torch 2.8.0 torchaudio 2.8.0 torchvision 0.23.0
So the reported install path was still resolving the three on their bare
lower bounds (`torch>=2.4`, `torchvision>=0.19`), free to move torch past
a torchvision built for an older ABI -- which is the reported failure,
`operator torchvision::nms does not exist`, against the preinstalled
torchvision in Colab's /usr/local/lib/python3.12/dist-packages/.
The pins move to deploy/torch-constraints.txt and are passed explicitly
at both call sites. No local version segment, so PEP 440 matches the
base images' +cu128 and +rocm6.4 builds instead of replacing them -- the
property the ROCm image depends on.
Also extends the Docker guard, which asserted on torch and torchaudio
only, omitting the one package that actually broke. It now imports
torchvision.ops and touches nms, so an ABI mismatch fails the build
rather than shipping.
Recurrence: docker.yml builds only on push to main, never on a PR, so
nothing would have caught a silent regression here before it shipped.
tests/test_torch_constraints_are_applied.py fails if the file drifts from
pyproject, if either call site drops --constraint, if the Dockerfile stops
COPYing the file, or if the guard stops covering torchvision.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* test(install): assert the constraint in the argv, not the cell text (#1357)
CodeRabbit on #1369, both findings valid.
The notebook check scanned the whole cell, so it passed when --constraint
was deleted from the run([...]) list but its explanatory comment
survived -- exactly the "the pin looks present but does not apply" shape
this PR exists to fix. It now parses the cell with ast and asserts
--constraint is in the argument list AND immediately followed by the
constraints file. Verified by deleting the flag from the argv while
keeping the comment: the test fails.
Also drops test_the_notebook_is_still_valid_json_and_has_its_cells --
it passed before the change and duplicated JSON parsing the constraint
test already does. A tautology.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: debpalash <nizam4103@gmail.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
CodeRabbit: the Colab sanity check resolved the tokenizer first and printed
versions only on success, so the one broken path it exists to catch reported
neither the installed versions nor CUDA status — the single most useful line
for diagnosing a Colab environment. Versions now print first.
CHANGELOG: contributor credit on all three entries, refs last.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`backend/api/routers/profiles.py` imports two pure-stdlib regex helpers from
`omnivoice.utils.voice_design`. That import pulled in `omnivoice/__init__`,
which eagerly imported `omnivoice.models.omnivoice` — torch, torchaudio,
transformers, flex_attention, the whole model definition — including a
top-level `from transformers import HiggsAudioV2TokenizerModel`.
transformers exposes that class through its lazy module and gates it on the
torchaudio backend, so the *attribute access* raises when torchaudio is
missing, ABI-mismatched, or installed without discoverable distribution
metadata — Colab's system Python, an interrupted `uv pip install`. It raised
during `backend/main.py`'s module import, before FastAPI existed: TTS,
dubbing, ASR and Settings all dead, the user left with a uvicorn traceback and
"Backend did not become healthy within 5 minutes".
Two changes, both structural rather than Colab-specific:
- `omnivoice/__init__` resolves its model exports lazily (PEP 562). Importing
`omnivoice.utils.*` no longer costs — or risks — the model stack.
`from omnivoice import OmniVoice` is unchanged; only the timing moves.
`backend.spec` already lists `omnivoice.models.omnivoice` as a hidden
import, so the frozen build is unaffected.
- `HiggsAudioV2TokenizerModel` resolves at its single use site in
`from_pretrained`, and a failure there raises an ImportError naming
torchaudio and the reinstall. Deferred into a request, `core.failure
.classify()` maps it to TRANSFORMERS_IMPORT and attaches a repair hint —
whose text now names torchaudio too, instead of only transformers + an ASR
workaround irrelevant to this path.
Colab notebook: cell 2's sanity check imports the model stack (and prints
torchaudio/transformers versions), so a broken env fails there with the real
error instead of as a health timeout two cells later.
Regression test: tests/test_omnivoice_lazy_model_import.py pins that the utils
import loads no heavy module, the lazy exports still resolve, and the deferred
failure is actionable and classified.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extends notebooks/OmniVoice_Studio_Colab.ipynb (setup cells 1-7 unchanged —
owner-verified on a real T4) with a Part 2 feature tour: one self-contained,
idempotent cell per feature, inline playback, honest runtime notes, loud
failures pointing at the backend log. Covers multilingual TTS (/generate),
zero-shot cloning (ref_audio multipart, incl. a commented own-voice upload
variant), voice design (/design/describe -> instruct), voice profiles
(save/list/reuse by id), TTS->ASR round trip (/transcribe), AI-watermark
detection with a generated-vs-plain-tone contrast (/watermark/*), the
OpenAI-compatible /v1 audio API via the official openai client, a two-voice
story (/longform/render SSE), a chaptered m4b audiobook (/audiobook SSE),
an optional miniature EN->ES video dub (upload -> prep poll -> transcribe ->
translate -> generate -> mux), and vocal-isolation stems off the dub job.
Every endpoint verified against the router sources and the 254-route
inventory. README/README_CN section text and the CHANGELOG entry now
describe the expanded scope.
notebooks/OmniVoice_Studio_Colab.ipynb boots the full app (web UI included)
on a free Colab T4: frontend built in-notebook with bun (releases ship no
standalone web bundle), backend installed via 'uv pip install --system .'
(the Docker image's path — keeps Colab's preinstalled CUDA torch), cuDNN 8
compat via scripts/setup.py, UI exposed through Colab's built-in kernel port
proxy (cloudflared alternative documented in-cell). Optional HF-token cell
reads Colab Secrets; smoke-test cell hits /health and plays a real /generate
WAV inline. All cells idempotent and fail loudly with actionable messages.
README.md + README_CN.md: the Colab section now carries the Open-in-Colab
badge for the in-repo notebook. CHANGELOG: [Unreleased] Added entry.