Daily Tech Briefing
AI 科技速览

每天 5 分钟内学习 AI。获取最新的人工智能新闻,理解其重要性,并学习如何将其应用于您的工作。

AI 快讯
Dev.to AI · 2026/8/4 03:24:26

Why Browser-Based Multilingual TTS Kept Freezing at 86% — and How We Fixed It

AI 中文解读
【Why Browser-Based Multilingual TTS Kept Freezing at 86% — and How We Fixed It】Running text-to-speech entirely in the browser sounds simple: download an ONNX model, create an inference session, and synthesize audio without sending user text or media to a server. In production, ...
<p>Running text-to-speech entirely in the browser sounds simple: download an ONNX model, create an inference session, and synthesize audio without sending user text or media to a server.</p> <p>In production, it is much harder.</p> <p>While building multilingual voice generation for <a href="https://github.com/MartinDelophy/ai-video-editor" rel="noopener noreferrer">Timeline Studio</a>, we repeatedly saw the same failure: the model-loading UI stopped at <strong>86%</strong>, the Generate button stayed busy, and switching from Chinese to English, German, Korean, Thai, or Japanese made the issue more likely.</p> <p>The most useful console message was:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>Unable to cache file QuotaExceededError: Quota exceeded. QuotaExceededError: The operation failed because it would cause the application to exceed its storage quota. </code></pre> </div> <p>The progress bar was only the symptom. The real problem was the interaction between large model files, multiple TTS runtimes, browser storage quotas, service-worker caching, WebGPU initialization, and region-specific model mirrors.</p> <p>This post explains the architecture changes that made the multilingual pipeline reliable.</p> <ul> <li> <strong>Project:</strong> <a href="https://github.com/MartinDelophy/ai-video-editor" rel="noopener noreferrer">https://github.com/MartinDelophy/ai-video-editor</a> </li> <li> <strong>Live demo:</strong> <a href="https://video-editor.ai-creator.top/" rel="noopener noreferrer">https://video-editor.ai-creator.top/</a> </li> </ul> <h2> The browser was doing more than the progress bar showed </h2> <p>A browser TTS model normally goes through several stages:</p> <ol> <li>Download configuration, phonemizer, tokenizer, and vocabulary files.</li> <li>Download one or more ONNX model files.</li> <li>Store artifacts in Cache Storage.</li> <li>Create an ONNX Runtime session.</li> <li>Compile the graph for WebGPU or initialize WASM.</li> <li>Run a warm-up inference.</li> <li>Finally synthesize the requested speech.</li> </ol> <p>Our original progress calculation mainly represented network downloads. If the files finished downloading but cache insertion or session creation failed, the UI retained the last reported value — often 86%.</p> <p>So the browser was not necessarily still downloading anything. It had already moved into an unrepresented stage and thrown an exception before the state machine could reach either success or a useful error state.</p> <p>The fix started by treating model setup as a real multi-stage operation:</p> <ul> <li>Checking local model cache</li> <li>Downloading model artifacts</li> <li>Initializing the local inference engine</li> <li>Preparing the selected voice</li> <li>Generating speech</li> </ul> <p>During initialization, the UI now says what is actually happening instead of pretending another file is still downloading.</p> <h2> One origin, many competing caches </h2> <p>Timeline Studio supports several browser-local voice runtimes because one model family is not the best choice for every language:</p> <div class="table-wrapper-paragraph"><table> <thead> <tr> <th>Language group</th> <th>Runtime</th> <th>Execution path</th> </tr> </thead> <tbody> <tr> <td>Chinese</td> <td>Piper</td> <td>WebGPU first, WASM fallback</td> </tr> <tr> <td>English</td> <td>Kokoro Q8</td> <td>WASM</td> </tr> <tr> <td>Selected European languages</td> <td>Piper</td> <td>WASM</td> </tr> <tr> <td>Korean, Thai, Vietnamese, Russian</td> <td>MMS</td> <td>WASM</td> </tr> <tr> <td>Japanese</td> <td>Supertonic</td> <td>WASM</td> </tr> </tbody> </table></div> <p>All of these runtimes operate under the same browser origin. Cache Storage, IndexedDB, and service-worker caches therefore compete for the same site quota.</p> <p>After a user tried several voices, the origin could contain:</p> <ul> <li>Current model files</li> <li>Older model revisions</li> <l
分享
阅读原文