Commit Graph
100 Commits
Author SHA1 Message Date
Palash Debnath f832d616f7 feat(electron): add full VoiceStudio desktop app 2026-09-14 10:22:23 -07:00
Palash Debnath eaf8bb9538 Update README.md 2026-09-10 22:50:20 -07:00
Palash Debnath 8932b09339 Merge pull request #2043 from debpalash/fix/mcp-timeout-follows-backend
fix(mcp): tools wait for the backend's own budget, not a fixed 120 s
2026-09-10 16:37:46 -07:00
Palash Debnath a35c7babdf docs(mcp): the first generation also downloads the model inside the budget 2026-09-10 16:16:01 -07:00
Palash Debnath bd9be744eb Merge remote-tracking branch 'origin/main' into fix/mcp-timeout-follows-backend
# Conflicts:
#	CHANGELOG.md
2026-09-10 16:15:59 -07:00
Palash Debnath 14778aaba4 Merge pull request #2044 from debpalash/fix/pytorch-whisper-vram-budget
fix(asr): PyTorch Whisper budgets the VRAM its model needs
2026-09-10 16:15:17 -07:00
Palash Debnath 5ca94b7d72 Merge remote-tracking branch 'origin/main' into fix/pytorch-whisper-vram-budget
# Conflicts:
#	CHANGELOG.md
2026-09-10 15:52:34 -07:00
Palash Debnath 7247cef1b6 Merge remote-tracking branch 'origin/main' into fix/mcp-timeout-follows-backend
# Conflicts:
#	CHANGELOG.md
2026-09-10 15:52:21 -07:00
Palash Debnath ff5bad5a92 Merge pull request #2042 from debpalash/fix/transcribe-m4a
fix(asr): PyTorch Whisper transcribes M4A through the ffmpeg fallback
2026-09-10 15:51:53 -07:00
Palash Debnath e7911e3e97 fix(asr): reduced VRAM budgets only for exact OpenAI Whisper ids
Review follow-up. The budget matched model names by substring, so a custom
repo whose name contains "turbo", "small" or "base" (or a word such as
"database") got a reduced budget and could be admitted to CUDA without
enough memory. Reduced budgets now apply only to the exact OpenAI
checkpoint ids, .en variants included. Any other repository, fine-tunes
included, keeps the conservative 5.0 GB, as the engine doc says.
2026-09-10 15:33:11 -07:00
Palash Debnath d37da79b34 fix(mcp): generation waits also cover the backend's queue clock
Review follow-up. A generation first waits in the GPU pool's queue, on its
own clock (GPU_QUEUE_TIMEOUT_S, 1800 s by default), before its execution
budget starts, so a 630 s wait could still give up before the backend
returned its queue error. The generate wait now adds the queue budget.
Transcription is unchanged: run_transcribe_guarded starts its 300 s clock
at submission, so queue time already counts against it.

