Skip to content

Add WebUi (Adopted from https://github.com/kigner/audio.cpp-webui, add support for Linux) - #87

Merged
0xShug0 merged 8 commits into
0xShug0:mainfrom
patrickjchen:webui/gradio-ui-i18n3
Jul 21, 2026
Merged

Add WebUi (Adopted from https://github.com/kigner/audio.cpp-webui, add support for Linux)#87
0xShug0 merged 8 commits into
0xShug0:mainfrom
patrickjchen:webui/gradio-ui-i18n3

Conversation

@patrickjchen

@patrickjchen patrickjchen commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

i18n:
- Adopt webui/ui_i18n.py:English/Simplified/Traditional all now come from one source.
- Default to English (was Chinese) and reorder the picker to match.
- AUDIOCPP_LANG supplies the default only when nothing has been picked in the
UI yet; a saved pick wins, so a stale env var can't defeat the picker.
Accepts the spellings people actually write (zh_TW, zh-CN, english, ...).

Linux:
- Re-apply EXE_SUFFIX / SERVER_EXE_NAME / SERVER_LAUNCHER and the from-source
build discovery (_cmake_cache_backend, _discover_dev_bin_dirs), which also
fixes _find_gguf_exe: upstream hardcoded build/windows-*-release, so it
could never find a Linux converter build.
- ffmpeg lookup and the "gguf converter not found" messages no longer name
.exe unconditionally.
- requirements.txt: mark pywin32 and the pythonnet/pywebview stack
sys_platform == "win32" so the file installs on Linux.

@0xShug0

0xShug0 commented Jul 21, 2026

Copy link
Copy Markdown
Owner

Thank you @patrickjchen. The changes to model manager in this PR may break existing CI/Nix flows. Could you tentatively create a dedicated model_manager.py for the UI so the existing one stays stays lightweight and focused on the framework installer/catalog? The manager for UI can be in the webui dir, which will make the UI self-contained.

CodingNinja2020 and others added 8 commits July 21, 2026 12:26
The WebUI comes from kigner's fork and is the bulk of the logic here:
https://github.com/kigner/audio.cpp-webui.git (merged at 8924917). It is a Gradio
UI over audiocpp_server that loads one model at a time on demand, with model
management, background downloads, per-family request profiles, VRAM budgeting and
adaptive chunking for TTS/ASR/VC, and a dialogue mode that chains diarization into
ASR. All of that is kigner's work and is carried over as-is.

That fork targets Windows only and its interface is Chinese only. What this commit
adds is the cross-platform and localization work on top:

Cross-platform:
- Resolve the server binary by OS convention (.exe only on Windows) instead of
  assuming audiocpp_server.exe, and name run_server.sh/.bat per platform in the
  messages that mention it.
- Find from-source builds in either layout: build/<os>-<backend>-<type>/bin, where
  the backend is in the directory name, and a plain `cmake -B build` -> build/bin,
  which says nothing about the backend and is classified from its CMakeCache
  (GGML_CUDA:BOOL=ON). Without the second, a stock Linux dev tree found no binary
  at all and SERVER_EXE pointed at a path that did not exist.
- Add run_webui.sh as the POSIX counterpart of run_webui.bat.

Localization, English first:
- Strings move to webui/locales/<lang>.json, chosen by AUDIOCPP_LANG (default en)
  or the language picker in the UI. en.json is the per-key fallback, so a partial
  translation degrades to English rather than showing raw keys, and an unknown or
  malformed locale warns and falls back instead of taking the UI down. Adding a
  language is dropping in a file. zh.json keeps the fork's original Chinese.
- Catalog entries hold English display_name/input_hint; a locale overrides any of
  them via catalog.<id>.<field>, which is how zh.json restores the Chinese model
  names. Without this the catalog's own strings leaked into the English UI.
- t() applies str.format only when given arguments, so a translation can reorder
  placeholders, and a bad one falls back rather than raising.

The picker switches language in place. Gradio bakes each label in when it builds
the Blocks tree and cannot rebuild it in another language, so switching means
re-labelling every component: a registry maps each component property back to the
locale key that produced it, and the handler turns that into one update each.

The registry is derived rather than declared. Every localized string already goes
through t(), so a component's English text identifies its key by reverse lookup,
keeping ~120 call sites free of registration boilerplate. Two cases reverse lookup
cannot see, and how they are handled:
- Interpolated labels never match their template ("Model list (task=tts)" vs
  "Model list (task={task})"), so they register explicitly via i18n_register().
- Several keys sharing one English string are ambiguous; _english_key_index()
  checks whether any locale translates them differently and drops those, leaving
  the component on its current label rather than risking the wrong one.

Switching is process-wide, not per session: Gradio serves one Blocks object to all
connections, which suits a local single-user tool. Values the server parses stay
English while their labels localize, and the TTS/Voice Design sample texts are
only re-localized while untouched, so a switch cannot discard typed input.

Gradio's own widget text ("Click to Upload", ...) is compiled into its frontend
bundle and picked from the browser locale, so it follows the browser rather than
this picker and is left alone; the README says so.

Fixed while localizing:
- Two loops named their variable `t`, shadowing the translator for the rest of
  their scope.
- The ASR language list built labels as "<localized> <English>", which read as a
  stutter once the localized name was itself English ("Chinese Chinese").

Comments and docstrings in webui.py are still Chinese and are left for a later pass.

model_manager: fetch HF files via huggingface_hub, kigner's fix. Xet-backed repos
redirect to a CDN that rejects plain GETs against the resolve URL, so only the hub
client can pull their weights.

Co-Authored-By: kigner <aidiscovery2045@proton.me>
The upstream author (kigner/audio.cpp-webui) rewrote the i18n layer and added
~1200 lines of features since our fork point. Their scheme is inline
_t(zh, en) calls with Traditional Chinese generated from the Simplified source
by OpenCC, which is mutually exclusive with our locales/*.json key lookup.
Take theirs as the base and re-apply our Linux work on top, rather than hand-
porting every new string into a locale file.

i18n:
- Adopt webui/ui_i18n.py; drop webui/locales/{en,zh}.json and the t()/registry
  code they fed. English/Simplified/Traditional all now come from one source.
- Default to English (was Chinese) and reorder the picker to match.
- AUDIOCPP_LANG supplies the default only when nothing has been picked in the
  UI yet; a saved pick wins, so a stale env var can't defeat the picker.
  Accepts the spellings people actually write (zh_TW, zh-CN, english, ...).

Linux:
- Re-apply EXE_SUFFIX / SERVER_EXE_NAME / SERVER_LAUNCHER and the from-source
  build discovery (_cmake_cache_backend, _discover_dev_bin_dirs), which also
  fixes _find_gguf_exe: upstream hardcoded build/windows-*-release, so it
  could never find a Linux converter build.
- ffmpeg lookup and the "gguf converter not found" messages no longer name
  .exe unconditionally.
- requirements.txt: mark pywin32 and the pythonnet/pywebview stack
  sys_platform == "win32" so the file installs on Linux.

model_manager: the two branches changed the same download path for different
reasons, so keep both. Upstream's resumable .part/Range downloads and Windows
rename-retry stay; snapshot fetches route through hf_hub_download again, which
is the only way to pull Xet-backed repos (upstream already ships hf-xet but
never wired it in). Added prune_hf_local_dir_cache so the hub client's
.cache/huggingface bookkeeping isn't promoted into installed model dirs.

Tests: 20 pass (test_ui_i18n updated for the English default, plus new cases
for the env-var precedence rule and alias normalization).
test_realtime_pipeline.py is untouched and still needs torch to run.
The try/except that falls back to `webui.ui_i18n` for the test harness also
swallowed ImportErrors raised *inside* ui_i18n — most notably a missing
opencc — and reported them as "No module named 'webui.ui_i18n'; 'webui' is
not a package", which points at the wrong problem. Only fall back when the
unresolved name is ui_i18n/webui itself; re-raise anything else so a missing
dependency names itself.
The WebUI's on-demand audiocpp_server defaulted to 8080, which on this setup
collides with a Windows-side listener (5KPlayer's Airplay.exe). Set the
catalog port to 8088. Code fallbacks and the standalone run_server default
stay at 8080 by design; override lives in the config.
Adopting upstream's streaming support routed the offline TTS button through
the generator do_tts_or_stream, whose immediate first yield replaces Gradio's
native "processing X.Xs" indicator with a static "⏳ Generating…" message — so
the seconds that used to tick during synthesis showed nothing until the final
"用时 X.Xs" status.

Run the blocking do_tts in a daemon thread and have the generator yield
"⏳ 生成中…已用时 Xs" every ~0.5s until it finishes, restoring the live count
(and now also covering the model-reload wait). do_tts already returns
(out, msg) and never raises, so no extra error handling is needed.
The 53 _ui_log(...) event lines (model load, TTS/ASR/music start+done,
downloads, GGUF conversion, ...) were hardcoded Chinese f-strings, so the
console and webui log stayed Chinese even with the English UI default. Route
each through _t(zh, en, ...), converting inline f-string expressions into named
format kwargs. Also localize the helper fragments they interpolate (resample
note, threads note, per-segment note, audio-duration hint) and the remaining
non-_ui_log log paths: the _pump_server_output duplicate-line collapser and the
required_files read-failure print.

Now logs default to English and switch to Chinese with the picker, matching the
rest of the UI. Verified: all 258 _t() calls have matching zh/en placeholder
sets with every placeholder covered by a kwarg; 20 tests pass.
@patrickjchen
patrickjchen force-pushed the webui/gradio-ui-i18n3 branch from 0c96c49 to 82da724 Compare July 21, 2026 16:50
@patrickjchen

Copy link
Copy Markdown
Contributor Author

Thank you @patrickjchen. The changes to model manager in this PR may break existing CI/Nix flows. Could you tentatively create a dedicated model_manager.py for the UI so the existing one stays stays lightweight and focused on the framework installer/catalog? The manager for UI can be in the webui dir, which will make the UI self-contained.

done, a new file model_manager_webui.py is created, and the original one is restored

@0xShug0
0xShug0 merged commit 3fd39dc into 0xShug0:main Jul 21, 2026
4 checks passed
@0xShug0

0xShug0 commented Jul 21, 2026

Copy link
Copy Markdown
Owner

@patrickjchen Merged! This is a big step forward for the project and thank you for the great work!

@0xShug0

0xShug0 commented Jul 21, 2026

Copy link
Copy Markdown
Owner

@patrickjchen I played around with it, and the UI is pretty cool!

I organized it a bit to make the webui fully self-contained.

@patrickjchen

patrickjchen commented Jul 21, 2026 via email

Copy link
Copy Markdown
Contributor Author

@0xShug0

0xShug0 commented Jul 21, 2026

Copy link
Copy Markdown
Owner

@patrickjchen MCP sounds interesting, but I’m currently considering a redesign of the public interface to make UI development, external integrations, and community contributions easier. I'd prefer to stabilize that interface first so MCP can be implemented as a thin adapter instead of becoming coupled to the current framework internals.

BTW, would you like to add an English README for the WebUI? The current one is only available in Chinese.

@0xShug0

0xShug0 commented Jul 24, 2026

Copy link
Copy Markdown
Owner

@patrickjchen Would you like to update the Web UI based on the release 0.4?

dleiferives pushed a commit to dleiferives/audio.cpp that referenced this pull request Jul 25, 2026
…d support for Linux) (0xShug0#87)

* webui: add the Gradio WebUI, cross-platform and English-first

The WebUI comes from kigner's fork and is the bulk of the logic here:
https://github.com/kigner/audio.cpp-webui.git (merged at 8924917). It is a Gradio
UI over audiocpp_server that loads one model at a time on demand, with model
management, background downloads, per-family request profiles, VRAM budgeting and
adaptive chunking for TTS/ASR/VC, and a dialogue mode that chains diarization into
ASR. All of that is kigner's work and is carried over as-is.

That fork targets Windows only and its interface is Chinese only. What this commit
adds is the cross-platform and localization work on top:

Cross-platform:
- Resolve the server binary by OS convention (.exe only on Windows) instead of
  assuming audiocpp_server.exe, and name run_server.sh/.bat per platform in the
  messages that mention it.
- Find from-source builds in either layout: build/<os>-<backend>-<type>/bin, where
  the backend is in the directory name, and a plain `cmake -B build` -> build/bin,
  which says nothing about the backend and is classified from its CMakeCache
  (GGML_CUDA:BOOL=ON). Without the second, a stock Linux dev tree found no binary
  at all and SERVER_EXE pointed at a path that did not exist.
- Add run_webui.sh as the POSIX counterpart of run_webui.bat.

Localization, English first:
- Strings move to webui/locales/<lang>.json, chosen by AUDIOCPP_LANG (default en)
  or the language picker in the UI. en.json is the per-key fallback, so a partial
  translation degrades to English rather than showing raw keys, and an unknown or
  malformed locale warns and falls back instead of taking the UI down. Adding a
  language is dropping in a file. zh.json keeps the fork's original Chinese.
- Catalog entries hold English display_name/input_hint; a locale overrides any of
  them via catalog.<id>.<field>, which is how zh.json restores the Chinese model
  names. Without this the catalog's own strings leaked into the English UI.
- t() applies str.format only when given arguments, so a translation can reorder
  placeholders, and a bad one falls back rather than raising.

The picker switches language in place. Gradio bakes each label in when it builds
the Blocks tree and cannot rebuild it in another language, so switching means
re-labelling every component: a registry maps each component property back to the
locale key that produced it, and the handler turns that into one update each.

The registry is derived rather than declared. Every localized string already goes
through t(), so a component's English text identifies its key by reverse lookup,
keeping ~120 call sites free of registration boilerplate. Two cases reverse lookup
cannot see, and how they are handled:
- Interpolated labels never match their template ("Model list (task=tts)" vs
  "Model list (task={task})"), so they register explicitly via i18n_register().
- Several keys sharing one English string are ambiguous; _english_key_index()
  checks whether any locale translates them differently and drops those, leaving
  the component on its current label rather than risking the wrong one.

Switching is process-wide, not per session: Gradio serves one Blocks object to all
connections, which suits a local single-user tool. Values the server parses stay
English while their labels localize, and the TTS/Voice Design sample texts are
only re-localized while untouched, so a switch cannot discard typed input.

Gradio's own widget text ("Click to Upload", ...) is compiled into its frontend
bundle and picked from the browser locale, so it follows the browser rather than
this picker and is left alone; the README says so.

Fixed while localizing:
- Two loops named their variable `t`, shadowing the translator for the rest of
  their scope.
- The ASR language list built labels as "<localized> <English>", which read as a
  stutter once the localized name was itself English ("Chinese Chinese").

Comments and docstrings in webui.py are still Chinese and are left for a later pass.

model_manager: fetch HF files via huggingface_hub, kigner's fix. Xet-backed repos
redirect to a CDN that rejects plain GETs against the resolve URL, so only the hub
client can pull their weights.

Co-Authored-By: kigner <aidiscovery2045@proton.me>

* webui: rebase on upstream 3-language UI, keep Linux support

The upstream author (kigner/audio.cpp-webui) rewrote the i18n layer and added
~1200 lines of features since our fork point. Their scheme is inline
_t(zh, en) calls with Traditional Chinese generated from the Simplified source
by OpenCC, which is mutually exclusive with our locales/*.json key lookup.
Take theirs as the base and re-apply our Linux work on top, rather than hand-
porting every new string into a locale file.

i18n:
- Adopt webui/ui_i18n.py; drop webui/locales/{en,zh}.json and the t()/registry
  code they fed. English/Simplified/Traditional all now come from one source.
- Default to English (was Chinese) and reorder the picker to match.
- AUDIOCPP_LANG supplies the default only when nothing has been picked in the
  UI yet; a saved pick wins, so a stale env var can't defeat the picker.
  Accepts the spellings people actually write (zh_TW, zh-CN, english, ...).

Linux:
- Re-apply EXE_SUFFIX / SERVER_EXE_NAME / SERVER_LAUNCHER and the from-source
  build discovery (_cmake_cache_backend, _discover_dev_bin_dirs), which also
  fixes _find_gguf_exe: upstream hardcoded build/windows-*-release, so it
  could never find a Linux converter build.
- ffmpeg lookup and the "gguf converter not found" messages no longer name
  .exe unconditionally.
- requirements.txt: mark pywin32 and the pythonnet/pywebview stack
  sys_platform == "win32" so the file installs on Linux.

model_manager: the two branches changed the same download path for different
reasons, so keep both. Upstream's resumable .part/Range downloads and Windows
rename-retry stay; snapshot fetches route through hf_hub_download again, which
is the only way to pull Xet-backed repos (upstream already ships hf-xet but
never wired it in). Added prune_hf_local_dir_cache so the hub client's
.cache/huggingface bookkeeping isn't promoted into installed model dirs.

Tests: 20 pass (test_ui_i18n updated for the English default, plus new cases
for the env-var precedence rule and alias normalization).
test_realtime_pipeline.py is untouched and still needs torch to run.

* webui: don't mask a missing opencc behind the ui_i18n import fallback

The try/except that falls back to `webui.ui_i18n` for the test harness also
swallowed ImportErrors raised *inside* ui_i18n — most notably a missing
opencc — and reported them as "No module named 'webui.ui_i18n'; 'webui' is
not a package", which points at the wrong problem. Only fall back when the
unresolved name is ui_i18n/webui itself; re-raise anything else so a missing
dependency names itself.

* webui: move on-demand server to port 8088 to avoid an 8080 clash

The WebUI's on-demand audiocpp_server defaulted to 8080, which on this setup
collides with a Windows-side listener (5KPlayer's Airplay.exe). Set the
catalog port to 8088. Code fallbacks and the standalone run_server default
stay at 8080 by design; override lives in the config.

* webui: restore the live elapsed-seconds counter during offline TTS

Adopting upstream's streaming support routed the offline TTS button through
the generator do_tts_or_stream, whose immediate first yield replaces Gradio's
native "processing X.Xs" indicator with a static "⏳ Generating…" message — so
the seconds that used to tick during synthesis showed nothing until the final
"用时 X.Xs" status.

Run the blocking do_tts in a daemon thread and have the generator yield
"⏳ 生成中…已用时 Xs" every ~0.5s until it finishes, restoring the live count
(and now also covering the model-reload wait). do_tts already returns
(out, msg) and never raises, so no extra error handling is needed.

* webui: localize console/log messages so they follow the UI language

The 53 _ui_log(...) event lines (model load, TTS/ASR/music start+done,
downloads, GGUF conversion, ...) were hardcoded Chinese f-strings, so the
console and webui log stayed Chinese even with the English UI default. Route
each through _t(zh, en, ...), converting inline f-string expressions into named
format kwargs. Also localize the helper fragments they interpolate (resample
note, threads note, per-segment note, audio-duration hint) and the remaining
non-_ui_log log paths: the _pump_server_output duplicate-line collapser and the
required_files read-failure print.

Now logs default to English and switch to Chinese with the picker, matching the
rest of the UI. Verified: all 258 _t() calls have matching zh/en placeholder
sets with every placeholder covered by a kwarg; 20 tests pass.

* make it work on Windows

* restore model_manager.py, and introduce a new one model_manager_webui.py

---------

Co-authored-by: Jilong Chen <jilong.chen@gmail.com>
Co-authored-by: kigner <aidiscovery2045@proton.me>
Anc813 pushed a commit to Anc813/audio.cpp that referenced this pull request Jul 25, 2026
…d support for Linux) (0xShug0#87)

* webui: add the Gradio WebUI, cross-platform and English-first

The WebUI comes from kigner's fork and is the bulk of the logic here:
https://github.com/kigner/audio.cpp-webui.git (merged at 8924917). It is a Gradio
UI over audiocpp_server that loads one model at a time on demand, with model
management, background downloads, per-family request profiles, VRAM budgeting and
adaptive chunking for TTS/ASR/VC, and a dialogue mode that chains diarization into
ASR. All of that is kigner's work and is carried over as-is.

That fork targets Windows only and its interface is Chinese only. What this commit
adds is the cross-platform and localization work on top:

Cross-platform:
- Resolve the server binary by OS convention (.exe only on Windows) instead of
  assuming audiocpp_server.exe, and name run_server.sh/.bat per platform in the
  messages that mention it.
- Find from-source builds in either layout: build/<os>-<backend>-<type>/bin, where
  the backend is in the directory name, and a plain `cmake -B build` -> build/bin,
  which says nothing about the backend and is classified from its CMakeCache
  (GGML_CUDA:BOOL=ON). Without the second, a stock Linux dev tree found no binary
  at all and SERVER_EXE pointed at a path that did not exist.
- Add run_webui.sh as the POSIX counterpart of run_webui.bat.

Localization, English first:
- Strings move to webui/locales/<lang>.json, chosen by AUDIOCPP_LANG (default en)
  or the language picker in the UI. en.json is the per-key fallback, so a partial
  translation degrades to English rather than showing raw keys, and an unknown or
  malformed locale warns and falls back instead of taking the UI down. Adding a
  language is dropping in a file. zh.json keeps the fork's original Chinese.
- Catalog entries hold English display_name/input_hint; a locale overrides any of
  them via catalog.<id>.<field>, which is how zh.json restores the Chinese model
  names. Without this the catalog's own strings leaked into the English UI.
- t() applies str.format only when given arguments, so a translation can reorder
  placeholders, and a bad one falls back rather than raising.

The picker switches language in place. Gradio bakes each label in when it builds
the Blocks tree and cannot rebuild it in another language, so switching means
re-labelling every component: a registry maps each component property back to the
locale key that produced it, and the handler turns that into one update each.

The registry is derived rather than declared. Every localized string already goes
through t(), so a component's English text identifies its key by reverse lookup,
keeping ~120 call sites free of registration boilerplate. Two cases reverse lookup
cannot see, and how they are handled:
- Interpolated labels never match their template ("Model list (task=tts)" vs
  "Model list (task={task})"), so they register explicitly via i18n_register().
- Several keys sharing one English string are ambiguous; _english_key_index()
  checks whether any locale translates them differently and drops those, leaving
  the component on its current label rather than risking the wrong one.

Switching is process-wide, not per session: Gradio serves one Blocks object to all
connections, which suits a local single-user tool. Values the server parses stay
English while their labels localize, and the TTS/Voice Design sample texts are
only re-localized while untouched, so a switch cannot discard typed input.

Gradio's own widget text ("Click to Upload", ...) is compiled into its frontend
bundle and picked from the browser locale, so it follows the browser rather than
this picker and is left alone; the README says so.

Fixed while localizing:
- Two loops named their variable `t`, shadowing the translator for the rest of
  their scope.
- The ASR language list built labels as "<localized> <English>", which read as a
  stutter once the localized name was itself English ("Chinese Chinese").

Comments and docstrings in webui.py are still Chinese and are left for a later pass.

model_manager: fetch HF files via huggingface_hub, kigner's fix. Xet-backed repos
redirect to a CDN that rejects plain GETs against the resolve URL, so only the hub
client can pull their weights.

Co-Authored-By: kigner <aidiscovery2045@proton.me>

* webui: rebase on upstream 3-language UI, keep Linux support

The upstream author (kigner/audio.cpp-webui) rewrote the i18n layer and added
~1200 lines of features since our fork point. Their scheme is inline
_t(zh, en) calls with Traditional Chinese generated from the Simplified source
by OpenCC, which is mutually exclusive with our locales/*.json key lookup.
Take theirs as the base and re-apply our Linux work on top, rather than hand-
porting every new string into a locale file.

i18n:
- Adopt webui/ui_i18n.py; drop webui/locales/{en,zh}.json and the t()/registry
  code they fed. English/Simplified/Traditional all now come from one source.
- Default to English (was Chinese) and reorder the picker to match.
- AUDIOCPP_LANG supplies the default only when nothing has been picked in the
  UI yet; a saved pick wins, so a stale env var can't defeat the picker.
  Accepts the spellings people actually write (zh_TW, zh-CN, english, ...).

Linux:
- Re-apply EXE_SUFFIX / SERVER_EXE_NAME / SERVER_LAUNCHER and the from-source
  build discovery (_cmake_cache_backend, _discover_dev_bin_dirs), which also
  fixes _find_gguf_exe: upstream hardcoded build/windows-*-release, so it
  could never find a Linux converter build.
- ffmpeg lookup and the "gguf converter not found" messages no longer name
  .exe unconditionally.
- requirements.txt: mark pywin32 and the pythonnet/pywebview stack
  sys_platform == "win32" so the file installs on Linux.

model_manager: the two branches changed the same download path for different
reasons, so keep both. Upstream's resumable .part/Range downloads and Windows
rename-retry stay; snapshot fetches route through hf_hub_download again, which
is the only way to pull Xet-backed repos (upstream already ships hf-xet but
never wired it in). Added prune_hf_local_dir_cache so the hub client's
.cache/huggingface bookkeeping isn't promoted into installed model dirs.

Tests: 20 pass (test_ui_i18n updated for the English default, plus new cases
for the env-var precedence rule and alias normalization).
test_realtime_pipeline.py is untouched and still needs torch to run.

* webui: don't mask a missing opencc behind the ui_i18n import fallback

The try/except that falls back to `webui.ui_i18n` for the test harness also
swallowed ImportErrors raised *inside* ui_i18n — most notably a missing
opencc — and reported them as "No module named 'webui.ui_i18n'; 'webui' is
not a package", which points at the wrong problem. Only fall back when the
unresolved name is ui_i18n/webui itself; re-raise anything else so a missing
dependency names itself.

* webui: move on-demand server to port 8088 to avoid an 8080 clash

The WebUI's on-demand audiocpp_server defaulted to 8080, which on this setup
collides with a Windows-side listener (5KPlayer's Airplay.exe). Set the
catalog port to 8088. Code fallbacks and the standalone run_server default
stay at 8080 by design; override lives in the config.

* webui: restore the live elapsed-seconds counter during offline TTS

Adopting upstream's streaming support routed the offline TTS button through
the generator do_tts_or_stream, whose immediate first yield replaces Gradio's
native "processing X.Xs" indicator with a static "⏳ Generating…" message — so
the seconds that used to tick during synthesis showed nothing until the final
"用时 X.Xs" status.

Run the blocking do_tts in a daemon thread and have the generator yield
"⏳ 生成中…已用时 Xs" every ~0.5s until it finishes, restoring the live count
(and now also covering the model-reload wait). do_tts already returns
(out, msg) and never raises, so no extra error handling is needed.

* webui: localize console/log messages so they follow the UI language

The 53 _ui_log(...) event lines (model load, TTS/ASR/music start+done,
downloads, GGUF conversion, ...) were hardcoded Chinese f-strings, so the
console and webui log stayed Chinese even with the English UI default. Route
each through _t(zh, en, ...), converting inline f-string expressions into named
format kwargs. Also localize the helper fragments they interpolate (resample
note, threads note, per-segment note, audio-duration hint) and the remaining
non-_ui_log log paths: the _pump_server_output duplicate-line collapser and the
required_files read-failure print.

Now logs default to English and switch to Chinese with the picker, matching the
rest of the UI. Verified: all 258 _t() calls have matching zh/en placeholder
sets with every placeholder covered by a kwarg; 20 tests pass.

* make it work on Windows

* restore model_manager.py, and introduce a new one model_manager_webui.py

---------

Co-authored-by: Jilong Chen <jilong.chen@gmail.com>
Co-authored-by: kigner <aidiscovery2045@proton.me>
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.

3 participants