Skip to content

fix(voxcpm1): fix webui download failure and Yue lang mis-triggering issues - #424

Merged
0xShug0 merged 2 commits into
0xShug0:mainfrom
jasonchen31:dev-fix-voxcpm1-webui-and-yue-lang
Sep 3, 2026
Merged

fix(voxcpm1): fix webui download failure and Yue lang mis-triggering issues#424
0xShug0 merged 2 commits into
0xShug0:mainfrom
jasonchen31:dev-fix-voxcpm1-webui-and-yue-lang

Conversation

@jasonchen31

Copy link
Copy Markdown
Contributor

Summary

  1. Fixes WebUI download failure from audio-cpp/audio.cpp-gguf and
  2. Cantonese mis-trigger on Traditional Chinese. Combines

Root cause

  1. WebUI download - model_specs/voxcpm1.json:251 used voxcpm1_0.5b_q8_0 containing . which is rejected by app/server/model_installer.cpp:49 valid_package_id() (only [A-Za-z0-9_-], 128 chars). webui/native/src/lib/api.ts:72 -> POST /v1/ui/models/install forwards the id verbatim, so src/framework/package_manager/manager.cpp:490 PackageManager::install() is never reached. tools/model_manager_v2.py:148 has no dot check, so CLI succeeded - appears as WebUI-only failure. voxcpm1 was the only package in model_specs/*.json with ..
  2. Traditional Chinese - voxcpm1 lacked Traditional->Simplified normalization. Tokenizer treats many Traditional codepoints as Cantonese-correlated, so 發財 without language=yue rendered with Yue voice. Same bug previously fixed in audio8_tts:0eec2be.

Changes

3407c74 - rename voxcpm1_0.5b_q8_0 -> voxcpm1_0_5b_q8_0 (aligns with qwen3_tts_0_6b, soprano_1_1_80m)

  • model_specs/voxcpm1.json:229 recommended_package
  • model_specs/voxcpm1.json:251 packages[0].id
  • webui/configs/models_catalog.json:20 download_id for voxcpm1
  • docs/community_models/voxcpm1.md:24,153 CLI example + package table

Remote file unchanged: VoxCPM1-GGUF/voxcpm-0.5b-q8_0-audiovae-f16.gguf (847888032 bytes, audiocpp.embedded_files/audiocpp.model_spec.json verified via Range fetch, audiocpp.embedded_files.names contains config.json/tokenizer.json). GGUF already embeds sidecars, so single-file huggingface_snapshot remains valid.

bc36c6d - port audio8_tts:0eec2be to voxcpm1 (cherry-picked fix_tokenzier/audio.cpp:2d6101df)

  • src/community_models/voxcpm1/session.cpp:4 + #include "engine/framework/text/chinese_variant.h"
  • src/community_models/voxcpm1/session.cpp:148 add extract_request_language() (text_input.language -> voice.style.language -> language/lang option) - mirrors audio8_tts:313
  • src/community_models/voxcpm1/session.cpp:281 offline: language = extract_request_language(request), maybe_convert = maybe_convert_traditional_to_simplified_opt(text, language), convert prompt_text/reference_text + converted_request.text_input.text before chunk_text_request (so word-budget operates on converted text)
  • src/community_models/voxcpm1/session.cpp:392,465 streaming: same extract + convert prompt_text and streaming_text before generate_streaming
  • Keeps Traditional only for yue/cantonese/zh-HK/zh-MO, otherwise converts via shared engine::text::chinese_variant (TSCharacters 3222, src/framework/text/chinese_variant.cpp + chinese_variant_data.inc, built via CMakeLists.txt:380 already in main)

References

  • src/community_models/audio8_tts/session.cpp:477,504, include/engine/framework/text/chinese_variant.h:1, src/framework/text/chinese_variant.cpp:1

jasonchen31 added 2 commits September 3, 2026 02:56
Package id voxcpm1_0.5b_q8_0 contains '.' which is rejected by
app/server/model_installer.cpp:valid_package_id() (only [A-Za-z0-9_-]).
The WebUI install path (webui/native/src/lib/api.ts -> POST
/v1/ui/models/install) forwards the id verbatim, so the native C++
PackageManager never receives the request and download from
audio-cpp/audio.cpp-gguf appears to fail, while
tools/model_manager_v2.py (no dot check) succeeds.

Rename to voxcpm1_0_5b_q8_0 to match repo naming convention
(qwen3_tts_0_6b, soprano_1_1_80m) and unblock validation:

- model_specs/voxcpm1.json: recommended_package + packages[0].id
- webui/configs/models_catalog.json: download_id for voxcpm1
- docs/community_models/voxcpm1.md: CLI example and package table

Remote file name voxcpm-0.5b-q8_0-audiovae-f16.gguf unchanged;
GGUF already embeds config/tokenizer sidecars, so single-file
huggingface_snapshot install remains valid.
Port audio8_tts OpenCC fix (0eec2be) to voxcpm1 to avoid Cantonese
mis-trigger on Traditional input without yue language. Uses shared
engine::text::chinese_variant (TSCharacters 3222) and keeps
Traditional only for yue/cantonese/zh-HK/zh-MO.

- src/community_models/voxcpm1/session.cpp: add
  extract_request_language() (text_input.language -> voice.style.language ->
  language/lang option), maybe_convert_traditional_to_simplified_opt
  for prompt_text/reference_text and TTS text before chunking
  (offline) and before generate_streaming (streaming)
- Mirrors src/community_models/audio8_tts/session.cpp:477,504

Fixes voxcpm1 rendering Traditional "發財" as Cantonese when no
language is specified; yue/cantonese/zh-HK/zh-MO preserves Traditional.
@0xShug0
0xShug0 merged commit a088f90 into 0xShug0:main Sep 3, 2026
6 checks passed
@0xShug0

0xShug0 commented Sep 3, 2026

Copy link
Copy Markdown
Owner

@jasonchen31 Good catch! PR merged.

CryptVenture added a commit to CryptVenture/audio.cpp that referenced this pull request Sep 3, 2026
60 of the 85 catalog entries name a download_id that is not a packages[].id, a
path no package installs into, or both: 46 unresolvable ids and 14 paths that
are not the package's target_directory. They resolve only through a
compatibility shim in catalog.ts that strips precision suffixes and guesses;
where the guess fails the entry offers no install button at all.

Each entry now names the package that entry already meant and the directory
that package installs into:

  - download_id is an exact packages[].id from the entry's own family. Where
    the old id was a stem ("omnivoice", "chatterbox"), it becomes the family's
    recommended package. Where it named a variant ("qwen3_tts_1_7b_custom_
    voice", "dots_tts_mf_q8_0"), the variant is preserved and only the
    spelling is corrected to the published id.
  - path is models/<target_directory> of that package. 40 entries pointed at
    pre-GGUF directories that no package writes ("models/chatterbox" ->
    "models/Chatterbox-GGUF"), and several pointed at a single .gguf file
    inside the directory, which only resolves when that exact filename ships.
  - Three entries resolved to safetensors packages the native manager cannot
    install, so they had no install choice; they now use their family's
    recommended GGUF package.

No entry is added, removed or retasked here, and display names, tasks, modes
and min_vram_gb are untouched. The voxcpm1 download_id fixed in 0xShug0#424 is left
as it is.

Validation:
  - Entries whose download_id is not a packages[].id, or whose path is not
    that package's target_directory: 60 before, 0 after.
  - No path is targeted by more than one download_id, so a catalog install
    leaves one package per directory.
  - tools/check_loader_catalog_sync.py reports loaders, model_specs and
    model_manager_v2 in sync.
  - Directory paths load exactly as the file paths they replace. Same server,
    same input, audiosr registered twice:
      models/AudioSR-GGUF                        200
      models/AudioSR-GGUF/audiosr-basic-f32.gguf 200
    identical response fields from both.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ATa5YkLUPMDPRL7w1gCo9p
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants