The g2pW GCS archive now returns 404, so every Space build failed at
fetch_tts_assets.py. The lock pins the same g2pW.onnx/POLYPHONIC_CHARS.txt
bytes (unchanged SHA-256) from two HF mirrors at fixed revisions.
Foreign-language spans were found per synthesis part, so a clip cut at ', '
read 'In 1968, ' as Chinese numbers and short French/German pieces as
English. Spans are now planned on the whole request and clipped per part;
clear sentences inside one span keep their own language.
feat(tts): read foreign-language spans in their own language via eSpeak NG
"1.马克思主义" was segmented after "1." and normalised to "一.", so the number was spoken as its own sentence. A list marker (1. / 一. / (3). at a line or clause start; never a decimal, version or IP) no longer ends a server or standalone-reader segment and is read as "一、". Python and static reader.js share the rule (parity test); narration identity becomes phrases-v13-list-markers.
13 days ago
fix: keep the contextual tone of 一 instead of the digit-only sandhi rule
Misaki's _yi_sandhi treats a word as a number only when every other character is a digit, so it rewrote g2pW's yi1 in 一九六五年/十一月/二十一日/十一届/统一战线/一月一号 to yi2/yi4. Keep a contextual reading for 一; the dictionary path and the reduplicated 看一看 neutral tone are unchanged. Real-model check: 20/20 sampled contexts follow g2pW; pronunciation gate 58/58, 0 regressions. Narration identity phrases-v12-context-yi.
fix: keep a trailing silence guard after every progressive part
Real-model measurement showed trim removes only sub-audible tails; continuation parts ended 70 ms after speech, so a player clip swap could clip the last syllable. Every progressive part now ends with at least 0.22 s of silence. Narration identity phrases-v11-tail-guard.
perf: per-part polyphone context, trimmed padding and part long-poll
- Progressive pause mode predicts g2pW readings per part from the same complete document (real-model gate: identical phones on five CCRD batches; local first-part pronunciation 8.8-16.1 s -> 0.07-0.79 s).
- Trim Kokoro's outer near-silence per part (~0.75-0.8 s) before deliberate pause_after silence; narration identity phrases-v10-trimmed.
- Optional GET /tts/jobs/{id}?after=N long-poll sharing the wait_first 8 s/16-waiter bound.
feat: reopen completed speech cache without admitting inference
Add strict opt-in cache-only lookup for exact original plans used by backward navigation. Misses return 410 without new work or joining pending jobs; retain rate, idempotency and cache bounds. Add API and normal connective-tone regressions. Models, actual phonemes, default synthesis, quote API and standalone reader remain unchanged.
feat: include one bounded first MP3 in opt-in create responses
Return completed leased part-zero audio with the first JSON response, avoiding a second HF request. Bound base64 payloads to 128 KiB and reuse the asynchronous first-part waiter budget. Recheck cancellation after off-loop file reads and retain canonical GET/HEAD/Range fallback. Delivery flags do not change synthesis/idempotency; models, queue, quotes and old clients are untouched.
feat: validate word-phrase plans and return first audio without polling
Support opt-in contiguous UTF-16 segment ends with numeric/surrogate protection and cache/retry identity. Keep the exact worker publication plan. Bounded asynchronous wait-first returns on an immutable published part, with 8-second/16-waiter fallback to ordinary 202. Preserve strict/default clients, quote API, model pins and CPU hardware.
feat: opt-in short pauses for unsupported speech characters
Keep strict default requests and original UTF-16 source spans. Replace only unavailable phonemes with commas in pause mode, encode intentional symbol-only PCM pauses, and bind the policy to bounded work/cache/idempotency. Preserve models, voices, pronunciation, single CPU worker and quote API.
Restrict parent origin/window/channel and frame ancestors; import bounded original text/context without auto synthesis or private bookmark restoration. Reuse existing independent player and require explicit active-speech replacement. Add cross-frame keyboard and collapse/stop controls while leaving inference and quote API unchanged.
fix: include native pitch runtime and verify it during image build
The target Pedalboard x86 wheel links libatomic.so.1 absent from Python slim. Install libatomic1 and run actual frequency/duration pitch guards in the image so missing DSP dependencies fail the build instead of leaving a RUNNING Space with failed TTS. Quote API/data and models remain unchanged.
feat: add optional duration-preserving CPU pitch audition
Preserve original text/UTF-16 positions and pinned CPU models. Keep dates, versions and labelled numeric IDs whole across source plans; use the same idempotent spoken forms in contextual and acoustic frontends. Add browser-only 0.5-2 playback rates and nonpersistent clip/deadline sleep timers with progress-safe cancellation.
feat: add source clip navigation, structural pauses and pause-aware prefetch
Keep original UTF-16 text and complete MP3 API. Publish source plans before synthesis, add safe source highlighting and previous/next/click seeks, vary supplemental silence by structure, and stop speculative tasks/audio preloads while paused. Release late job capabilities and ignore obsolete play promises without changing CPU, models, voices or quote data.
fix: coalesce whitespace-only speech parts without trimming source
Avoid flushing a progressive MP3 encoder that never received PCM. Preserve leading, internal and trailing whitespace in speech-bearing spans, with real local codec and lossless segmentation gates.
fix: keep speech retries stable across proxy and mobile IP changes
Bind secret random retry capabilities to request content rather than peer IP while retaining observed-peer and global rate limits. Use 192-bit reader tokens and wait for restored voice options before enabling playback.
feat: publish completed speech parts and add resumable long reader
Preserve complete MP3 API, quote/data contracts and pinned two-thread CPU models. Add bounded atomic part publication with cancellation-safe leases, contextual adjacent batches and idempotent retries. Audition reader supports opt-in local bookmarks, at most one following batch and MP3 preload, and explicit recovery without skipping text.
feat: add contextual g2pW readings and use both CPU cores
Keep Kokoro voices and quote API/data unchanged. Add pinned offline g2pW ONNX polyphone disambiguation, preserve lexical tones and reviewed regional dictionary readings, retain source offsets across synthesis splits, and use two CPU threads sequentially in the existing single worker.
fix: clean up audition sessions and audio API schema
Preserve original quote routes and data. Add one isolated Kokoro CPU worker, checksum-pinned build assets, bounded admission/cache, job cancellation, native MP3/Range playback and cross-site CORS. Consolidate case-colliding readme into the HF README for Android development.