GUIDEclient.speech.createLongForm()

Long-Form Audio

Generate audio from text of any length — articles, blog posts, book chapters. The SDK handles chunking, generation, retry, and concatenation automatically.

How It Works

The murmr API has a 4,096-character limit per request. For longer text, the SDK splits your input into chunks at natural sentence boundaries, generates audio for each chunk sequentially, and concatenates the results with configurable silence gaps.

1

Split text at sentence boundaries

Splits at .!? and CJK equivalents. Falls back to clause boundaries, then word boundaries.

2

Generate audio for each chunk

Sends each chunk to /v1/audio/speech sequentially with your saved voice.

3

Retry failed chunks

Exponential backoff (1s, 2s, 4s) with up to 3 retries per chunk.

4

Concatenate with silence gaps

Inserts 400ms of silence between chunks (WAV/PCM only) and produces a single audio file.

Quick Example

typescript
import { MurmrClient } from '@murmr/sdk';
import { writeFileSync } from 'fs';

const client = new MurmrClient({ apiKey: process.env.MURMR_API_KEY! });

const result = await client.speech.createLongForm({
  input: articleText,             // Any length
  voice: "voice_abc123",          // Saved voice ID
  language: "English",
  onProgress: ({ current, total, percent }) => {
    console.log(`Chunk ${current}/${total} (${percent}%)`);
  },
});

writeFileSync("article.wav", Buffer.from(result.audio));
console.log(`Generated ${result.totalChunks} chunks, ${result.durationMs}ms total`);

Saved voices only

Long-form generation uses saved voices (via voice ID or voice_clone_prompt). VoiceDesign descriptions are not supported because each chunk would produce a slightly different voice. Save a voice first.

Text Chunking Strategy

The SDK splits text intelligently to preserve natural speech flow. It never splits mid-sentence.

PriorityBoundary TypeCharacters
1 (best)Sentence endings. ! ? (and CJK: 。 ! ?)
2Clause boundaries, ; : — (and CJK: 、 ; :)
3 (fallback)Word boundariesWhitespace

The default chunk size is 3,500 characters (configurable from 100 to 4,096). Keeping it below the 4,096 API limit leaves room for sentence-boundary splitting to work effectively.

typescript
// You can also use the chunker standalone
import { splitIntoChunks } from '@murmr/sdk';

const chunks = splitIntoChunks(longText, 3500);
console.log(`Split into ${chunks.length} chunks`);

Audio Format Considerations

FormatSilence GapsConcatenationBest For
WAVYes (PCM silence)Header-awareHighest quality, editing
PCMYes (raw silence)Raw concatenationProcessing pipelines
MP3NoBinary concatenationWeb delivery, small files
OpusNoBinary concatenationStreaming, real-time
AACNoBinary concatenationMobile apps
FLACNoBinary concatenationLossless archival

Silence gaps require WAV or PCM

The silenceBetweenChunksMs option only works with WAV and PCM formats. Compressed formats (MP3, Opus, AAC, FLAC) are binary-concatenated without silence gaps. If natural pauses between sections matter, use WAV.

Parameters

ParameterTypeDescription
inputrequiredstringText of any length. Automatically chunked at sentence boundaries.
voicerequiredstringSaved voice ID (e.g. "voice_abc123").
voice_clone_promptstringBase64-encoded voice embedding. Takes precedence over voice if set.
languagestringOutput language.
response_formatAudioFormatAudio format: mp3, opus, aac, flac, wav, or pcm.
chunkSizenumberMax characters per chunk. Range: 100–4096.
silenceBetweenChunksMsnumberMilliseconds of silence between chunks. WAV and PCM only.
maxRetriesnumberRetry count per chunk. Exponential backoff: 1s, 2s, 4s.
startFromChunknumberResume from a specific chunk index after failure.
onProgress(progress) => voidProgress callback. Receives { current, total, percent }.

Return Value

typescript
interface LongFormResult {
  audio: Buffer;          // Concatenated audio with silence gaps
  totalChunks: number;    // Number of chunks processed
  durationMs: number;     // Total audio duration in ms
  format: AudioFormat;    // Audio format used
  characterCount: number; // Total characters processed
}

Resuming After Failure

If a chunk fails after all retries, a MurmrChunkError is thrown with the exact chunk index. Use startFromChunk to resume without re-generating completed chunks.

typescript
import { MurmrChunkError } from '@murmr/sdk';

try {
  const result = await client.speech.createLongForm({
    input: bookChapter,
    voice: "voice_abc123",
  });
} catch (err) {
  if (err instanceof MurmrChunkError) {
    console.log(`Failed at chunk ${err.chunkIndex}/${err.totalChunks}`);
    console.log(`${err.completedChunks} chunks completed successfully`);

    // Resume from the failed chunk
    const result = await client.speech.createLongForm({
      input: bookChapter,
      voice: "voice_abc123",
      startFromChunk: err.chunkIndex,
    });
  }
}

Note

When resuming, the SDK re-chunks the text identically (same input + same chunkSize = same chunks). Skipped chunks still fire onProgress callbacks so your progress UI stays accurate.

Tuning Tips

Chunk size

Larger chunks (3,5004,000) produce more natural prosody across sentences. Smaller chunks (5001,000) reduce the impact of a single chunk failure but may produce more noticeable transitions.

Silence between chunks

The default 400ms works well for paragraph transitions. Try 200ms for continuous narration or 600800ms for distinct sections. Set to 0 for seamless concatenation.

Character usage

Each chunk counts against your monthly character quota. A 10,000-character article split into 3 chunks uses 10,000 characters from your plan, not 3 requests.

See Also