Skip to content

fix(ebook): load the full Edge TTS voice list - #1409

Closed
kalashnikxvxiii wants to merge 1 commit into
harborstremio:beta-branchfrom
kalashnikxvxiii:fix/ebook-tts-voice-list
Closed

kalashnikxvxiii wants to merge 1 commit into
harborstremio:beta-branchfrom
kalashnikxvxiii:fix/ebook-tts-voice-list

Conversation

@kalashnikxvxiii

Copy link
Copy Markdown

Summary

The eBook reader only ever offered the 21 built-in voices, all English or Arabic, so no other language could be selected. It now loads the full, 300+ voices across 75 locales.

Why

kothok-edge-tts reads the voice list response until the socket closes and lets the read error escape:

    let n = tls.read(&mut chunk).await?;    // propagates the error
    if n == 0 { break; }

Microsoft closes the connection without a TLS close_notify, so rustls reports UnexpectedEof rather than a clean Ok(0). list_voices() fails every single time even though the body already arrived intact, and the reader silently keeps its built-in table.
I checked the endpoint directly with the same token and parameters: HTTP 200, 167 KB, 322 voices across 75 locales, italian included. So nothing is wrong with the request itself, only with how the response is read.
The fix belongs upstream, but 0.2.10 is the newest release and the crate is unchanged since July, so this works around it on our side: fetch the list with reqwest, which ends the body on Content-length, and keep the crate call as a fallback if the direct fetch fails or comes back empty.

Two things worth flagging for review:

  • TRUSTED_CLIENT_TOKEN and SEC_MS_GEC_VERSION had to be redeclared here because the are pub(crate) in the crate. They are public protocol constants, identical in every edge-tts implementation, but it is duplication.
  • sec_ms_gec() is re-exported by the crate but marked #[doc(hidden)], so it works yet is not guaranteed API.

http_client_builder becomes pub(crate) so the shared timeouts and pool settings are reused instead of duplicated.

Verification

  • cargo check --manifest-path src-tauri/Cargo.toml - clean, no new warnings (17 before and after, all pre-existing elsewhere)
  • cargo test --manifest-path src-tauri/Cargo.toml - 180 passed, 0 failed, 2 ignored
  • Ran a source build and opened the narration settings: the voice list now shows every locale

Platform Impact

Verified on Linux (WebKitGTK). The change sits in the shared HTTP path rather than in anything platform-specific, so it should behave the same everywhere.
The crate fallback keeps the previous behaviour if the direct fetch ever fails.

Checklist

  • This pull request is focused and contains no unrelated refactors.
  • I ran vp check for the changed files. (n/a, Rust only)
  • I ran vp run typecheck after TypeScript changes. (n/a, no TypeScript)
  • I ran the relevant Cargo checks after Rust changes.
  • I tested affected platforms when the change is platform-specific. (Linux)
  • I preserved playback, navigation, and configured hotkey behavior where applicable.
  • I added or updated tests for behavior changes. (depends on a live network call; verified manually)
  • I removed secrets, tokens, private URLs, and personal data from logs and screenshots.

The reader only ever offered the 21 built-in voices, all English or
Arabic, so no other language could be picked.

kothok-edge-tts reads the voice list response until the socket closes
and lets the read error escape. Microsoft closes without a TLS
close_notify, so rustls reports UnexpectedEof and list_voices() fails
every time, even though the body already arrived intact. Checked
against the endpoint directly: 200, 167 KB, 322 voices across 75
locales.

Fetch the list with reqwest, which ends the body on Content-Length, and
keep the crate call as a fallback. http_client_builder becomes
pub(crate) so the timeouts and pool settings stay in one place.
@Talal1011 Talal1011 added this to the Beta 0.9.126 milestone Sep 13, 2026
@Talal1011

Copy link
Copy Markdown
Collaborator

Release tracking: this work was integrated through our experimental/beta release branch and is carried in Beta 0.9.126 (published build e758926), with integration adjustments where needed. Closing the PR as already incorporated into the release build; this does not indicate a new merge into the upstream beta branch. Thank you for the contribution.

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