Parity tests pin each tool's wait above the backend's own worst case,
from ASR_TRANSCRIBE_TIMEOUT_S, GPU_QUEUE_TIMEOUT_S and generate_timeout_s
on cpu, cuda and mps. A later backend change that outgrows the MCP wait
now fails a test. A new case covers a CPU budget larger than the GPU one.
2026-09-10 15:31:14 -07:00
Palash Debnath b4cfd7aac0 fix(asr): keep readable audio at its native rate; cover the M4A route
Review follow-up. The shared loader resamples soundfile-readable audio to
16 kHz with a linear interpolation, which can alias 44.1/48 kHz input into
Whisper's band. PyTorch Whisper now reads such audio at its native rate,
as before, so the pipeline's band-limited resampler converts it. Only
files soundfile can't open (MP4/M4A) take the ffmpeg path, which resamples
properly. New tests: a 48 kHz stereo WAV reaches the pipeline at 48 kHz
without ffmpeg, a POST /transcribe with an .m4a returns 200, and the MCP
tool names M4A bytes .m4a.
2026-09-10 15:30:23 -07:00
Palash Debnath e501a596d3 docs(changelog): note the PyTorch Whisper VRAM budget fix (#2044) 2026-09-10 15:06:52 -07:00
Palash Debnath 033f8f2f64 fix(asr): PyTorch Whisper budgets the VRAM its model needs
The CUDA preflight demanded 5.0 GB of free VRAM for every model, sized for
full large-v3. The default model is large-v3-turbo, which the pipeline
loads in fp16: about 1.6 GB of weights, not the 3.2 GiB fp32 figure in the
old comment. So a 6 GB card with nothing else resident reported 5.0 GB
free and was sent to CPU every time, although CUDA ran the same audio in
37 s against minutes on CPU.

The budget is now fp16 weights + 1.5 GB workspace (batch 16) + 0.5 GB
headroom, per model and capped at the old 5.0 GB. That is 3.6 GB for turbo
and 5.0 GB for full large-v3 and any unrecognised model. Both CPU-fallback
warnings name the model and the OMNIVOICE_ASR_VRAM_PREFLIGHT=0 opt-out.
The engine doc lists the budgets.

Fixes #2041
2026-09-10 15:06:45 -07:00
Palash Debnath 39c348af26 docs(changelog): note the MCP timeout fix (#2043) 2026-09-10 15:05:25 -07:00
Palash Debnath 58d590a686 fix(mcp): tools wait for the backend's own budget, not a fixed 120 s
The MCP tools gave up on a backend POST after OMNIVOICE_MCP_TIMEOUT_S,
default 120 s, while the backend's own budgets run longer: 300 s for ASR,
and 300 s or more for generation. A transcription the backend would have
finished came back as an empty client-side timeout, and the abandoned
job kept holding the worker. The docstring said the timeout followed
OMNIVOICE_GENERATE_TIMEOUT_S, but it never read it.

Unset, each tool now waits for the backend's budget plus 30 s, never less
than 120 s. transcribe follows OMNIVOICE_ASR_TRANSCRIBE_TIMEOUT_S, and
generate_speech follows the larger of the GPU and CPU generation budgets,
scaled by text length like the backend. An explicit
OMNIVOICE_MCP_TIMEOUT_S still wins. docs/mcp.md says so.

Fixes #2040
2026-09-10 15:05:18 -07:00
Palash Debnath 6ff9ab80f8 docs(changelog): note the M4A transcribe fix (#2042) 2026-09-10 15:05:01 -07:00
Palash Debnath aef275a041 fix(asr): PyTorch Whisper transcribes M4A through the ffmpeg fallback
PyTorchWhisperBackend.transcribe read uploads with soundfile, and
libsndfile cannot open MP4/M4A (AAC). /transcribe and the MCP tool both
accept .m4a, so every such upload failed with "Format not recognised"
before ASR ran. It now uses _load_audio_16k_mono_f32, the loader the
sherpa backend already uses: soundfile first, then the validated ffmpeg
path, returning the 16 kHz mono float32 Whisper expects.

Fixes #2039
2026-09-10 15:04:53 -07:00
Palash Debnath 0525a078e0 Merge pull request #2035 from debpalash/fix/cosyvoice-advisory-floors
test(cosyvoice): raise the advisory floors to GitHub's fixes
2026-09-10 14:57:12 -07:00
Palash Debnath 083e7965f8 Merge pull request #2037 from debpalash/fix/sidecar-ready-diagnostics
fix(sidecar): a failed ready handshake names its cause
2026-09-10 14:37:51 -07:00
Palash Debnath df81bcd1ac fix(deps): raise protobuf and transformers bounds in pyproject too
The floors test checked only uv.lock, and pyproject still allowed
transformers>=5.5.0 and protobuf>=4.25. A fresh resolution, or an install
without the lock, could still pick a release below the advisory fixes.
The manifest now requires transformers>=5.10.0 and protobuf>=5.29.6. The
lock already resolved 5.15.1 and 7.36.0, so no package version changes;
only the recorded requirements do.
2026-09-10 14:35:31 -07:00
Palash Debnath aa98bb6974 Merge pull request #2038 from debpalash/fix/worker-control-teardown-flake
test(workers): give Control teardown waits a generous bound
2026-09-10 14:25:11 -07:00
Palash Debnath 1f386817cd Merge remote-tracking branch 'origin/main' into fix/sidecar-ready-diagnostics
# Conflicts:
#	CHANGELOG.md
2026-09-10 14:16:28 -07:00
Palash Debnath edc7199ab8 Merge pull request #2036 from debpalash/fix/youtube-bot-check-guidance
fix(dub): YouTube's bot check points at the app's cookie import
2026-09-10 14:15:26 -07:00
Palash Debnath 942561bbb3 test(sidecar): repair the literals in the new drain and error-frame tests 2026-09-10 14:12:04 -07:00
Palash Debnath 2e2b9fedd9 fix(sidecar): bind each stderr drain to its own process
The drain thread took its buffer from spawn but read self._proc when it
started, so a drain that started late could read a replacement process's
stderr into the old buffer. Spawn now passes the process and its buffer
together. Tests cover a late drain and the error-frame branch of the ready
diagnostics.
2026-09-10 14:09:20 -07:00
Palash Debnath 837baa922a Merge remote-tracking branch 'origin/main' into fix/cosyvoice-advisory-floors
# Conflicts:
#	CHANGELOG.md
2026-09-10 14:07:43 -07:00
Palash Debnath 0688c37f04 Merge pull request #2020 from debpalash/feat/engine-list-detail
feat(catalogue): engine list + detail panel, weights under their engine
2026-09-10 14:06:26 -07:00
Palash Debnath 973f44c0a5 docs(changelog): note the worker teardown flake fix (#2038) 2026-09-10 14:01:58 -07:00
Palash Debnath acae6bea4e test(workers): give Control teardown waits a generous bound
test_blocked_reconnect_persistence_does_not_stall_another_worker failed on
a Windows runner (#2020's Smoke job) when its final wait for the Control
stream to end expired at 2s. That wait only proves the stream ends: after
both releases, the real disconnect path persists all 64 queued tasks, and
a slow runner took longer. The assertions that matter, another worker's
heartbeat and prewarm staying under 0.2s while reconciliation is blocked,
are untouched.

The three waits that only bound a Control stream's exit now share
_CONTROL_EXIT_TIMEOUT_S = 10s. A stream that never ends still fails.
2026-09-10 14:01:50 -07:00
Palash Debnath fc9bd8c8d8 test(dub): import app modules at test time in the bot-check tests 2026-09-10 13:52:50 -07:00
Palash Debnath 9e4d67325f fix(sidecar): each spawn quotes only its own stderr
A shared deque cleared on spawn could still receive late lines from the
previous process's drain thread, and a new start-up failure would quote
them. Each spawn now gets a fresh buffer passed to its own drain thread.
2026-09-10 13:52:41 -07:00
Palash Debnath bb7eb06697 test(deps): raise the app's protobuf and transformers floors too
The app's own lock already resolves transformers 5.15.1 and protobuf
7.36.0, but PYTHON_FLOORS still allowed transformers 5.5.0 and did not
pin protobuf. A later lock change could have slipped below the fixes for
the advisories Dependabot raised on CosyVoice's manifest (#2030, #2031).
2026-09-10 13:49:32 -07:00
Palash Debnath 3a90be329f docs(changelog): note the sidecar ready-failure diagnostics (#2037) 2026-09-10 13:46:38 -07:00
Palash Debnath 6a923f5a10 fix(sidecar): a failed ready handshake names its cause
A sidecar that failed its ready handshake reported "did not signal ready:
None" for the two most likely causes. _recv returns None on EOF, and a
deadline kill closes stdout just like a crash, so the report could not
tell a slow start from a start-up crash. The exit code was never read,
and stderr went only to the log.

The error now names which it was:

- no ready frame within the deadline, so it was stopped;
- it exited with code N before signalling ready;
- it sent the wrong op, or reported an error frame (with its message).

Each ends with the sidecar's last stderr lines, scrubbed of home paths
and secrets and capped at 800 characters. The prefix is unchanged, so
existing matching still works. The echo sidecar gets test-mode hooks to
exit, stall or send the wrong op before ready.

Fixes #2026
2026-09-10 13:46:31 -07:00
Palash Debnath 8bad7a316b docs(changelog): note the YouTube bot-check guidance (#2036) 2026-09-10 13:44:29 -07:00
Palash Debnath 437593bfbb fix(dub): YouTube's bot check points at the app's cookie import
A YouTube link that hits "Sign in to confirm you're not a bot" showed
yt-dlp's raw advice to pass --cookies-from-browser or --cookies, which are
CLI flags nobody using VoiceStudio can pass. It now has its own failure
class, VIDEO_DOWNLOAD_BOT_CHECK. Its hint says to export signed-in cookies
as a cookies.txt file and attach it in Dub, or to upload the video
instead. The class is terminal, so it is neither retried as a network drop
nor escalated through player clients like a 403.

Fixes #2034
2026-09-10 13:44:21 -07:00
Palash Debnath 686d9c5fcf fix(catalogue): repair the guidance the Weights-list rename broke
The rename to "the engine's Weights list in Model Catalogue" left several
messages without a verb, and pointed others at the wrong place:

- The offline and create-voice messages say what to do again.
- pyannote has no owning engine, so diarization points at Other weights.
- The Hugging Face mirror moved to Settings → Network, and voice previews
  moved to Settings → Storage.
- Unloading and switching engines happen in the engine list, not a
  Weights list.
- A bad saved path points at Settings → Storage or the env file.
- Docstrings that read "the the" are fixed.

The dub stream-drop fallback goes through i18n in all 21 locales. A
Dictation pick on a row that is already downloading no longer starts a
second install: the row's radio is disabled while it works, and
useModelDownloads refuses a second mutation for a repo already in flight.
The Supertonic-3 license test checks for the Accept wording.
2026-09-10 13:34:54 -07:00
Palash Debnath 01d503f64f Merge remote-tracking branch 'origin/main' into fix/cosyvoice-advisory-floors 2026-09-10 13:31:49 -07:00
Palash Debnath c94585a339 Merge pull request #2032 from debpalash/fix/darwin-eperm-exit-settle
fix(lifecycle): wait for a Darwin exit to register after EPERM
2026-09-10 13:28:34 -07:00
Palash Debnath 40139bb2a2 Merge remote-tracking branch 'origin/main' into fix/cosyvoice-advisory-floors 2026-09-10 13:20:21 -07:00
Palash Debnath 045f75c30e Merge pull request #2031 from debpalash/dependabot/pip/backend/engines/cosyvoice_subprocess/transformers-5.10.1
chore(deps): bump transformers from 4.57.6 to 5.10.1 in /backend/engines/cosyvoice_subprocess
2026-09-10 13:20:16 -07:00
Palash Debnath 4a4fa6a9e0 test(cosyvoice): raise the advisory floors to GitHub's fixes
The floors came from OSV alone, which did not list the protobuf and
transformers advisories GitHub flagged once the manifest reached main
(Dependabot #2030, #2031). Raise them to the first fixed releases so a
later downgrade fails the test. Note that transformers 5 was checked
against CosyVoice's tokenizer and cached decoding.
2026-09-10 13:04:49 -07:00
Palash Debnath 5f3f35f134 Merge remote-tracking branch 'origin/main' into fix/darwin-eperm-exit-settle
# Conflicts:
#	CHANGELOG.md
2026-09-10 13:04:31 -07:00
Palash Debnath 32393613be Merge branch 'main' into feat/engine-list-detail 2026-09-10 13:03:00 -07:00
Palash Debnath 2c83f5c16c Merge pull request #2013 from debpalash/feat/catalogue-one-page
feat(catalogue): one page — setup summary over per-family engines and weights
2026-09-10 13:02:39 -07:00
Palash Debnath a76e743415 docs(changelog): note the Darwin exit-settle fix (#2032) 2026-09-10 13:02:08 -07:00
Palash Debnath 8cf7bebb61 fix(lifecycle): wait for a Darwin exit to register after EPERM
XNU stops signalling a process as soon as it starts exiting but posts
NOTE_EXIT later in the same exit. A KILL that lands in that window gets
EPERM while the exit probe still reads "alive", so stopping a child that
TERM had just ended could fail with "Operation not permitted". This
flaked the macOS run of contained_exit_probe_preserves_a_live_child.

The EPERM branch now re-probes for up to 250 ms before treating the error
as a live, unsignalable root. Live roots, reaped roots and probe failures
are still errors.
2026-09-10 13:02:00 -07:00
Palash Debnath 05df8159eb Merge branch 'main' into dependabot/pip/backend/engines/cosyvoice_subprocess/transformers-5.10.1 2026-09-10 12:58:26 -07:00
Palash Debnath 5980fce852 Merge pull request #2030 from debpalash/dependabot/pip/backend/engines/cosyvoice_subprocess/protobuf-5.29.6
chore(deps): bump protobuf from 4.25.9 to 5.29.6 in /backend/engines/cosyvoice_subprocess
2026-09-10 12:58:02 -07:00
Palash Debnath 0eaa1bdc3e Merge branch 'main' into feat/catalogue-one-page 2026-09-10 12:34:20 -07:00
Palash Debnath 44d3639c02 Merge pull request #2025 from debpalash/feat/cosyvoice3-isolated
feat(engines): CosyVoice 3 installs in one click into its own venv
2026-09-10 12:33:01 -07:00
Palash Debnath ba8f6cfd15 Merge feat/catalogue-one-page (with main) into feat/engine-list-detail
Conflicts: RecoBanner (deleted here: the recommendation card is gone),
ModelStoreTab + EngineCompatibilityMatrix (this branch's rewrite kept),
supertonic3 backend (main's own-venv check kept, message without the
retired "→ Engines" step), CHANGELOG (base layout + the #2020 line).

Carried over from main and the review:
- The list row hides Install while only the license review is left
  (main's #2017 rule, now in the row; Accept lives in the panel).
- Engine action aria labels go through i18n (engines.aria*, all 21
  locales) instead of hardcoded English.
- Every "Model Catalogue → Engines/Models" path main added, plus the
  frontend strings that still named the retired panes, now point at the
  one-page catalogue.
- test_engine_unavailable_reason_1866 reads the license matcher from its
  new home, engines/engineDisplay.js.
2026-09-10 12:17:02 -07:00
Palash Debnath 80ec0d06c9 Merge origin/main into feat/catalogue-one-page; harvest remaining review threads
Conflicts: CHANGELOG (main cut 0.5.2 and opened a new Unreleased; the
#2013 lines move there), pockettts/supertonic3 docs (main's new one-click
install text kept, with the retired "Model Catalogue → Engines →" step
dropped, as in the rest of docs).

Review fixes on top:
- Bulk installs name the right repository on failure: every "install
  several" button now pairs allSettled results with their request before
  filtering (shared failedInstalls/installFailureMessage + unit test).
- confucius4-tts docs: "The first synthesis triggers".
2026-09-10 12:09:39 -07:00
Palash Debnath 85ce7206b5 fix(engines): keep the literal data filter so tar extraction is visibly validated
Bandit B202 flagged the custom filter callable. Links are now left out by
choosing the members, and extractall keeps filter="data", which validates
everything extracted. Same behaviour: the Matcha-TTS tarball's absolute
link is skipped instead of aborting the fetch.
2026-09-10 12:02:33 -07:00
Palash Debnath 180371910e fix(cosyvoice): patched dependencies, no wetext download, Windows long-path hint
Built the real environment on Windows to check the one-click install.
- The pins upstream carries with published advisories (diffusers,
  hydra-core, lightning, modelscope, onnx, protobuf, transformers) are
  raised to fixed releases; that exact set installs and passes the
  installer's import probe. pyarrow, not needed, is dropped. A test keeps
  every pin at or above its advisory fix.
- wetext is dropped with its install-time fetch. Its data exists only on
  ModelScope, which rate-limits downloads; a throttled fetch left files
  missing while reporting success, so the normaliser failed silently.
  CosyVoice reads text as written without it, and nothing reaches
  ModelScope at install or synthesis time. The unused post-install hook
  goes with it.
- openai-whisper builds from source, and under a long cache path the build
  hits Windows' 260-character limit; the install failure now says to turn
  on long-path support.
2026-09-10 11:39:50 -07:00
Palash Debnath efdec50081 fix(engines): a source tarball with a link in it still extracts
The stdlib data filter raises on a link to an absolute path, and the
pinned Matcha-TTS tarball ships one (data -> its author's training
folder), which aborted the fetch and with it the CosyVoice install. Found
by building the real environment. Links are now skipped on every
interpreter, as the pre-3.11.4 path already did.
2026-09-10 11:34:03 -07:00
Palash Debnath 655db866d1 Merge pull request #2029 from debpalash/fix/release-checksum-race
fix(release): one job writes the notes and publishes, after every platform
2026-09-10 11:31:19 -07:00
Palash Debnath 7c1599b73a test(release): pin the missing-checksum gate; docs drop the manual publish step
The guard now proves the job exits on a missing platform before it
rewrites the notes or publishes, so removing that exit fails CI.
RELEASING.md's end-to-end updater test still said to publish the draft by
hand; the workflow publishes it.
2026-09-10 11:08:10 -07:00
Palash Debnath 399b9ec3f6 Merge remote-tracking branch 'origin/main' into feat/cosyvoice3-isolated 2026-09-10 11:06:04 -07:00
Palash Debnath b804a6f23f Merge pull request #2022 from debpalash/feat/moss-tts-nano-isolated
feat(engines): MOSS-TTS-Nano installs into its own venv, pinned to a working upstream
2026-09-10 11:05:21 -07:00
Palash Debnath 9561d41fb6 fix(cosyvoice): a missing model-folder override is an error, not a silent swap
When OMNIVOICE_COSYVOICE_MODEL pointed at a folder that no longer existed,
the sidecar quietly loaded the installed CosyVoice 3 model instead, so it
spoke with a model and voice the user had not chosen while
model_identity() still named theirs. It now fails with a message naming
the path and how to fix or clear it.
2026-09-10 10:51:13 -07:00
Palash Debnath 6305f577e1 docs(changelog): link the release-publish entry to #2029 2026-09-10 10:49:16 -07:00
Palash Debnath dd1dce75cb fix(release): one job writes the notes and publishes, after every platform
Each build leg appended its checksums to the shared release notes with
softprops/action-gh-release. Two consequences, both seen on v0.5.2:

- The appends were concurrent read-modify-writes, so a leg that read the
  notes before another wrote them lost its section. v0.5.1 and v0.5.2
  both shipped without the macOS Apple Silicon checksums in the notes,
  though the SHA256SUMS file was attached.
- softprops defaults to draft: false, so the first leg to finish
  published tauri-action's draft while the others were still building.
  v0.5.2 went public at 17:27; its complete latest.json landed at 17:38.

Legs now only attach their SHA256SUMS file with gh release upload. A new
release-notes-checksums job runs once after the matrix, the updater-manifest
repair and the uninstall scripts, writes all four platforms' checksums in
matrix order, fails if one is missing (leaving the release a draft), and
then publishes it. contributors-strip edits the notes after it, so the
notes have one writer at a time. A test pins all of that.

docs/RELEASING.md described a manual publish and .exe / .deb / .nsis.zip
artifacts the workflow no longer builds; it now matches what ships.
2026-09-10 10:49:08 -07:00
Palash Debnath 9c925b17a0 Merge remote-tracking branch 'origin/main' into feat/moss-tts-nano-isolated 2026-09-10 10:38:43 -07:00
Palash Debnath 30c64dc44b Merge pull request #2021 from debpalash/feat/voxcpm2-isolated
feat(engines): VoxCPM2 installs into its own venv and runs in a sidecar
2026-09-10 10:37:43 -07:00
Palash Debnath e8be51f751 Merge remote-tracking branch 'origin/feat/moss-tts-nano-isolated' into feat/cosyvoice3-isolated
# Conflicts:
#	CHANGELOG.md
2026-09-10 10:13:53 -07:00
Palash Debnath 919116dfa5 Merge remote-tracking branch 'origin/feat/voxcpm2-isolated' into feat/moss-tts-nano-isolated
# Conflicts:
#	CHANGELOG.md
2026-09-10 10:13:21 -07:00
Palash Debnath 9dd005eab5 docs(changelog): list VoxCPM2 under Unreleased, not the released 0.5.2
Merging main placed the entry beside its old neighbour, which now sits in
the released [0.5.2] section.
2026-09-10 10:11:47 -07:00
Palash Debnath 8a497aa4db Merge remote-tracking branch 'origin/main' into feat/voxcpm2-isolated 2026-09-10 10:10:37 -07:00
Palash Debnath 38c2405fa1 Merge pull request #2007 from debpalash/release/v0.5.2
docs(changelog): cut the 0.5.2 release section
2026-09-10 10:09:20 -07:00
Palash Debnath 97b153df3a test(changelog): count versions the way the app's changelog parser reads them
The one-section-per-version check matched raw heading text, so [v0.5.2]
and [0.5.2] would pass as two versions while core.changelog, which serves
the in-app notes, strips the v and whitespace and reads them as one. The
check now uses parse_changelog itself.
2026-09-10 09:47:54 -07:00
Palash Debnath 6b62866fb5 test(cosyvoice): its fake venv carries the completion marker 2026-09-10 09:46:21 -07:00
Palash Debnath ab565e9b5c Merge remote-tracking branch 'origin/feat/moss-tts-nano-isolated' into feat/cosyvoice3-isolated 2026-09-10 09:46:02 -07:00
Palash Debnath 594daf9251 test(moss-tts-nano): its fake venv carries the completion marker 2026-09-10 09:45:53 -07:00
Palash Debnath 8114132a72 Merge remote-tracking branch 'origin/feat/voxcpm2-isolated' into feat/moss-tts-nano-isolated 2026-09-10 09:45:33 -07:00
Palash Debnath 63a1c1791a fix(engines): an own-venv engine needs a finished install, and VoxCPM2 PCM is 48 kHz
engine_venv_python() accepted any venv interpreter, so a reinstall that
failed partway made the resolver pick the sidecar and report it ready,
hiding the working in-process engine. It now also requires the completion
marker, which the import probe writes only after the engine imported in
that venv and which a new dependency step removes. That covers VoxCPM2
here and PocketTTS / Supertonic-3 from #2016.

The parent reads sidecar PCM at the engine's fixed 48 kHz, so the VoxCPM2
sidecar resamples a model that reports another rate instead of passing its
samples through mislabelled. The retry test now proves a permanent error
runs once.
2026-09-10 09:45:20 -07:00
Palash Debnath 4e37e21745 chore(release): v0.5.2
Cut the Unreleased notes as 0.5.2 (2026-09-10) and fold in the untagged
0.5.2 section prepared on 2026-09-02, so release.yml publishes one
complete section. A test now requires one section per version.
2026-09-10 09:42:08 -07:00
Palash Debnath 3bfdeeddba Merge pull request #2024 from debpalash/fix/uv-no-app-config
fix(engines): engine installs never inherit VoiceStudio's own uv config
2026-09-10 09:42:02 -07:00
Palash Debnath be722ff608 test: register the CosyVoice sidecar with the stdout guard and STRUCTURE.md 2026-09-10 09:22:24 -07:00
Palash Debnath 0b7117b833 Merge remote-tracking branch 'origin/feat/moss-tts-nano-isolated' into feat/cosyvoice3-isolated 2026-09-10 09:22:06 -07:00
Palash Debnath a88c39eac1 test: register the MOSS-TTS-Nano sidecar with the stdout guard and STRUCTURE.md 2026-09-10 09:21:58 -07:00
Palash Debnath 3f19b2e9a7 Merge remote-tracking branch 'origin/feat/voxcpm2-isolated' into feat/moss-tts-nano-isolated 2026-09-10 09:21:40 -07:00
Palash Debnath 172a142825 test: register the VoxCPM2 sidecar with the stdout guard and STRUCTURE.md
The #1428 guard pins the exact set of sidecars it scans, and
docs/STRUCTURE.md must list every engine adapter; both failed CI on the
new engines/voxcpm2_subprocess.
2026-09-10 09:21:32 -07:00
Palash Debnath ac35351000 Merge remote-tracking branch 'origin/main' into fix/uv-no-app-config
# Conflicts:
#	CHANGELOG.md
2026-09-10 09:11:59 -07:00
Palash Debnath f9da18842a docs(changelog): link the CosyVoice entry to #2025 2026-09-10 09:10:09 -07:00
Palash Debnath c4206ee1aa Merge remote-tracking branch 'origin/feat/moss-tts-nano-isolated' into feat/cosyvoice3-isolated 2026-09-10 09:09:41 -07:00
Palash Debnath ec1529479d feat(engines): CosyVoice 3 installs in one click into its own venv
CosyVoice ran only in-process, which needed it importable from the app's
own interpreter; upstream's setup (its own Python 3.10 environment, pins
that clash with the app's) never gives that, so the engine was unusable
from an installer build. The one-click installer now clones a reviewed
commit (074ca6dc) and its Matcha-TTS submodule (dd9105b3) into
DATA_DIR/engines/cosyvoice/, builds a Python 3.10 venv, downloads the
CosyVoice 3 weights, and a self-contained sidecar runs the model there.

Upstream's requirements cannot be used as they are: they add a
third-party Azure DevOps index, pin torch 2.3.1 (CUDA 12.1 only, no
RTX 50-series), pull TensorRT and DeepSpeed on Linux, and do not even
resolve together (fastapi). A trimmed list ships with the app
(engines/cosyvoice_subprocess/requirements.txt, which says what was
dropped and why); torch comes from the per-host 2.7.0 pins. Every package
installs from a wheel except two pure-Python ones, so nothing needs a
compiler, and SoX is not used.

The installer gains what CosyVoice needs, generally:
- ExtraSource fetches a pinned submodule tree, which neither a depth-1
  clone nor GitHub's tarball includes;
- weights_allow_patterns downloads only the files the model loads
  (5.4 of 9.8 GB);
- post_install_code runs an optional fetch in the engine's venv: here,
  wetext's normalisation data, which it otherwise downloads from
  ModelScope on every model load. A failure only leaves that to first use.
- The completion marker now applies to engines with weights too, since
  weights left by an earlier run do not prove the dependency step
  finished. IndexTTS keeps its weights check, so no existing install is
  asked to reinstall.

The sidecar formats prompts as upstream's v3 examples do, speaks in
upstream's sample voice when there is no reference clip (v3 has no
built-in speakers), and never hands AutoModel a missing folder, which
would start a ModelScope download. The gateway keeps offering the
CosyVoice weights as a plain download to remote workers that run the
in-process engine.
2026-09-10 09:09:37 -07:00
Palash Debnath 61a5418c6a Merge remote-tracking branch 'origin/feat/voxcpm2-isolated' into feat/moss-tts-nano-isolated 2026-09-10 09:08:38 -07:00
Palash Debnath b28390af30 test(voxcpm2): patch the base class the engine really inherits
Other suites purge services from sys.modules, so importing
subprocess_backend inside the test can yield a different module than the
one VoxCPM2SubprocessBackend subclassed, and the patch then misses: the
real generate() ran and failed. Patch VoxCPM2SubprocessBackend's own base.
2026-09-10 09:07:59 -07:00
Palash Debnath 764fed09bc Merge pull request #2018 from debpalash/fix/license-reason-passthrough
fix(engines): say when a license or the platform is what blocks an engine
2026-09-10 09:04:07 -07:00
Palash Debnath 4fdde15079 Merge pull request #2023 from debpalash/fix/translation-uninstall-guard
fix(translation): uninstalling an engine never removes what others need
2026-09-10 09:00:07 -07:00
Palash Debnath 14a8a9cd46 docs(changelog): link the uv config entry to #2024 2026-09-10 08:46:57 -07:00
Palash Debnath 1af1ecc5bd fix(engines): engine installs never inherit VoiceStudio's own uv config
The backend runs inside the app's tree, and the uv processes it starts for
engine installs had no working directory of their own. uv therefore
discovered VoiceStudio's pyproject.toml and applied its [tool.uv]
constraint-dependencies, torch==2.8.0 among them, to each engine's venv.

Resolved that way, MOSS-TTS-v1.5 (torch==2.9.1+cu128) and Confucius4
(torch==2.7.0) are unsatisfiable, so their one-click installs and
bootstraps could never succeed. An engine that pins no torch got the app's
instead of its own, so its venv was not really independent.

uv_subprocess_env, which every one-click install step and every engine
bootstrap already uses, now always sets UV_NO_CONFIG=1. It used to return
None in two cases and let the call inherit the environment; it now always
returns a copy. Region and custom mirrors still apply, because they reach
uv as UV_INDEX_URL. The app's own `uv sync` and the translation installer,
which install into the app's environment on purpose, are unchanged.
2026-09-10 08:46:49 -07:00
Palash Debnath e0879027d5 Merge remote-tracking branch 'origin/main' into fix/license-reason-passthrough
# Conflicts:
#	CHANGELOG.md
#	tests/test_engine_unavailable_reason_1866.py
2026-09-10 08:41:45 -07:00
Palash Debnath 5298c8e5e1 Merge pull request #2016 from debpalash/feat/isolated-engine-installs
feat(engines): isolated one-click installs for five engines
2026-09-10 08:38:39 -07:00
Palash Debnath 1de4fedad7 docs(changelog): file the translation guard under Fixed, not Highlights 2026-09-10 08:33:55 -07:00
Palash Debnath c5f32d020a fix(translation): uninstalling an engine never removes what others need
The translation uninstall route runs `pip uninstall -y <package>` on the
app's own environment. Two entries made that break something else:

- The LLM engine's package is openai, a core dependency that Settings →
  LLM Providers also uses. Unlike Argos, it was not marked builtin, so
  uninstalling that engine removed it from the app.
- Google, DeepL, Microsoft and MyMemory share deep_translator. Uninstalling
  any one removed it for all four.

The route now asks uninstall_blocker() first. It refuses (400) a package
VoiceStudio itself depends on, read from the installed package metadata so
there is no second list to keep in step, and refuses (409) a package
another engine shares, naming the engines that would stop working. The
openai entry is marked builtin as well, and a test requires every entry
backed by an app dependency to be.
2026-09-10 08:26:53 -07:00
Palash Debnath f5ea363724 fix(engines): name the missing MPS on Apple Silicon, and hold the MLX test on every host
mlx_supported() fails three ways. Only the non-Apple branch is a platform
gap; Apple Silicon whose PyTorch cannot use MPS was left on the generic
line, and the live-host test asserted a platform reason even there, so it
would fail on such a Mac. That case now has its own owned sentence, and
the live test asserts only the branch its host can produce, with literal
cases covering the rest on every machine.
2026-09-10 08:22:20 -07:00
Palash Debnath 4280157407 docs(changelog): link the MOSS-TTS-Nano entry to #2022 2026-09-10 08:21:06 -07:00