Fix chunked TTS failing on newline-delimited text (e.g. German bullet lists)
splitTextIntoChunks only split on sentence terminators (.!?), so structured text separated by newlines was never chunked — the full page went as one request, causing a TCP timeout that the browser reported as "Failed to fetch". Fix: process each line individually before applying the sentence regex so newline-separated segments become their own split points. Also move generation.js from deferred batch E into the main feature batch C so generateChunkedTts is always defined before the user can click Generate. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
e6cadd26a3
commit
345bec8a05
@ -8027,16 +8027,25 @@ async function mergeWavBlobs(blobs) {
|
|||||||
function splitTextIntoChunks(text, maxLen = 800) {
|
function splitTextIntoChunks(text, maxLen = 800) {
|
||||||
const abbrev = /\b(Mr|Mrs|Ms|Dr|Prof|Sr|Jr|vs|etc|e\.g|i\.e)\.\s/g;
|
const abbrev = /\b(Mr|Mrs|Ms|Dr|Prof|Sr|Jr|vs|etc|e\.g|i\.e)\.\s/g;
|
||||||
const safe = text.replace(abbrev, m => m.replace('.', '\x00'));
|
const safe = text.replace(abbrev, m => m.replace('.', '\x00'));
|
||||||
const parts = safe.match(/[^.!?]+[.!?]+\s*/g) || [];
|
|
||||||
const last = safe.replace(/[^.!?]+[.!?]+\s*/g, '').trim();
|
|
||||||
if (last) parts.push(last);
|
|
||||||
const restore = s => s.replace(/\x00/g, '.');
|
const restore = s => s.replace(/\x00/g, '.');
|
||||||
if (!parts.length) return [text];
|
|
||||||
|
// Gather segments from each line: sentences first, then any remaining line text.
|
||||||
|
// This ensures newline-delimited text (e.g. German bullet lists) gets split too.
|
||||||
|
const segments = [];
|
||||||
|
for (const line of safe.split('\n')) {
|
||||||
|
const sentences = line.match(/[^.!?]+[.!?]+\s*/g) || [];
|
||||||
|
const rest = line.replace(/[^.!?]+[.!?]+\s*/g, '').trim();
|
||||||
|
segments.push(...sentences);
|
||||||
|
if (rest) segments.push(rest);
|
||||||
|
}
|
||||||
|
if (!segments.length) return [text];
|
||||||
|
|
||||||
const chunks = [];
|
const chunks = [];
|
||||||
let cur = '';
|
let cur = '';
|
||||||
for (const p of parts) {
|
for (const seg of segments) {
|
||||||
if ((cur + p).length > maxLen && cur) { chunks.push(restore(cur.trim())); cur = p; }
|
const joined = cur ? cur + ' ' + seg.trim() : seg.trim();
|
||||||
else cur += p;
|
if (joined.length > maxLen && cur) { chunks.push(restore(cur.trim())); cur = seg.trim(); }
|
||||||
|
else cur = joined;
|
||||||
}
|
}
|
||||||
if (cur.trim()) chunks.push(restore(cur.trim()));
|
if (cur.trim()) chunks.push(restore(cur.trim()));
|
||||||
return chunks.length ? chunks : [text];
|
return chunks.length ? chunks : [text];
|
||||||
|
|||||||
@ -57,16 +57,25 @@ async function mergeWavBlobs(blobs) {
|
|||||||
function splitTextIntoChunks(text, maxLen = 800) {
|
function splitTextIntoChunks(text, maxLen = 800) {
|
||||||
const abbrev = /\b(Mr|Mrs|Ms|Dr|Prof|Sr|Jr|vs|etc|e\.g|i\.e)\.\s/g;
|
const abbrev = /\b(Mr|Mrs|Ms|Dr|Prof|Sr|Jr|vs|etc|e\.g|i\.e)\.\s/g;
|
||||||
const safe = text.replace(abbrev, m => m.replace('.', '\x00'));
|
const safe = text.replace(abbrev, m => m.replace('.', '\x00'));
|
||||||
const parts = safe.match(/[^.!?]+[.!?]+\s*/g) || [];
|
|
||||||
const last = safe.replace(/[^.!?]+[.!?]+\s*/g, '').trim();
|
|
||||||
if (last) parts.push(last);
|
|
||||||
const restore = s => s.replace(/\x00/g, '.');
|
const restore = s => s.replace(/\x00/g, '.');
|
||||||
if (!parts.length) return [text];
|
|
||||||
|
// Gather segments from each line: sentences first, then any remaining line text.
|
||||||
|
// This ensures newline-delimited text (e.g. German bullet lists) gets split too.
|
||||||
|
const segments = [];
|
||||||
|
for (const line of safe.split('\n')) {
|
||||||
|
const sentences = line.match(/[^.!?]+[.!?]+\s*/g) || [];
|
||||||
|
const rest = line.replace(/[^.!?]+[.!?]+\s*/g, '').trim();
|
||||||
|
segments.push(...sentences);
|
||||||
|
if (rest) segments.push(rest);
|
||||||
|
}
|
||||||
|
if (!segments.length) return [text];
|
||||||
|
|
||||||
const chunks = [];
|
const chunks = [];
|
||||||
let cur = '';
|
let cur = '';
|
||||||
for (const p of parts) {
|
for (const seg of segments) {
|
||||||
if ((cur + p).length > maxLen && cur) { chunks.push(restore(cur.trim())); cur = p; }
|
const joined = cur ? cur + ' ' + seg.trim() : seg.trim();
|
||||||
else cur += p;
|
if (joined.length > maxLen && cur) { chunks.push(restore(cur.trim())); cur = seg.trim(); }
|
||||||
|
else cur = joined;
|
||||||
}
|
}
|
||||||
if (cur.trim()) chunks.push(restore(cur.trim()));
|
if (cur.trim()) chunks.push(restore(cur.trim()));
|
||||||
return chunks.length ? chunks : [text];
|
return chunks.length ? chunks : [text];
|
||||||
|
|||||||
@ -117,6 +117,7 @@
|
|||||||
'/static/js/voice-clone.js',
|
'/static/js/voice-clone.js',
|
||||||
'/static/js/voice-library.js',
|
'/static/js/voice-library.js',
|
||||||
'/static/js/tts-preview.js',
|
'/static/js/tts-preview.js',
|
||||||
|
'/static/js/generation.js',
|
||||||
'/static/js/benchmark.js',
|
'/static/js/benchmark.js',
|
||||||
'/static/js/stt.js',
|
'/static/js/stt.js',
|
||||||
'/static/js/rehearser-parse.js',
|
'/static/js/rehearser-parse.js',
|
||||||
@ -152,12 +153,10 @@
|
|||||||
if (window.initAccessibilityEnhancements) window.initAccessibilityEnhancements();
|
if (window.initAccessibilityEnhancements) window.initAccessibilityEnhancements();
|
||||||
|
|
||||||
// E — post-init modules load in background AFTER the UI is already visible.
|
// E — post-init modules load in background AFTER the UI is already visible.
|
||||||
// Engines, AI backends, generation, and conversation sections load while
|
// Engines, AI backends, and conversation load while the user browses other tabs.
|
||||||
// the user browses Voices / Clone / Design, not before.
|
|
||||||
_loadBatch([
|
_loadBatch([
|
||||||
'/static/js/engines.js',
|
'/static/js/engines.js',
|
||||||
'/static/js/ai-backends.js',
|
'/static/js/ai-backends.js',
|
||||||
'/static/js/generation.js',
|
|
||||||
'/static/js/conversation.js',
|
'/static/js/conversation.js',
|
||||||
]);
|
]);
|
||||||
})();
|
})();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user