Skip to content

Text Chunking

ResponsiveVoice automatically splits long text into smaller chunks for optimal playback. This ensures reliable speech synthesis even with large amounts of text.

  • API Limits: TTS services have character limits per request
  • Memory: Smaller audio buffers are more efficient
  • Responsiveness: Speech starts faster with smaller chunks
  • Reliability: Reduces chance of timeouts and errors

Chunking happens automatically when you call speak():

// This long text is automatically split into chunks
responsiveVoice.speak(
`
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.
`,
'UK English Female',
);

Within the character limit, text is split at the latest (rightmost) natural boundary, preferring higher-priority delimiters first:

  1. Sentence endings (. ? !)
  2. Major separators (; :)
  3. Clause separators (,)
  4. Word boundaries (spaces)
  5. CJK character boundaries (between ideographs, when no earlier boundary fits)
SettingValueDescription
Default chunk size100 charsCharacters per chunk when not set
Min chunk size50 charsLower bound (smaller values clamp up)
Max chunk size300 charsUpper bound (larger values clamp down)
Sentence priorityHighPrefers sentence boundaries

The chunk character limit is a page-wide setting. Set it globally:

<script src="https://cdn.responsivevoice.org/sdk/latest/responsivevoice.js"></script>
<script>
// At startup
responsiveVoice.init({ characterLimit: 150 }); // clamped to 50–300
// Or at runtime
responsiveVoice.setCharacterLimit(150);
responsiveVoice.getCharacterLimit(); // 150
</script>

Chunks are queued and played sequentially without gaps:

responsiveVoice.speak(longArticle, 'UK English Female', {
onstart: () => console.log('Started reading article'),
onend: () => console.log('Finished reading article'),
// onend fires once when ALL chunks complete
});

For complete control, split the text yourself with chunkText(). Each chunk is { text, index, total, isLast }:

const chunks = responsiveVoice.chunkText(article, { characterLimit: 200 });
for (const chunk of chunks) {
await new Promise<void>((resolve) =>
responsiveVoice.speak(chunk.text, 'UK English Female', { onend: resolve }),
);
}

chunkText is also importable standalone from @responsivevoice/text.

Track progress across chunks:

const chunks = responsiveVoice.chunkText(longText, { characterLimit: 200 });
let currentChunk = 0;
function speakNextChunk() {
if (currentChunk >= chunks.length) {
console.log('Complete!');
return;
}
const chunk = chunks[currentChunk];
const progress = ((chunk.index + 1) / chunk.total) * 100;
console.log(`Progress: ${progress.toFixed(0)}%`);
responsiveVoice.speak(chunk.text, 'UK English Female', {
onend: () => {
currentChunk++;
speakNextChunk();
},
});
}
speakNextChunk();

The chunker is aware of:

  • Numbers: won't split on . or , inside a number (3.14, 1,000)
  • Grouping pairs: prefers not to split inside quotes, parentheses, or brackets
// Numbers stay intact
responsiveVoice.speak('The price is $19.99 per month.', voice);
// Quoted text is kept together
responsiveVoice.speak('She said "Hello there, friend!" and waved.', voice);

ResponsiveVoice takes plain text, not SSML — no current browser implements the Web Speech API's SSML, so it isn't supported. Shape delivery with the rate, pitch, and volume parameters plus punctuation. See the FAQ.

  1. Pre-chunk large texts for better control
  2. Keep characterLimit within range (50–300; default 100)
  3. Avoid very small chunks (causes choppy playback)
  4. Consider caching for repeated content