- Preview/snippet decode strict UTF-8, then strict GB18030 (CW/1/革命时期的爱情.txt is the only non-UTF-8 TXT of 47,250); UTF-8 files are unchanged.
- First clip may extend to the nearest clause mark within 32 characters; starts/seeks snap back to a clause start within 48; batch ends prefer clause marks before word boundaries. First clips ending on punctuation: 50% -> 87.5% on sampled CCRD text.
perf: play TTS clips from memory, long-poll parts and queue next batch early
- Bounded in-memory MP3 clip cache (48 clips/4 MiB, 4 ahead, 2 concurrent GETs, released on stop/page exit): sentence changes and next/previous/double-click on generated parts no longer wait for an HF round-trip; back-navigation plays held clips before cache_only confirms.
- Long-poll /tts/jobs/{id}?after=N; queue the following batch once the current one publishes.
- Retry client_busy/cancel_pending 429 after ~0.4 s instead of the unreadable 5 s Retry-After.
fix: retry TTS gateway errors and restore CW LFS attribute
- Treat non-JSON (HTML) 502/504 gateway responses as transient TTS errors.
- Report paused playback to mediaSession.
- Bump tts-client.js query version.
- Re-add LFS attribute for CW/1/革命时期的爱情.txt; removing it in 85ff6f28 made the Space serve the pointer text.
fix: align spoken sentences and reuse prepared audio on seeks
Do not merge multiple sentences in one source part; keep connective prefixes with their clauses and preserve lexical tones. Seek within live current/next jobs instead of stop/rebuilding them, with epochs and in-flight guards. Retain only two played/ready descriptors for completed-cache-only reopening; misses prepare just the target, never an old batch. Preserve pause, sleep, source Unicode, inline/audio cleanup and all search behavior.
feat: play first MP3 directly from the synthesis response
Request opt-in inline first audio on explicit play, validate bounded bytes against the original part and decode a temporary local MP3 Blob. Eliminate the first audio GET without pre-generating books. Revoke on clip end, navigation and stop; stale responses allocate nothing. Keep canonical GET and pause-aware decode-error fallback, immutable later parts and all native controls.
feat: read complete words with low-latency first phrases
Use bounded browser word and natural-clause boundaries, protected numbers and original UTF-16 plans rather than fixed-character cuts. First POST waits for published audio; synthesis is fixed at 1.2 independent of playback rate. Hide voice name and replace collapse chevron with a horizontal icon while preserving collapse/stop and preview independence.
fix: preserve native reader focus and bounded source markup
Normalize legacy WebView fallback highlights rather than accumulating per-clip text nodes. Keep active controls within the preview focus scope while another source loads and detach only before DOM replacement. Reopening controls preserves active speech; visible-start explicitly switches source. Exercise real long Unicode fallback DOM and actual first-control inline Tab escape.
feat: compact native preview reader with rolling long-text playback
One preview play icon, fixed female01, compact non-modal native controls and direct CORS audio. Start at visible source or double-clicked sentence; support locate, pitch/rate/sleep and pause-aware bounded prefetch. Remove document-wide 20k cap and iframe startup chain; first batch targets 80 codepoints, subsequent 480. Request opt-in pauses for unknown phones without changing originals.
Yesterday
feat: pilot explicit preview and selection reading with Hitokoto
Reuse the lazy independent CPU reader through a strict two-origin window/channel bridge. Preserve exact preview text and selection context, require explicit synthesis and active replacement, and keep search/filter/preview independent of the persistent player. No index/corpus/backend/model dependencies or SW cache-name changes.
fix(filters): use one stateful expand-collapse button
Remove system speech entry, settings, playback controls, styles and static module. Preserve fullscreen/restore button order and fullscreen share URLs. BHA removes only the obsolete TTS static-copy line. No backend, corpus, index, generated-data or runtime-configuration changes.
feat: add system TTS controls and shareable fullscreen previews
Frontend-only system speech, voice/rate/pitch preferences, position-aware playback, sleep timer and fullscreen URL restoration. BHA additionally copies the new static module into its frontend image output. No backend, corpus, generated data, index or runtime configuration changes.
ui: place preview fullscreen control before close
Swap only the fullscreen and close button order in preview toolbars, including the BHA proofreading toolbar. No backend, data, index, configuration or CSS changes.