Convenience utilities for audio playback and streaming. These Node.js-only functions simplify playing generated audio during development and testing.
Note: These utilities require Node.js and are not available in browser or edge runtime environments.
import { play, stream } from "@elevenlabs/elevenlabs-js";
// These are top-level utility functions, not client methodsPlay audio using ffplay (from ffmpeg suite).
/**
* Play audio using ffplay. Requires ffplay to be installed and in PATH.
* @param audio - AsyncIterable of audio chunks
* @returns Promise that resolves when playback completes
* @throws ElevenLabsError if not in Node.js or ffplay not found
*/
function play(audio: AsyncIterable<Uint8Array>): Promise<void>;Requirements:
Stream audio using mpv player.
/**
* Stream audio using mpv. Requires mpv to be installed and in PATH.
* @param audio - ReadableStream of audio chunks
* @returns Promise that resolves when streaming completes
* @throws ElevenLabsError if not in Node.js or mpv not found
*/
function stream(audio: ReadableStream<Uint8Array>): Promise<void>;Requirements:
import { ElevenLabsClient, play } from "@elevenlabs/elevenlabs-js";
const client = new ElevenLabsClient({ apiKey: "your-api-key" });
// Generate audio
const audio = await client.textToSpeech.convert("voice-id", {
text: "Hello, this will be played out loud!",
});
// Play audio through speakers
await play(audio);
console.log("Playback finished");import { ElevenLabsClient, stream } from "@elevenlabs/elevenlabs-js";
const client = new ElevenLabsClient({ apiKey: "your-api-key" });
// Generate streaming audio
const audioStream = await client.textToSpeech.stream("voice-id", {
text: "This is streaming audio playback.",
optimize_streaming_latency: 3,
});
// Stream to speakers
await stream(audioStream);
console.log("Streaming finished");// Quick test of voice quality
async function testVoice(voiceId: string, sampleText: string): Promise<void> {
const audio = await client.textToSpeech.convert(voiceId, {
text: sampleText,
});
console.log(`Playing sample with voice: ${voiceId}`);
await play(audio);
}
await testVoice("voice-id", "This is a sample of the voice.");// Play samples from multiple voices for comparison
async function compareVoices(
voiceIds: string[],
text: string
): Promise<void> {
for (const voiceId of voiceIds) {
console.log(`\nPlaying voice: ${voiceId}`);
const audio = await client.textToSpeech.convert(voiceId, {
text,
});
await play(audio);
// Pause between voices
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
await compareVoices(
["voice-1", "voice-2", "voice-3"],
"This is a comparison test."
);// Test different voice settings
async function testVoiceSettings(voiceId: string): Promise<void> {
const settings = [
{ stability: 0.3, similarity_boost: 0.5 },
{ stability: 0.5, similarity_boost: 0.75 },
{ stability: 0.8, similarity_boost: 0.9 },
];
for (const setting of settings) {
console.log(`\nTesting settings:`, setting);
const audio = await client.textToSpeech.convert(voiceId, {
text: "Testing voice settings.",
voice_settings: setting,
});
await play(audio);
await new Promise(resolve => setTimeout(resolve, 500));
}
}
await testVoiceSettings("voice-id");// Quick TTS testing during development
async function quickTest(text: string): Promise<void> {
const audio = await client.textToSpeech.convert(
process.env.DEFAULT_VOICE_ID!,
{ text }
);
await play(audio);
}
// Usage during development:
// await quickTest("Testing new feature");// Stream long-form content
async function streamLongContent(text: string): Promise<void> {
const audioStream = await client.textToSpeech.stream("voice-id", {
text,
optimize_streaming_latency: 4,
});
console.log("Starting playback...");
await stream(audioStream);
console.log("Finished");
}
await streamLongContent(
"This is a very long piece of text that will be streamed..."
);// Handle playback errors
async function safePlay(audio: AsyncIterable<Uint8Array>): Promise<void> {
try {
await play(audio);
} catch (error) {
if (error.message?.includes("ffplay")) {
console.error("ffplay not found. Please install ffmpeg.");
console.error("Install: https://ffmpeg.org/download.html");
} else {
console.error("Playback error:", error);
}
}
}// Check if playback utilities are available
import { spawn } from "child_process";
async function checkRequirements(): Promise<{
ffplay: boolean;
mpv: boolean;
}> {
const checkCommand = (cmd: string): Promise<boolean> => {
return new Promise((resolve) => {
const proc = spawn(cmd, ["--version"]);
proc.on("error", () => resolve(false));
proc.on("close", (code) => resolve(code === 0));
});
};
const [ffplay, mpv] = await Promise.all([
checkCommand("ffplay"),
checkCommand("mpv"),
]);
return { ffplay, mpv };
}
const available = await checkRequirements();
console.log("ffplay available:", available.ffplay);
console.log("mpv available:", available.mpv);// Add delay before playback
async function playWithDelay(
audio: AsyncIterable<Uint8Array>,
delayMs: number
): Promise<void> {
console.log(`Waiting ${delayMs}ms before playback...`);
await new Promise(resolve => setTimeout(resolve, delayMs));
console.log("Playing...");
await play(audio);
}
await playWithDelay(audio, 2000); // 2 second delay// Play multiple audio files in sequence
async function playQueue(
audioQueue: AsyncIterable<Uint8Array>[]
): Promise<void> {
for (let i = 0; i < audioQueue.length; i++) {
console.log(`Playing ${i + 1}/${audioQueue.length}...`);
await play(audioQueue[i]);
if (i < audioQueue.length - 1) {
// Brief pause between tracks
await new Promise(resolve => setTimeout(resolve, 500));
}
}
}
const queue = await Promise.all([
client.textToSpeech.convert("voice-id", { text: "First track" }),
client.textToSpeech.convert("voice-id", { text: "Second track" }),
client.textToSpeech.convert("voice-id", { text: "Third track" }),
]);
await playQueue(queue);// Test streaming latency
async function testStreamingLatency(): Promise<void> {
const latencies = [0, 1, 2, 3, 4];
for (const latency of latencies) {
console.log(`\nTesting latency optimization: ${latency}`);
const startTime = Date.now();
const audioStream = await client.textToSpeech.stream("voice-id", {
text: "Testing streaming latency optimization.",
optimize_streaming_latency: latency,
});
await stream(audioStream);
const duration = Date.now() - startTime;
console.log(`Total time: ${duration}ms`);
}
}
await testStreamingLatency();// Interactive testing prompt
import * as readline from "readline";
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
async function interactiveTest(voiceId: string): Promise<void> {
while (true) {
const text = await new Promise<string>((resolve) => {
rl.question("Enter text to speak (or 'quit' to exit): ", resolve);
});
if (text.toLowerCase() === "quit") {
rl.close();
break;
}
const audio = await client.textToSpeech.convert(voiceId, { text });
await play(audio);
}
}
// await interactiveTest("voice-id");import { writeFile } from "fs/promises";
// Option to save or play audio
async function saveOrPlay(
audio: AsyncIterable<Uint8Array>,
shouldPlay: boolean,
savePath?: string
): Promise<void> {
if (shouldPlay) {
await play(audio);
} else if (savePath) {
const chunks: Uint8Array[] = [];
for await (const chunk of audio) {
chunks.push(chunk);
}
await writeFile(savePath, Buffer.concat(chunks));
console.log("Saved to:", savePath);
}
}
// Play during development
await saveOrPlay(audio, true);
// Save in production
await saveOrPlay(audio, false, "output.mp3");macOS:
# Install ffmpeg (includes ffplay)
brew install ffmpeg
# Install mpv
brew install mpvUbuntu/Debian:
# Install ffmpeg
sudo apt-get install ffmpeg
# Install mpv
sudo apt-get install mpvWindows:
# Install using Chocolatey
choco install ffmpeg
choco install mpv