docs(openwebui): the TTS voice rejector is in-browser Kokoro, not frank-tts #20

Merged
dank merged 3 commits from docs/openwebui-browser-kokoro-tts into main 2026-10-18 20:38:50 -07:00
Owner

What changed

Docs only — the diagnosis of Frank's live OpenWebUI toast, plus two crosslinks.

Error: Voice "narrator1" not found. Should be one of: af_heart, …, bm_fable
is not frank-tts refusing the name. That 29-name enum is the fixed voice
pack of Kokoro.js running in the browser, which OpenWebUI 0.11.4 ships in
its own front end as a TTS engine (browser-kokoro). The narrator1 reject
happens client-side, so the cloned-voice endpoint never sees the request.

Evidence (measured 2026-10-18, on the live service)

Instrument Result
Admin config DB (config table) audio.tts.engine=openai, audio.tts.openai.api_base_url=http://host.containers.internal:7772/v1, audio.tts.model=frank-tts, audio.tts.voice=narrator1, split_on=punctuation — correct
Exact OpenWebUI body, POSTed from inside the container 200, audio/mpeg, 7,629 B ({"model":"frank-tts","input":…,"voice":"narrator1","response_format":"mp3","speed":1.0})
podman logs open-webui zero audio/speech requests for the failing click
Bundle forensics voice table {af_heart:{name:"Heart",language:"en-us",gender:"Female",traits:"❤️",targetQuality:"A"}} + _validate_voice + model onnx-community/Kokoro-82M-v1.0-ONNX; engine select values "" (Default) and browser-kokoro; personal Kokoro.js dtype setting
Container env no AUDIO_*/TTS/STT variable set
All four user.settings rows no audio/TTS/voice key

The contrast is the instrument: a server-path failure leaves a container log
line and a frank-tts error; a browser-kokoro failure leaves neither.

Fix (a UI click, not a deploy)

Settings → Audio → TTS Engine → Default returns synthesis to the admin
config, i.e. frank-tts and the cloned voices. Choosing af_heart instead
keeps in-browser Kokoro, which cannot clone — fixed pack only, and it
downloads the ONNX model per tab.

Pages

  • Dankclaw/OpenWebUI.md — new Text-to-speech (frank-tts) section: the
    endpoint contract (the shim resolves voice=<name> against
    /home/dank/voices/<name>/reference.wav; an unknown name is a 400 listing
    what exists, never a silent fallback), the browser-Kokoro trap, and the
    discriminating probe. See Also gains [[Frank TTS]].
  • Dankclaw/Frank TTS.md — troubleshooting table gains the symptom "a
    consumer rejects narrator1 by listing 29 names and no request reaches the
    façade".
  • log.md — worklog entry for the window, including the dankvoice merge
    (0c7fe8b) and the plain-omp auto-load proof.

Verification

./tests/run.sh on the merged tree — reported in the PR comments.

Also merged origin/main (5fbbea2) into the branch during the window; the
only conflict was log.md, where both sides appended dated entries at the
tail — resolved by keeping upstream's entries first, then this window's.

## What changed Docs only — the diagnosis of Frank's live OpenWebUI toast, plus two crosslinks. `Error: Voice "narrator1" not found. Should be one of: af_heart, …, bm_fable` is **not** frank-tts refusing the name. That 29-name enum is the fixed voice pack of **Kokoro.js running in the browser**, which OpenWebUI 0.11.4 ships in its own front end as a TTS engine (`browser-kokoro`). The `narrator1` reject happens client-side, so the cloned-voice endpoint never sees the request. ## Evidence (measured 2026-10-18, on the live service) | Instrument | Result | |---|---| | Admin config DB (`config` table) | `audio.tts.engine=openai`, `audio.tts.openai.api_base_url=http://host.containers.internal:7772/v1`, `audio.tts.model=frank-tts`, `audio.tts.voice=narrator1`, `split_on=punctuation` — correct | | Exact OpenWebUI body, POSTed from **inside** the container | `200`, `audio/mpeg`, 7,629 B (`{"model":"frank-tts","input":…,"voice":"narrator1","response_format":"mp3","speed":1.0}`) | | `podman logs open-webui` | **zero** `audio/speech` requests for the failing click | | Bundle forensics | voice table `{af_heart:{name:"Heart",language:"en-us",gender:"Female",traits:"❤️",targetQuality:"A"}}` + `_validate_voice` + model `onnx-community/Kokoro-82M-v1.0-ONNX`; engine select values `""` (Default) and `browser-kokoro`; personal `Kokoro.js dtype` setting | | Container env | no `AUDIO_*`/`TTS`/`STT` variable set | | All four `user.settings` rows | no audio/TTS/voice key | The contrast is the instrument: a server-path failure leaves a container log line **and** a frank-tts error; a `browser-kokoro` failure leaves neither. ## Fix (a UI click, not a deploy) Settings → Audio → **TTS Engine → Default** returns synthesis to the admin config, i.e. frank-tts and the cloned voices. Choosing `af_heart` instead keeps in-browser Kokoro, which cannot clone — fixed pack only, and it downloads the ONNX model per tab. ## Pages - `Dankclaw/OpenWebUI.md` — new *Text-to-speech (frank-tts)* section: the endpoint contract (the shim resolves `voice=<name>` against `/home/dank/voices/<name>/reference.wav`; an unknown name is a 400 listing what exists, never a silent fallback), the browser-Kokoro trap, and the discriminating probe. See Also gains `[[Frank TTS]]`. - `Dankclaw/Frank TTS.md` — troubleshooting table gains the symptom "a consumer rejects `narrator1` by listing 29 names and no request reaches the façade". - `log.md` — worklog entry for the window, including the `dankvoice` merge (`0c7fe8b`) and the plain-`omp` auto-load proof. ## Verification `./tests/run.sh` on the merged tree — reported in the PR comments. Also merged `origin/main` (`5fbbea2`) into the branch during the window; the only conflict was `log.md`, where both sides appended dated entries at the tail — resolved by keeping upstream's entries first, then this window's.
dank added 3 commits 2026-10-18 20:18:56 -07:00
The `Voice "narrator1" not found. Should be one of: af_heart, …, bm_fable`
toast is OpenWebUI 0.11.4's bundled Kokoro.js validator: the enum is
Kokoro's fixed 29-voice pack, not frank-tts's registry. Frank-tts answers
200 audio/mpeg for the exact OpenWebUI body from inside the container, and
the failing click leaves no `audio/speech` line in the container log — that
contrast is the instrument. Admin config DB is correct
(engine=openai, base URL :7772/v1, model frank-tts, voice narrator1); no
container env and no user row carries an audio override, so the
`browser-kokoro` choice is per-browser storage. Fix: Settings → Audio →
TTS Engine → Default.
# Conflicts:
#	serverAppConfigs-docs/log.md
A consumer that lists the 29-name af_*/am_*/bf_*/bm_* pack and refuses
narrator1 without a request reaching the façade is synthesizing in the
browser. Frank TTS's troubleshooting table gains that symptom; OpenWebUI's
See Also gains the service page.
dank merged commit 100b62ba22 into main 2026-10-18 20:38:50 -07:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dank/serverAppConfigs#20