Skip to content

Releases: debpalash/VoiceStudio

v0.4.2 — OmniVoice Studio

Choose a tag to compare

@github-actions github-actions released this 27 Jul 23:23
b01c635

Highlights

  • The update prompt is a small toast with buttons, not a screenful of release notes
  • Installing an update no longer throws away work that is still running
  • Quitting the app mid-generate stops reporting itself as a crash
  • A half-downloaded model repairs itself instead of dead-ending
  • "Dismiss" no longer reads as "terminate an employee" in five languages

Changed

  • An available update now announces itself as a toast with Install and restart, What's new and Later, instead of only a dot beside the version number. The release notes stay in Settings → Updates, where there is room for them — a version's notes are the whole changelog section, and rendering them inline is what made the old prompt fill the screen (#1272)

Fixed

  • Installing an update no longer relaunches the app while work is running. The check only knew about dub synthesis, so a restart could silently discard an upload, a transcription, a translation, an export or a standalone synth — and two overlapping synths used to cancel each other's protection. Install is now greyed out while anything is in flight (#1272)
  • A half-downloaded model now repairs itself instead of failing with a raw 500. The automatic repair recognised only one of the two ways the loader reports missing weights, so an interrupted download whose subfolder failed to load got neither the repair nor a hint about what to do (#1273)
  • Quitting the app with a generate queued reported "500 Internal Server Error: model load skipped: backend shutting down" and offered to file a bug for it. A shutdown is not a fault: the backend now answers 503 with what to do, and no bug report is offered for it (#1276)
  • Dub history: clearing a large history while a render was running could still resurrect the deleted job — which markers survived depended on the process hash seed, and an oversized purge could discard a live one (#1252)
  • German, Japanese, Russian and both Chinese locales rendered "Dismiss" as the employment sense — "terminate an employee" — on close buttons (#1272)
  • The "wait for the current job to finish" message named dubbing specifically, though it now covers uploads, transcription, translation, exports and synthesis; reworded across all 21 languages (#1272)

Linux x64 artifacts

81c1265984ec4376aecd28417413b037cdef3b1b9fe6bc7cb8d731cad7811f60  OmniVoice Studio_0.4.2_amd64.AppImage
4e880f64a85333b9c54a1a15990e54b02355667faf609e0b82160e75d88d8906  OmniVoice Studio_0.4.2_amd64.AppImage.sig

macOS Intel artifacts

22f0212893ee2b0b373329b730520fad943bd5685d1a6219a4b4b53b1e8ef949  OmniVoice Studio_0.4.2_x64.dmg
7e1ebf185e456fe89a5fbee3603f1992604cf9c672717fe7d63a0fa64d2d14e1  OmniVoice Studio.app.tar.gz
e2d5cc678b4ed3ee637e37a48d6e109babe6d0311d041dc867e3bc85493b160a  OmniVoice Studio.app.tar.gz.sig

Windows x64 artifacts

6cd5b924fa1e6ec2022ff3db0c18bec24e765fb71a294f9101fac807d4a132a1 *OmniVoice Studio_0.4.2_x64_en-US.msi
1ebddf5fcd019345085763f127a6be20b6d3cff0b241a2095e1aafd987b4d369 *OmniVoice Studio_0.4.2_x64_en-US.msi.sig

Contributors

Thank you all 💜

@debpalash

v0.4.1 — OmniVoice Studio

Choose a tag to compare

@github-actions github-actions released this 26 Jul 22:00
9736fd4

Highlights

  • AMD GPUs are used again — every ROCm host was silently running on the CPU
  • Two synth failures that used to say "an error OmniVoice doesn't recognize" now say what actually went wrong
  • A dub URL ingest that fails on a disk problem now says which folder and why
  • A broken audio dependency no longer takes the whole backend down at startup
  • A GPU too small for the chosen engine now says so up front, not after a five-minute wait
  • A port conflict now says so, instead of "Backend died (exit code 1)"
  • A model download that dies at 90% now resumes instead of failing the install
  • First run: Continue and the Hugging Face token box no longer sit under the status bar
  • macOS 12 (Monterey): the app launches again instead of dying on startup
  • Exporting a voice or a dub no longer fails when the name isn't spelled in Latin letters
  • Two more failures that used to arrive as raw OS text now say what to do about them
  • Unload works on every model the panel offers it for, and a language the active engine can't speak says so
  • Deleting a dub no longer un-deletes itself when the job it belonged to finishes

Changed

  • First run: the status bar (Logs, version, Sponsors) appears once you reach the studio, instead of overlaying the setup steps (#1241)

Added

  • OMNIVOICE_MCP_ALLOWED_HOSTS — comma-separated host patterns (e.g. host.containers.internal:*,192.168.1.5:*) that extend the MCP SDK's DNS-rebinding allowlist, so AI agents running in Docker containers or on other machines can reach the /mcp endpoint. The SDK default is localhost-only; this env var is opt-in (#1249)

Docs

  • Docker: ROCm section explains that torch.cuda.is_available() == True isn't proof the app is on the GPU, and notes the --group-add needed for /dev/kfd on rootless hosts (#1228)

Fixed

  • Deleting a dub while it was still importing crashed the import with the toast ingest: 'mgw39lx3' — a dict key and nothing else — and the delete could then be undone by the job's own pending write, in history or mid-render; both are fixed, and no failure can present itself as a bare value again — thanks dustmaker124-ui! (#1252, #1253)
  • macOS 12 (Monterey): the app threw on startup and never started the backend — it called a Safari 16 method on the WebView that macOS ships. It launches and works now; some styling still needs a newer WebView (tracked in #1268) — thanks singhrahat! (#1245)
  • Settings → Engines: Unload failed with 400 Unknown model id: engine:kittentts on any in-process engine — the panel offered the button for ids the backend never accepted; the warm dictation model had the same gap — thanks JavaxmI! (#1247)
  • Picking a language the active engine can't speak recited 23 codes without saying which engine refused or that switching engine was the fix — thanks pulananave! (#1257)
  • A YouTube import that failed as "DRM protected" and then worked on a manual retry now escalates the player client automatically, and a genuinely undownloadable video says so — thanks gysahlgreene! (#1254)
  • Exporting a voice profile, persona, dub, subtitle or stem whose name is Chinese, Japanese, Korean, Cyrillic, Greek, Hebrew or emoji failed with a 'latin-1' codec 500 — every download endpoint now sends the name correctly, and browsers get the real one back — thanks zvxzdx! (#1262)
  • A synth that failed because ffmpeg/ffprobe wasn't on the system path said "an error OmniVoice doesn't recognize"; it now names the media engine and points at Settings → Audio tools, and the app's own copy is published on PATH so dependencies find it in the first place — thanks Heuvelsma! (#1256)
  • Windows "The paging file is too small" arrived as a bare 500; it now explains that this is a virtual-memory setting, not full RAM, and gives the steps to raise it — thanks trankeny545-sudo! (#1251)
  • AMD/ROCm: every ROCm host was silently force-routed to the CPU — the compatibility gate compared a CUDA sm_ tag against a ROCm build's gfx list, which can never match — thanks simmessa! (#1228)
  • AMD/ROCm: torch.compile was disabled on all AMD hosts by the same mismatched comparison (#1228)
  • AMD/ROCm: HSA_OVERRIDE_GFX_VERSION is auto-set only when your card genuinely needs it and the remap target exists in your build; gfx1150/gfx1151 (Strix Point/Halo) added to the map (#1228)
  • Windows blocking an engine file (Smart App Control, WDAC, or AppLocker) is now named, with the fix for personal and managed PCs — thanks AdityaHemantBhat! (#1227)
  • A failed audio write (LibsndfileError: System error.) now names the target file, its folder's writability and the drive's free space — thanks morozov28061995-boop! (#1221)
  • Dub URL ingest: a disk error now names the job folder, its writability and the drive's free space, instead of pointing at the system TEMP folder it never used — thanks dustmaker124-ui! (#1225)
  • Dub URL ingest fails immediately when the job folder is missing or unwritable, instead of starting a download that can only fail (#1225)
  • The backend no longer dies at startup when transformers can't resolve its audio tokenizer (a missing or mismatched torchaudio, common on Google Colab) — it starts, and the error arrives with a repair hint — thanks Navdeep-Chauhan-777! (#1229)
  • Importing omnivoice.utils.* no longer drags in torch, torchaudio, transformers and the full model definition — thanks Navdeep-Chauhan-777! (#1229)
  • Colab notebook: the install cell now catches a broken environment with the real error, instead of a 5-minute health timeout two cells later — thanks Navdeep-Chauhan-777! (#1229)
  • A GPU with less VRAM than the chosen engine needs is flagged in Settings → Engines before you generate, instead of showing a clean green "accelerated" until the job times out — thanks AdityaHemantBhat and @beingavais! (#1226, #1222)
  • A generation timeout now names your actual card and its VRAM and recommends a lighter engine (#1226, #1222)
  • First run: Continue and the Hugging Face token box rendered underneath the status bar, off the bottom of the window — the wizard laid itself out against the viewport instead of its own frame (#1241)
  • A busy port 3900 now reports a port conflict instead of "Backend died (exit code 1)", in every language — thanks xipb14! (#1223)
  • The app verifies it actually freed the port before starting the backend, rather than assuming the kill worked (#1223)
  • A model download truncated near the end is now retried and resumed instead of aborting the whole install — thanks Reaksa-Cambodia! (#1224)
  • Engine first-use downloads (VoxCPM2, MOSS-TTS-Nano) retry transient network failures instead of failing the load outright (#1224)
  • A backend killed by the OS mid-stream now leaves a low-memory trail in the crash report (#1224)

macOS Apple Silicon artifacts

3c88dc39fbef840a81d6c4d5df862d4cb1970bebe320da973e7f304d97e4febe  OmniVoice Studio_0.4.1_aarch64.dmg
be702e7f03913da7a4ff4bb0049dc2dd225d3c5602d959a6dcbcce7330c75049  OmniVoice Studio.app.tar.gz
3845c8a23fc79b8025cd8e3a6b8766901c0d1928ef6e0569e0ee6c25b63a541c  OmniVoice Studio.app.tar.gz.sig

Windows x64 artifacts

d6d407fb26ce2aa7c474909d6cbce236daa044a56e258c46681296ef9c968d00 *OmniVoice Studio_0.4.1_x64_en-US.msi
011c4c8e9c58bf2de3b06a3a76df26718b5c6f0ecb168bd3d495c3b334952e96 *OmniVoice Studio_0.4.1_x64_en-US.msi.sig

macOS Intel artifacts

91fd008c1bbd60b2f665ef7836a326c1756fee5b0cf3db15b9c845d249431f0b  OmniVoice Studio_0.4.1_x64.dmg
84a8b1ac1da95ecdfb1c0be08cb5a4e57ca5cead3e0a14a416caf50e15aec6d7  OmniVoice Studio.app.tar.gz
82e6bb094852c15ebfae54f45c22ac4185d36bd398cf52ac3e1e1c73cf0b26ca  OmniVoice Studio.app.tar.gz.sig

Contributors

Thank you all 💜

@debpalash @paoloantinori

v0.4.0 — OmniVoice Studio

Choose a tag to compare

@github-actions github-actions released this 21 Jul 01:43

Highlights

  • Audiobooks, end to end — a real Stop with live per-chapter progress, a multi-voice cast, expressive controls, a markup toolbar, live stats, and a one-click sample
  • Pick a designed voice from the Gallery anywhere you choose a voice — audiobook, Stories, and Dubbing
  • Dub Paste Translation — drop in a translation or .srt and it maps straight onto your segments, timings intact
  • Downloading a finished audiobook no longer hijacks the app — it just saves
  • First run is ~2.4 GB, not ~5 GB — only the TTS model is required; ASR picks are curated per platform
  • Guided mic + Accessibility permissions with Open Settings deep-links; Parakeet TDT v3 on Apple Silicon
  • Opens in your system language, with a one-tap switch back to English
  • Security: server-mode admin routes can't be reached by a trusted-network client without the API key
  • A render error shows a recoverable card instead of a blank window; queued and long generations stop failing with a bogus "too heavy for your hardware"

Changed

  • Settings → Models: grouped catalog (TTS / ASR / Dictation / Diarisation), "recommended for this machine" chips, incompatible models collapsed behind a toggle
  • Only the TTS model (~2.4 GB) is required on first run; ASR picks are curated per platform via curated_on in models.yaml (MLX on Apple Silicon, CT2+Turbo on CUDA, PyTorch on ROCm, int8 on CPU)
  • Audiobook tab tidied up: the settings column is now grouped into compact collapsible sections (Output / Book details / Pronunciation / Markup), so script + voice + Create sit up top instead of a long scroll — same controls, denser layout (#1214)

Removed

  • The Dubbing per-segment picker's hardcoded design-presets group — superseded by the richer designed-voice Gallery; already-saved preset: picks still generate identically (#1220)

Added

  • Voice picker: the designed-voice Gallery is now selectable anywhere a voice is chosen — the audiobook default voice and each Cast row can pick a gallery archetype (searchable, favourites first), and it's materialised into a real profile on pick so it just works everywhere (#1219)
  • The Stories editor and the Dubbing per-segment voice pickers now use the same gallery-enabled picker, so designed-voice archetypes are selectable there too; the dub picker drops its redundant hardcoded presets group in favour of the richer Gallery (existing picks unchanged) (#1220)
  • Audiobook tab: a Cast panel maps each [voice:NAME] in the script to a profile so multi-voice renders correctly (it previously fell back to a single voice), plus a markup insert toolbar, live stats (chapters · words · est. runtime), and pre-flight validation for unknown voices and empty chapters (#1217)
  • Audiobook tab: a Stop button that truly cancels a running generation (not just the UI) and live per-chapter progress — a bar, elapsed + ETA, and each chapter's status (rendering / done / cached / failed); finished chapters stay cached so Create again resumes. Cmd/Ctrl+Enter starts a render (#1216)
  • Settings → Permissions + wizard System Check: live mic/Accessibility grant state, per-OS guidance, Open Settings deep-links; dictation pre-flights the mic grant (#1175)
  • parakeet-mlx engine: Parakeet TDT v3 on Apple Silicon — 25 EU languages, word timestamps, ~2 GB, opt-in from Settings → Models, never auto-downloads (#1175)
  • First-run downloads race the direct GitHub path against the mirror and use whichever answers fastest (#1179)
  • First-run consent question for the existing opt-in analytics (two equal buttons, skip = no)
  • First run: when the app auto-opens in a non-English system language, a one-time, dismissible banner offers to switch the UI to English — shown only until you pick a language, never for English systems (#1215)
  • Source builds carry the publishable analytics token and get the same first-run consent ask as installers; opt-in events now note the install channel (installer / docker / source) — thanks agudmund! (#1193)
  • Official Google Colab notebook (notebooks/OmniVoice_Studio_Colab.ipynb) — full app + API feature tour on a free T4
  • ROCm Docker image ghcr.io/debpalash/omnivoice-studio:rocm (+ :stable-rocm, :X.Y.Z-rocm) (#1165)
  • OMNIVOICE_TRUSTED_NETWORKS — comma-separated CIDRs exempted from the consumption auth gates (share PIN / API key / dictation WS); admin routes stay loopback-only (#1170)
  • Info/warn system notifications are dismissible and stay dismissed across restarts; error-level notices can't be dismissed, and the unclean-shutdown notice is now acknowledged server-side — thanks agudmund! (#1192)
  • clone_voice MCP tool — AI agents can clone a new voice from a base64 reference audio sample; returns a profile_id immediately usable with generate_speech — thanks paoloantinori! (#1194)
  • Dub tab: Paste Translation — paste a translation made elsewhere (ChatGPT, DeepL, a human) as subtitles, numbered lines, or plain lines; it maps onto the existing segments with a before→after preview, keeping timings and the source transcript intact (#1203)
  • Audiobook tab: Production Overrides (position/class temperature, steps, guidance, postprocess, seed) for expressive narration, plus IndexTTS2 emotion controls and a "vary repeated lines" toggle — defaults reproduce today's renders exactly (#1208)
  • Audiobook tab: a Load sample button that fills the editor with a demo story — chapters, per-character [voice:], [pause], [slow]/[fast]/[emphasis]/[spell], and reaction tags — so first-timers can hit Create and hear every capability before their real work (#1214)

CI

  • The quiet changelog style and 21-locale key/placeholder parity are now enforced by plain pytest checks; CodeRabbit/Greptile carry the house rules via .coderabbit.yaml/greptile.json (#1198)

Docs

  • docs/expressive-speech.md: per-engine breaths/laughter/emotion control, incl. the default engine's 13 native reaction tags
  • Flush caches / Unload documented in the performance guide, incl. POST /system/flush-memory for scripts
  • README FAQ: why a longer reference clip doesn't clone better (zero-shot 15 s cap; fine-tuning is the audiobook-grade path)
  • docs/expressive-speech.md corrected so every recipe it names (breaths, temperature) is reachable in the surface it points to, including the Audiobook tab (#1208)
  • New docs/api-auth.md — one place for authenticating the local API: share PIN, API key, dictation WebSocket, and trusted networks, with curl/SDK examples and what 401/403/429 mean (#1212)

Fixed

  • Downloading a finished audiobook (or story mix) no longer hijacks the app: in the desktop WebView a plain download link to the media file made WebKit navigate the whole window to it and play it fullscreen (then the blank-window guard misfired) — downloads now go through the native Save dialog + a server-side copy instead (#1218)
  • The blank-window guard's fallback page is shown by injection rather than a data: URL the desktop WebViews refuse to navigate to, and its Reload button now returns to the app even if the window had navigated away (#1218)
  • Security (server mode): the admin routes (/system/*, /api/settings/* — RCE-class) now require the API key or genuine loopback — with an API key set and OMNIVOICE_TRUSTED_NETWORKS configured, a trusted-network client could previously reach them with no credential; the short share PIN no longer gates admin either (#1213)
  • A render error no longer blanks the whole window — a recoverable error card (Reload / Report) appears instead, and CI now builds the real production bundle so a pre-mount crash can't ship (#1209)
  • Voice-clone trimmer: the preview now plays exactly the selected region on variable-bitrate clips (it had drifted off on VBR/mis-reported-duration files by playing the original file on a different timeline) (#1210)
  • Screen readers now announce the hidden file-picker buttons (batch add, gallery import, stories import) (#1211)
  • Audiobook language selection now reaches the backend — the client had dropped the language field, and the tab's Markup reference now lists the reaction tags ([laughter], [sigh], …) that already work there (#1208)
  • A backend that fails to start now says why — exit code and error output, with actionable hints and a one-click report — instead of the evidence-free "Can't reach the local OmniVoice backend" (#1177)
  • Generation no longer crawls on CPU after a cancelled or failed dub: the TTS model is moved back to the GPU on every exit path, and each generation now verifies its own placement (#1191)
  • A generation queued behind a busy one no longer spends its timeout waiting: the budget starts when a GPU worker picks the job up, so a queued request can't be failed as "too heavy for the available compute" without having run (#1190)
  • One request's timeout no longer cancels unrelated jobs already waiting in the GPU queue (#1190)
  • Timeout messages stopped claiming capacity was restored automatically — the abandoned job keeps the device until it finishes, and the guidance now says to let it drain (#1190)
  • The length-scaled generate budget now covers every path — streaming previews, batch dubbing, /v1/audio/speech, dub and archetype previews — instead of only the two classic call sites, so long inputs stop failing at a flat 300s (#1190)
  • Provenance watermarking moved off the GPU worker pool: on 1-worker machines each embed was serializing ahead of the next generation (#1190)
  • A batch segment that times out fails the job with a reason instead of shipping a finished-looking dub with silent gaps (#1190)
  • /v1/audio/speech refuses work up front with 429 + Retry-After when the pool is saturated, and returns a retryable 503 rather than a 500 on timeout (#1190)
  • Subtitle parsing no longer stalls on a blank-line-heavy .srt: the timing-line regex backtracked across newlines, so a mis-saved export could pin an import for hours (#1203)
  • A broken ASR engine's fallback could silently auto-download...
Read more

v0.3.22 — OmniVoice Studio

Choose a tag to compare

@github-actions github-actions released this 13 Jul 21:48
0d4eb0f

The dubbing release. Dubbed videos stop sounding like a compromise: the music keeps its stereo width and full frequency range, short lines no longer leave dead air while the mouth keeps moving, one speaker stays one voice, and the language tabs finally switch the transcript with the audio. Underneath it, the memory fixes that ended the "can't reach the local backend" era on 16 GB machines ship at last — plus a sweep of never-again hardening drawn from an audit of every bug this project has ever closed.

Added

  • A "Voice match" toggle for dubbing — keep one steady voice per speaker. Each dubbed line clones from a snippet of its own original audio, which matches the delivery beautifully but can make the voice itself drift from line to line — most audibly on videos where speaker detection ran in fallback mode ("still 4 segments different in voice", as one report put it). A new control next to the Timing picker chooses: Per line (the default, unchanged) for the best per-line delivery match, or Consistent to clone every line of a speaker from one shared reference — the speaker's pooled sample, or the best single clip when none exists — for a steady identity across the whole dub. Flipping it honestly marks segments as needing regeneration, and the shared reference is encoded once and reused, not re-studied per line. (#1147)

  • A performance guide, at last. docs/performance.md explains where generation and dubbing time actually goes, the three classic causes of "it got slow" (an empty Transcript field on a voice profile chief among them), every tuning knob the backend reads — none of which were documented anywhere — and which settings to leave alone (raising OMNIVOICE_GPU_WORKERS on a small GPU is how you get the crash the default exists to prevent). Includes how to run the built-in profiler so a slowness report can carry numbers instead of vibes.

  • In-app analytics is now wired end to end — and still off until you say yes. The frontend analytics SDK is only ever started after you opt in (Settings → Privacy), never at app launch, so a default install still transmits nothing. Two of the SDK's defaults are explicitly disabled because they would be actively harmful here: autocapture, which sends the text content of whatever you click — in this app, the script you are about to synthesise, your voice names, your file names — and session recording, which records the screen. Events carry metadata only, filtered through the same allowlist as the backend, so no future change can leak your content by adding a field.

  • Opt-in analytics — off by default, and it can't lie to you. OmniVoice still sends nothing out of the box: no accounts, no telemetry, no phone-home, and your text, audio, voices, and projects never leave your machine regardless of what you choose. There is now one toggle in Settings → Privacy → "Help improve OmniVoice", off unless you turn it on. If you do, it sends anonymous usage stats — which engine and language you used, how long a generation took, how many characters the text had (a number, not the text), and the type of any error. It never sends the text you type, your audio, your file names, your voice names, or anything identifying you. That isn't a promise in a policy: an allowlist in the code drops any property that isn't on it, so a future change can't leak content by accident, and crash tracebacks are deliberately not auto-captured (they can carry file paths and tokens). Turning it off stops everything immediately. Builds from source have no analytics destination at all and don't even show the toggle.

  • Settings → Usage: see what you've made, counted entirely on your own machine. Takes generated, audio produced, voices, days used, and a breakdown by mode and language — all computed from the history already in your own database. It collects nothing new, stores nothing new, and transmits nothing anywhere, no matter what you've chosen under Settings → Privacy: this panel is yours, it works with analytics switched off, and it never phones home. If you want to know what you've been making, the answer shouldn't require sending it to anyone.

  • The memory panel now tells the whole truth. Settings → Models (and GET /model/loaded) used to report only the OmniVoice core model — a resident second engine like MLX-Audio, or the warm dictation model, was invisible, so the memory picture looked ~2 GB lighter than reality. It now lists every resident model (in-process engines and the dictation ASR included) and adds a system block with free/total RAM (and free VRAM on a dedicated GPU) plus a low-memory warning. On top of that, a load that starts while memory is already low leaves a breadcrumb in the backend log, so a subsequent out-of-memory kill points at the load that tipped it instead of dying silently. Advisory only — nothing is blocked (the OS can reclaim memory, and refusing a load on an estimate would brick machines that would actually cope). Tune the threshold with OMNIVOICE_LOW_MEMORY_HEADROOM_GB (default 2).

Fixed

  • Switching preview languages can't leave a mixed-language transcript. Follow-up to the tab/transcript sync: if a track's translations were only partially stored in the browser (older projects, partial regenerations), switching tabs could show German audio with a few rows still in the previous language. Missing rows now hydrate from the app's own per-language store on the backend — and a picked regional dialect is automatically cleared when you switch to a language it doesn't belong to, wherever the switch comes from. (#1149)

  • The Export step's language tabs now switch the transcript too. Clicking Bengali/German/Hindi… above the finished dub swapped the video but left the segment list showing whichever language you generated last — German audio over Bengali text. The tabs now also swap every segment's text to that language (through the same per-language store the language picker uses, so nothing is lost when you switch back); the Original tab keeps your editing language as-is, since each row already shows the original line beneath its translation. (#1148)

  • A "backend crashed" notice can no longer outlive the update that fixed the crash — and the desktop shell's self-repair paths are now pinned by tests that CI actually runs. Crash notices now record which app version wrote them, and a notice left behind by an older version is ignored and cleaned up after you upgrade instead of resurfacing as if the new build had crashed. The Windows blank-window repair (the one-click WebView cache fix after a BSOD) also gets regression tests pinning its safety contract — one attempt per request, never touches anything unasked, never blocks startup on a locked cache — and CI now runs the desktop shell's entire Rust unit-test suite on macOS, Windows, and Linux, which it previously never executed at all. (#1145)

  • The MLX-Audio phonemizer's language model now ships with the app environment instead of being fetched mid-generation. Follow-up to the pip fix: with the installer present, the first English MLX-Audio generation would auto-download a small model straight from GitHub — an outbound request that bypasses the app's mirror system (a problem on restricted networks) and fails offline. The model is now a pinned dependency of the managed environment: it arrives at install/update time through the normal dependency flow, and first generation works fully offline. (#1146)

  • The MLX-Audio engine's first English generation no longer trips over a missing installer. Its phonemizer auto-downloads a small language model on first use by shelling out to pip — which the app's managed Python environment didn't include, so the download always failed (and before the recent containment fix, took the whole backend down with it, #1133). pip now ships as a real dependency of the managed environment, so it survives app updates too — anything installed ad-hoc would have been stripped by the updater's environment sync, quietly re-breaking this after every release. (#1144)

  • A voice engine's helper library can no longer shut down the whole backend. One user's backend died 21 seconds after starting (#1133): the MLX-Audio engine's phonemizer tries to auto-download a language model on first use, the downloader is written as a command-line tool, and on failure it calls "exit the program" — which, running inside the backend, exited the backend. Any engine dependency written that way could do this. Exits are now contained at the engine-dispatch boundary and turned into a normal, explained error ("an engine dependency failed to auto-install something — see the log"), for TTS and transcription alike. The app keeps running; the failed request tells you what actually happened. (#1143)

  • Vietnamese years read like Vietnamese again. A recent release started spelling out numbers before synthesis, and its Vietnamese number library turns out to be wrong for exactly the numbers people say most — years ("2024" became "hai nghìn lẻ hai mươi bốn", which no Vietnamese speaker says). The voice model has always pronounced Vietnamese digits correctly on its own, so Vietnamese text now keeps its digits — the same conservative rule that already protected Vietnamese decimals. Also closes the loophole that made this depend on spelling: picking "Vietnamese" from the language list behaved differently from the code "vi". (#1139)

  • A voice profile's pinned seed now pins Audiobook renders too. Locking a take (or a designed voice) stores a seed so the voice performs reproducibly — and the Voice page honors it, but Audiobook/Stories renders quietly ignored it and rolled fresh randomness for every segment. Book renders with a pinned-seed profile are now deterministic end to end, matching the Voice page. And the audiobook renderer's higher generation quality (32 decoding steps — the model's own quality preset,...

Read more

v0.3.21 — OmniVoice Studio

Choose a tag to compare

@github-actions github-actions released this 12 Jul 10:08
4d2fdac

The memory release. The reason the app kept saying "Can't reach the local backend" on 16 GB machines was never really the network — the backend was quietly running out of memory and getting killed. This release fixes that at the source: the models it holds now get out of each other's way. Plus the uninstaller and factory reset grew into a proper Settings → Storage pair.

Added

  • Factory reset grew up: Settings → Storage → "Reset & remove". It used to do exactly one thing — clear your UI preferences — while the only other option was deleting everything and starting over. Between "forget my theme" and "wipe the machine" sat every reset people actually needed. Now there are four one-click tiers — UI preferences, all settings, downloaded assets & models, and everything OmniVoice did — plus a per-item checklist if you want to drop just the model weights, just a wedged sidecar engine, or just the history. Every option shows its real size on disk before you commit, and the number on the button is exactly what gets freed. Deleting voices, projects or audio asks you to type DELETE; nothing irreversible happens on a single click. "Everything" deliberately stops short of the Python environment, so you land on a working first-run screen rather than a rebuild — the app stops its engine, deletes, and starts it again for you. On macOS and Linux the model cache is the shared Hugging Face cache, so it's its own checkbox and says so; on Windows and portable installs it's OmniVoice's own, and the app doesn't pretend otherwise.

  • The Storage panels got a design. "Remove all data" and "Reset & remove" listed folders as a flat run of text, so a 7.5 GB model cache and a 391-byte config file carried exactly the same visual weight — the one thing you actually wanted to see (where the space went) was the one thing you couldn't. Every row now has an icon, a dimmed path, and a proportional bar showing its share of what will be freed, so the big one looks big. The shared Hugging Face cache is promoted out of the confirm dialog into its own "Optional" row with a checkbox, so ticking it moves the running total in front of you instead of springing a different number on you at the point of no return, and the dialog now lists exactly what is about to go.

Fixed

  • Switching TTS engines no longer stacks their models in memory. Using a second engine in a session (or a per-request engine override) loaded its model on top of the first one's, because the OmniVoice core model and the other engines live in two separate caches that never coordinated — measured on a 16 GB M2, an omnivoicemlx-audio switch left the machine holding both (footprint 3.9 GB → 4.3 GB, the ~2.8 GB core never freed). That accumulation is a direct contributor to the memory pressure behind the "Can't reach the local backend" OOM deaths. Now only one TTS engine's model stays resident: resolving an engine hands back every other resident engine first (the same omnivoice → mlx-audio switch now drops to ~1.5 GB). Steady-state single-engine use is unaffected; an A/B switch pays a re-load on the way back (~8 s for the OmniVoice core, ~1–2 s for the lighter engines). Opt out with OMNIVOICE_SINGLE_ENGINE_RESIDENT=0 if you have RAM to keep several warm. Two underlying leaks are fixed as part of this: every in-process TTS engine's unload() now actually frees its model and empties the device cache (previously all but OmniVoice were silent no-ops), and faster-whisper's unload() cleared the wrong attribute so its model was never released.

  • The backend no longer sits on ~2 GB of idle dictation model — the real reason it was being killed on 16 GB Macs. Four reports of "Can't reach the local OmniVoice backend" (#1076, #1092, #1093, #1101) all died at the same moment: during a generate, on a 16 GB machine. Measuring it showed the generate was never the problem — it costs about 116 MB. The problem was the baseline: the backend sat at ~6.2 GB even while idle. The TTS model has always been unloaded after an idle timeout, but the speech-recognition model used for dictation never was — so once you dictated a single time, ~2 GB stayed resident for as long as the app ran. On a 16 GB Mac, that plus the app, macOS, and your other programs is enough for the system to run out of memory and kill the backend, which surfaced as the "can't reach the backend" error. Dictation's model now gets the same idle release the TTS model already had, handing that memory back. The only cost is a ~1.4-second re-warm on your next dictation after a long pause, and a live dictation session is pinned so nothing is ever unloaded mid-sentence.

  • Folder sizes under 1 KB displayed as "0 KB". The uninstall panel's 391 B config folder rendered as 0 KB — which reads as "nothing here" for a folder that very much exists. The Storage panels now share one byte formatter that can say 391 B.

  • Some styling silently did nothing. A handful of components referenced CSS custom properties that were never defined (--chrome-fg-subtle, --chrome-bg-raised, --color-warning). An undefined var() makes the whole declaration invalid, so the browser drops it and the element quietly inherits — the dimmed folder paths in the Storage panels weren't dimmed at all. Fixed in those panels, and a new guard (frontend/src/test/cssTokens.test.js) fails on any bare var(--token) in JSX that isn't defined in a stylesheet or documented as runtime-injected, so a typo can't ship as invisible styling again.

Linux x64 artifacts

2b9e5ac428ad90be0662465fcff244247c9756d30223058254385a449c3ea89e  OmniVoice Studio_0.3.21_amd64.AppImage
4234981ecae54772dba76f05b7d67b823f1f79cef5882a406813400bdf7ad87a  OmniVoice Studio_0.3.21_amd64.AppImage.sig

Windows x64 artifacts

466ed828188631bc19959e1edcf753e03a892c3159699510f9917653dd8b6cd2 *OmniVoice Studio_0.3.21_x64_en-US.msi
93fa3bde043aeb4b9d7eda5f534be5dc8d8d6817f9241935d859e0e05590f40b *OmniVoice Studio_0.3.21_x64_en-US.msi.sig

macOS Intel artifacts

aa5c9e2182ec9707d0b3939278df274f4a9ddea10e87496da12e7e538b2f2855  OmniVoice Studio_0.3.21_x64.dmg
41a69a3db3c2dbdd0955ab6aa0bb63836a9358112a2f4b895fe8d65915fdf8e9  OmniVoice Studio.app.tar.gz
ebc343d107022764e230d3efe109b4977c850d25edcf283ab9c7f13603e1b833  OmniVoice Studio.app.tar.gz.sig

v0.3.20 — OmniVoice Studio

Choose a tag to compare

@github-actions github-actions released this 12 Jul 08:57
b0c692d

The follow-through release. v0.3.19 promised that "Can't reach the local OmniVoice backend" would stop firing while the backend was merely restarting — and then a user hit it anyway, on 0.3.19, because the fix had a race in it. That's closed properly here. Uninstalling also stopped being a thing only maintainers could do: it's now a button in the app, where the person who asked for it can actually reach it.

Added

  • Uninstall is now in the app: Settings → Storage → "Remove all data". The v0.3.19 uninstaller was a script — which never reached the people who needed it, since anyone who installed the .dmg / .msi / AppImage has no repo to run it from (exactly the case in #1089). The app now lists every folder this install owns with its real size, deletes them behind a typed confirmation, and quits. The downloaded model weights are a separate, opt-in checkbox, because that's the standard Hugging Face cache shared with other AI tools on your machine — removing it can delete models OmniVoice never downloaded. Custom and portable install locations are honored, and nothing outside OmniVoice's own folders can be touched. The scripts now also ship as release assets, so you can clean up without launching the app at all. (#1089)

Fixed

  • "Can't reach the local OmniVoice backend" could still fire on 0.3.19 — the fix had a hole. The app asks the desktop shell whether a start/restart is in progress before showing that error, but the shell learns of a dead backend from a 2-second poll: when the backend dies mid-generation, the supervisor needs a moment to notice it, record the crash, and flip its state to "restarting". The app was asking once, ~3 seconds in — often still hearing "everything's fine" — and dead-ending on the generic toast anyway. A failed connection contradicts "everything's fine", so that answer is now treated as stale rather than authoritative: the app keeps retrying briefly, letting the shell catch up, which turns the failure into the "backend is restarting — hang tight" banner (and gives the crash report time to be written, so you get the real cause instead of a guess). A shell that has genuinely given up, or no shell at all, still errors immediately. (#1101)

  • The uninstaller was leaving the backend's log folder behind on Linux and Windows. It cleaned the app-data, config, and Python-env folders but missed where the backend actually writes backend.log / backend_err.log~/.local/state/OmniVoice on Linux and %LOCALAPPDATA%\OmniVoice\Logs on Windows. Both the scripts and the documented path lists now cover them. (#1089)

macOS Apple Silicon artifacts

0154046993f87772b5bf9b59ec37b7c86c7165aef1d7bc1f1b739dad80f198b6  OmniVoice Studio_0.3.20_aarch64.dmg
e040ef798d57cbd53fefb32c92156be613a4fa0ba257a074d207a0376b7ebe04  OmniVoice Studio.app.tar.gz
6d88bb653fcff10bbe8ac5f52349ea77ab3a2529caca1b1d04188b64a072f1a1  OmniVoice Studio.app.tar.gz.sig

Windows x64 artifacts

6288e6d6e8b3a25bbb73fa8b3df48c710435583f30814dc741c49ef7305df7bb *OmniVoice Studio_0.3.20_x64_en-US.msi
d2cb4eea0f2f22e2e4e490419b479b7eb624107a152bf98063cdbc7d68e6ee52 *OmniVoice Studio_0.3.20_x64_en-US.msi.sig

macOS Intel artifacts

4efa7bcf171d99889fddc3b57757267bdaa34113f1560dfb80f0998e91e765b3  OmniVoice Studio_0.3.20_x64.dmg
592e4aa42ce75e62a14d359a037d8aceb89ca1dc4a2d89c4ee199e2340d6d326  OmniVoice Studio.app.tar.gz
2064e0597271f7eab2b1308efba927e2cf339ec968821a4b85ce2358bd3e1eff  OmniVoice Studio.app.tar.gz.sig

v0.3.19 — OmniVoice Studio

Choose a tag to compare

@github-actions github-actions released this 12 Jul 07:20
d7ca904

The honesty release. Every error in here was already technically true and practically useless — so this round went after the lies the app tells when something goes wrong. "Can't reach the local OmniVoice backend" no longer fires while the backend is simply still starting; a dead Hugging Face mirror no longer strands the setup wizard with advice it can't follow; and a dub that dies mid-transcription now names the actual cause instead of guessing at it. Alongside that: generated speech starts playing on the first chunk instead of the last, and there's finally a real uninstaller.

Added

  • Generated speech starts playing on the first chunk, instead of after the last one. Long text is synthesized in chunks, but you used to sit through the entire render before hearing anything. The Studio now streams the preview: audio begins the moment the first chunk is ready and the rest arrives as it renders, so a long passage is audible in about the time the first sentence takes. The take saved to your history is byte-identical to the non-streaming render — streaming is a delivery channel, not a different synthesis path — and if a stream fails mid-flight the app falls back to the classic whole-file flow with nothing half-written to disk. (#1088)

  • A clean uninstaller + a straight answer to "where's my data?" OmniVoice is fully local, so removing it is just deleting the folders it wrote — but until now users had to guess which ones. New scripts/uninstall.sh (macOS/Linux) and scripts/uninstall.ps1 (Windows) find every OmniVoice folder — app data, the multi-GB managed Python env, config, logs, and (separately, because it's shared) the Hugging Face model cache — print each with its size as a dry-run first, and delete only on --yes. They honor your custom locations (OMNIVOICE_DATA_DIR, HF_HOME, portable mode) and never touch the app binary. The complete per-platform path list lives in the new docs/install/uninstall.md, linked from the README FAQ, SUPPORT, and troubleshooting. (#1089)

Fixed

  • A dub that dies mid-transcription now says what actually happened instead of guessing. "Transcribe stream dropped before emitting any segments. Likely ASR backend failed to load" was a guess — and usually the wrong one. The backend is contract-bound to emit a terminal event on every stream even when it fails, so a stream that simply goes silent means the backend process died underneath it — on smaller GPUs, almost always a native out-of-memory abort while loading the ASR model on top of a still-resident TTS model. The app now consults the desktop shell's crash forensics and tells you that: the exit code, when it happened, a one-click "View crash details" with the captured error output, and the actual next step (free VRAM / pick a smaller ASR model) rather than "check the backend log". With no crash recorded, the original message still stands. (#1062)

  • "Can't reach the local OmniVoice backend" stopped crying wolf during startups and restarts. A real backend start or auto-restart takes 10–20+ seconds (Python spawn plus the PyTorch import), but the app's transport retry only bridged ~3 seconds — every click inside that window dead-ended with the scary toast, over and over, even though the backend healed itself moments later. The app now asks the desktop shell whether a start/restart is actually in progress and simply waits for it (up to the shell's own 2-minute restart budget), and shows a single "backend is restarting — hang tight" banner with a "back — carrying on" confirmation — the reconnecting affordance the supervisor has promised since #567. A truly dead backend (or a non-desktop deployment) still errors promptly, and the crash notice keeps telling the honest story.

  • A dead Hugging Face mirror can no longer strand the first-run wizard. When a model download failed because the configured mirror was unreachable, the error pointed at Settings — which first-run users can't open (the wizard gates the studio) — and falsely claimed the mirror setting only applies after a restart (downloads actually pick it up per call, immediately). Now the wizard shows the mirror quick-pick (including "Hugging Face (official)") right next to the failed download and retries it the moment you switch; the corrected hint says retry-first, restart only if it still fails. Two backend holes in the same flow are closed too: switching endpoints clears the "failed recently" retry cooldown (no more 429 on the immediate retry), and clearing to official also removes the legacy hf_endpoint pref, which used to silently keep the dead mirror in effect.

Changed

  • The first-run wizard shows the app version in its masthead, next to the OmniVoice Studio title — so setup-time screenshots and bug reports identify the build at a glance (the install splash already did).

  • Repo root decluttered. Retired the finished planning archives (.planning/, specs/), the pre-React design mockups (design/), the legacy research dir (research/), and stale third-party agent rules (.agents/) — ~110 files of process noise gone; everything stays in git history, and the four load-bearing engine decision docs moved to docs/adr/. Contributor-facing only; the app is unchanged.

Linux x64 artifacts

4aae088250f48d6da432ea10483875ccf26647b60be67de65cfebf465cc6622b  OmniVoice Studio_0.3.19_amd64.AppImage
0fada05ba551b7a2f325fd9ad132f1c48dcf13ee8c6e005120410443a2eb218c  OmniVoice Studio_0.3.19_amd64.AppImage.sig

Windows x64 artifacts

373a7eace6dd9ae279f5ccadfe681dd5beb1b1144981a5ca38cf44e4d1954ef0 *OmniVoice Studio_0.3.19_x64_en-US.msi
3b2083d13093031137e46f46693b5851b01d13cdf9c111d7eecf1aae32ca5c6f *OmniVoice Studio_0.3.19_x64_en-US.msi.sig

macOS Intel artifacts

70499c162e027395894b8a4f0c959e69a926f1a660036a2c552fe106dd69e789  OmniVoice Studio_0.3.19_x64.dmg
586bdb50baf290476bfdc011d6f1a8f2355d919d8aff8b342027fdebe2ff8d93  OmniVoice Studio.app.tar.gz
570c608c81e67ca975f6a90ec07ad3c2336e1b0daa71e1393149944bff278f92  OmniVoice Studio.app.tar.gz.sig

v0.3.18 — OmniVoice Studio

Choose a tag to compare

@github-actions github-actions released this 11 Jul 20:44
2a22952

The self-sufficiency release. Two long-standing "works on my network / works after four terminal commands" walls came down: model downloads now find a reachable Hugging Face endpoint on their own (no more restricted-network first-run dead-ends), and IndexTTS-2 — previously the only engine that demanded a manual clone-venv-install ritual — installs itself with one click. Under the hood, a test-debt sweep hardened the suite that guards all of it.

Added

  • IndexTTS-2 installs itself now — one click in Settings → Engines. The emotion-controlled cloning engine used to demand four terminal steps (clone the repo, create a venv, uv pip install, set an environment variable); the row now has an Install button that does all of it — source fetch (git, with a no-git tarball fallback), an isolated venv that keeps its transformers<5 away from the app, the ~6 GB model weights (via your configured/auto-selected Hugging Face endpoint), and configuration — with step-by-step progress, a disk-space check before anything is written, and resumable repair if anything is interrupted. The engine is usable the moment the job finishes, no restart; existing manual installs are detected and left untouched, and the manual steps remain as a collapsible fallback. The provisioner is parametrized so future sidecar engines (MOSS-v1.5, dots.tts, Confucius4) can reuse it. (#1083)

  • Model downloads now find a reachable Hugging Face endpoint on their own. On networks where huggingface.co is blocked or slow (the class of first-run dead-ends behind #984), the app quietly probes the official endpoint and the hf-mirror.com community mirror, picks whichever actually works, remembers the choice, and re-checks only when a download fails or the pick goes stale — so a restricted-network first run reaches a working voice instead of a wall of connection errors. Anyone who already set a mirror (env var, pref, or Settings) stays exactly where they pointed: explicit choices are never auto-switched, and Settings → Models → Hugging Face mirror now shows the automatic pick with its measured latency plus a "Test again" button. Probes only touch the two download hosts — no geo-IP, no telemetry — and every download stays checksum-verified by huggingface_hub regardless of endpoint. (#1082)

Fixed

  • Concurrent settings writes can no longer drop each other. Two parts of the app saving preferences at the same moment (say, an engine install finishing while you change a setting) could silently lose whichever save landed first; preference writes are now serialized, with a regression test. Found and fixed as part of the IndexTTS-2 installer work. (#1083)

CI

  • Test-suite debt sweep. Exports coverage (26 new tests, which caught two real router bugs), fp16 default-dtype leak instrumentation, and a suite-order pollution class root-caused at its source — the checks that guard every release got stricter. (#1081)

Windows x64 artifacts

f7d26a94af61fad908c21adb9da8f63196f8de58bdd4900562c09b0838c11348 *OmniVoice Studio_0.3.18_x64_en-US.msi
d05d99953b477ab59271b4671b91665bf40802bb9b33e27e29ff51cbf80c83a0 *OmniVoice Studio_0.3.18_x64_en-US.msi.sig

Linux x64 artifacts

f83cc7bd935ebabfba77872da0290fd91863d9ae74d65948bcb3d1742332a465  OmniVoice Studio_0.3.18_amd64.AppImage
aee0e0df4c01032b3bd0bd07a16867ac9556dad179a6095bc921f5ff5efee862  OmniVoice Studio_0.3.18_amd64.AppImage.sig

macOS Intel artifacts

0f6191a23650030feee045f8aa7290d21b7f3f4689e53f4cbc3ae0ff21c927cc  OmniVoice Studio_0.3.18_x64.dmg
1eef1bba602e593306e1da2d0b4a52e8e8aa5a96c3cce523489611d58aa8deb7  OmniVoice Studio.app.tar.gz
1961333bd38990ccc78ad110e74d6ba5e16161d725fe4e2bed12be3ecb4e4c43  OmniVoice Studio.app.tar.gz.sig

v0.3.17 — OmniVoice Studio

Choose a tag to compare

@github-actions github-actions released this 11 Jul 16:58
254f071

The polish release. The dubbing workspace can no longer trap you — an interrupted dub session used to relaunch into an eternal spinner that even reinstalling couldn't clear (thank you @nanai97 for the screenshot that cracked it). A 58-finding audit of every Settings panel got fixed end to end, FFmpeg and yt-dlp stopped being your problem (the app provisions its own, with a new Audio tools panel when you want control), the Engines and Models pages went compact and tabbed, the launcher stopped trusting half-dead backends, and the app finally opens at 100% scale.

Added

  • FFmpeg, FFprobe, and yt-dlp stopped being your problem. The setup wizard no longer lists them as system requirements with "brew install" homework — the app provisions them itself: shipped installs already bundle them, and when nothing is found the backend downloads its own checksum-pinned static build in the background, showing a single actionable card only if that fails. A new Settings → Audio tools panel gives back the control: per-tool version and origin (App package / Bundled / System / Custom), update / use-system / choose-file / restore-bundled — and one-click yt-dlp updates that survive app upgrades, because video-site support changes faster than releases. Install docs updated to match. (#1071)

  • The Engines and Models pages got compact and tabbed. Engines is now one section with TTS / ASR / LLM tabs; every engine is a strict two-line, fixed-height row with truncated text and aligned status / GPU / isolation / action columns, so the whole engine list fits one screen — details like "Why unavailable?" expand below the row instead of stretching it. Models rows tightened the same way. (#1072)

  • The Engines and Models pages got a full readability-and-features pass. Every engine row now carries a small identity mark and honest capability badges (voice cloning, device routing with the reason on hover, sidecar isolation), and engines that are ready-but-have-advice finally say so — upgrade hints used to be dropped before reaching the UI. The model store gains a filter, disk-space context next to downloads, "in memory — safe to unload" indicators, copyable setup snippets for opt-in engines, and empty states that tell you what to do next. (#1058)

Fixed

  • The app no longer attaches to a "zombie" backend that looks alive but fails everything. If a backend process survived while its install was replaced or deleted underneath it, it kept answering health checks from memory — so the next launch attached to it and every real request failed with a confusing access-control error. The launcher now runs a deeper probe (an endpoint that actually touches the database) before attaching, and replaces any backend that fails it. The local dev/test scripts also now terminate running instances before wiping data, which is how this state was produced. (#1077)

  • The app opens at 100% scale by default. New installs rendered everything at 130% zoom, which read as oversized on typical displays. Fresh sessions now start at native size; if you already picked a scale in Settings → Appearance, your choice is kept. (#1074)

  • The app no longer relaunches into a dead "generating" dub session — the blank-pane-and-spinner trap. The saved dub session was restoring its in-flight state verbatim: quit (or crash) while a dub was generating and every subsequent launch waited forever for work that died with the process — and reinstalling couldn't clear it. Interrupted sessions now reopen on the segment editor with all your work intact (or the upload screen if nothing was transcribed yet). Thanks to @nanai97 for the screenshot that told the whole story. (#1067)

  • A 58-finding audit of every Settings panel, fixed end to end. Highlights: the About page linked to the wrong project's GitHub; Arabic rendered left-to-right (RTL wiring was missing); a saved proxy could never be cleared after a reload; the HF-mirror and refinement panels vanished entirely when the backend was down; "Test now" on the HF token served five-minute-old cached results; factory reset only cleared part of what it promised; pronunciation previews ignored language-scoped entries; the hotkey recorder swallowed invalid presses in silence; Settings search could strand you with an empty sidebar — plus first component tests for previously untested panels, full i18n for five all-English panels, accessible names across inputs, confirmed destructive actions, deep links instead of dead-end advice, temp-file reclaim, and log-sharing workflows. (#1059, #1060, #1061, #1063, #1064)

macOS Apple Silicon artifacts

f8b730ab27870b6be781e76c690b7fe406c5b446e7542a8f466e6669b2919ad1  OmniVoice Studio_0.3.17_aarch64.dmg
efed3a908b6b0c23d2494f5026c3801ca539a908e753d7281819d1f973e17c8b  OmniVoice Studio.app.tar.gz
7a2eedf59ae3e5f38c6a08f186a462c9fff359251ae3ca0274970bcb4be58910  OmniVoice Studio.app.tar.gz.sig

Windows x64 artifacts

8216073abd0ca67db5eb462f06d821385b63542a06dc357db2d580ae5f1a46ac *OmniVoice Studio_0.3.17_x64_en-US.msi
defee37952fa6be4de905a2c764c917de5e8e3a6c1c0736d8ce8b7d2c6bcf92d *OmniVoice Studio_0.3.17_x64_en-US.msi.sig

macOS Intel artifacts

360ef5ba7dd1083d7e9f8e4a1becce05f1e3df18c371497c1c529c2e07d87316  OmniVoice Studio_0.3.17_x64.dmg
3742437396bf5a651f9c113c6a66b06e4c40d6821d547e6b5219562907b9fcb5  OmniVoice Studio.app.tar.gz
a30031606f1f42e5252c32a329209d107613f83f3e3265cc2ce91c82500bf939  OmniVoice Studio.app.tar.gz.sig

v0.3.16 — OmniVoice Studio

Choose a tag to compare

@github-actions github-actions released this 10 Jul 19:37
55c40be

The quality release. Three long-standing frictions got structural fixes: regenerating no longer destroys good takes (a takes rail with starring and restore), audiobooks stop redoing finished work (per-sentence caching — edit one line, re-render one line; crashes resume where they stopped), and dub translations stay consistent and fit their timeline (auto-glossary + a naturalness pass, plus fit prediction before any GPU time is spent). Under the hood, every text path now speaks numbers, times, and abbreviations correctly, the VoxCPM2 engine gained upstream-alignment guards, and a Windows first-run breaker — model downloads completing but the cache ending up with broken file links — now self-heals automatically. Thank you @dmnobunaga for the razor-sharp diagnosis on that last one.

Fixed

  • Windows: model downloads that finished but wouldn't load now repair themselves. On machines without Developer Mode, the model cache could end up with all its multi-gigabyte files downloaded but the snapshot's file links broken — and the app reported a misleading "does not appear to have a file named model.safetensors". The app now detects the broken links on load failure, restores just the missing pieces (reusing everything already downloaded, and falling back to real file copies where links can't be trusted), and retries once; if repair is impossible, the error finally names the actual cache folder to delete. Root-caused in the wild by @dmnobunaga — thank you. (#1056)

  • VoxCPM2: cloning reference clips are now conditioned, and outputs lose their silent tails. Reference audio used to reach the model completely raw; it now gets edge-silence trimming and a 30-second cap (fail-open — short clean clips pass through untouched), and generated audio gets a trailing-silence trim. The install hint also moved to voxcpm>=2.0.3, which carries an important Apple-Silicon audio-quality fix — older installs keep working and see an upgrade hint in the logs. (#1055)

  • Streaming TTS requests without an emo_alpha field no longer crash. A minimal /ws/tts request hit a KeyError and returned an error frame instead of audio — found while giving that route its first tests. (#1054)

  • Long generations no longer risk a multi-gigabyte memory spike while being watermarked. The invisible watermark (on by default) pushed the entire waveform through AudioSeal in a single call, and its memory use grows with audio length — a multi-minute generation demanded a single ~2 GB allocation, enough to fail outright on a 16 GB machine already holding a model ("DefaultCPUAllocator: not enough memory"). Watermark embedding — and the Verify-audio detector, which had the same flaw with uploaded files — now processes audio in ~30-second chunks, so peak memory stays flat no matter how long the audio is. Detection also got sharper for spliced files: it now reports the strongest chunk instead of a whole-file average. (#1045)

  • The ⊕ Insert token list no longer climbs out of the viewport. In the voice-clone script panel, the insert popover (expression tags, CMU phoneme chips) always opened upward from the textarea — and since that input sits at the very top of the panel, the list disappeared past the top of the window with no way to see or scroll it. It now opens below the input, where there's always room. (owner-reported)

Added

  • Edit one sentence, re-render one sentence. Audiobook and Stories renders now cache every synthesized sentence individually (content-addressed, under the existing chapter cache): fixing a single line in a chapter reuses all the untouched audio, and an interrupted render — crash, quit, power loss — resumes from the sentences that already finished instead of redoing the whole chapter. One byte cap bounds both cache layers, and chapter caches from released versions keep working. (#1048)

  • Numbers, times, and abbreviations are spoken correctly in every engine. A conservative normalization pass now runs before TTS everywhere (Studio, dubbing, audiobooks): "3:30" is read as a time, "2" as "two" (29 languages), "Dr." as "Doctor" — while stray control characters and markup remnants that trigger engine hallucinations are stripped. Deliberately cautious: when a rewrite could be wrong, the text is left alone, and your pronunciation-dictionary entries always have the final say. Toggleable (text_normalization_enabled, default on). The OpenAI-compatible API, streaming TTS, and the batch queue run the same pass, so every door into the engines speaks text identically. (#1049, #1054)

  • Dub translations stay consistent and sound natural (LLM engine). Before translating, one pass over the whole transcript builds a terminology glossary (your manual glossary entries always win) that rides along on every segment, so names and terms stop drifting mid-video. After each segment's direct translation, an optional reflect pass critiques and rewrites stiff lines into natural spoken dialogue — any failure silently keeps the direct translation. Both toggleable in the Dub tab; the reflect toggle states its 3-calls-per-segment cost. (#1050)

  • The Dub tab now predicts which lines won't fit — before wasting GPU time on them. After translation, each segment gets a duration estimate (self-calibrating to your engine and language from the segments already rendered) and a "Tight fit" or "Won't fit +Ns" badge when the dubbed audio can't match the timeline even with speed-up. An opt-in "Suggest shorter lines" option asks the LLM for a meaning-preserving shorter rewrite you can apply per segment — never applied automatically. (#1051)

  • Generation takes: star the good ones, restore any of them. Regenerating no longer means losing the previous result — recent takes appear in the workspace history with replay, star/unstar, and one-click restore as the active output. History is now capped (Settings → Storage, default 200 takes): the oldest unstarred takes are pruned, starred ones are kept forever, and an audio file is only deleted when nothing else references it. (#1052)

  • A persistent mini-player for all the audio that used to play "invisibly". Generated output, voice-profile and dub-segment previews, story lines, Gallery voices, and Projects renders all played through a bare audio pipe — no waveform, no seek, no time, and (until v0.3.15's stop pill) no way to stop them. A slim player bar now docks above the Logs footer whenever such audio plays, on every page: live waveform (decoded once from the audio already in memory — nothing is re-fetched), click/drag/keyboard seek, play/pause, elapsed/total time, what's-playing label, and a stop button. It replaces the stop-only pill, and because it's part of the app's layout rather than a floating overlay, the pill's "covers the Production Overrides row at 1440×900" overlap class can't come back. Stories line previews also route through it — which makes them stoppable and fixes them being silent on the macOS/Linux desktop builds (their old playback path used blob: URLs, which WebKit refuses to play). (no issue — owner request following #1032's stop-pill band-aid)

Windows x64 artifacts

1e1c49bb74852df72555e4e54e9d4b3d39032a9bd9be82a204c1ffa3f4a3af7e *OmniVoice Studio_0.3.16_x64_en-US.msi
ca2422ff2f1a2eb6c63ca134c7982cf59926ebbb62be141a7aa1bf8f4aab259e *OmniVoice Studio_0.3.16_x64_en-US.msi.sig

macOS Apple Silicon artifacts

654fe9bcc150e871d27bc2b276f55c7f1bea103ccbb40cb28f72c80112a1b7a9  OmniVoice Studio_0.3.16_aarch64.dmg
9d8c613ce41de0a13fa4745fa3e5b46c4e54693d46fceb9ef659eeb2ee371f00  OmniVoice Studio.app.tar.gz
b30af332691711dfe9739bda51ad8242fb89744c89a3899be6bfaeea17ffda0c  OmniVoice Studio.app.tar.gz.sig

macOS Intel artifacts

77a47387c69533e07c3be806924c7b5d8afbd09da2ac7f67937aff1be147bdb1  OmniVoice Studio_0.3.16_x64.dmg
75dd3a032bdb15c388e78a2791e9396ac7b45bbc9d635bb51ac998c7c11acca9  OmniVoice Studio.app.tar.gz
ba8c309a2c2768a27cd8fe3546eaa02d7203da2fa380874bf0ca1e8733d64663  OmniVoice Studio.app.tar.gz.sig