Node.js TTS Integration: Complete Guide
Node.js is the most common runtime for TTS integrations. Here's how to build it right.
Installation
npm install @speeko/sdkBasic Request
import { Speeko } from '@speeko/sdk';
const client = new Speeko({ apiKey: process.env.SPEEKO_KEY });
const audio = await client.tts({
text: 'Hello world',
voice: 'af_heart',
format: 'mp3'
});
await fs.promises.writeFile('output.mp3', audio);Express Integration
import express from 'express';
import { Speeko } from '@speeko/sdk';
const app = express();
const speeko = new Speeko({ apiKey: process.env.SPEEKO_KEY });
app.use(express.json());
app.post('/api/tts', async (req, res) => {
try {
const { text, voice = 'af_heart' } = req.body;
if (!text || text.length > 5000) {
return res.status(400).json({ error: 'Invalid text' });
}
const audio = await speeko.tts({ text, voice });
res.set('Content-Type', 'audio/mpeg');
res.set('Cache-Control', 'public, max-age=31536000');
res.send(audio);
} catch (err) {
res.status(500).json({ error: err.message });
}
});
app.listen(3000);Streaming to Client
Pipe TTS output directly to the browser:
app.get('/api/tts/stream', async (req, res) => {
const { text } = req.query;
res.set({
'Content-Type': 'audio/mpeg',
'Transfer-Encoding': 'chunked'
});
const stream = speeko.ttsStream({ text, voice: 'af_heart' });
stream.on('data', chunk => res.write(chunk));
stream.on('end', () => res.end());
stream.on('error', err => {
console.error(err);
res.destroy();
});
});Client-Side Playback
<audio controls>
<source src="/api/tts/stream?text=Hello" type="audio/mpeg">
</audio>Fastify (Higher Performance)
import fastify from 'fastify';
import { Speeko } from '@speeko/sdk';
const app = fastify();
const speeko = new Speeko({ apiKey: process.env.SPEEKO_KEY });
app.post('/tts', {
schema: {
body: {
type: 'object',
required: ['text'],
properties: {
text: { type: 'string', maxLength: 5000 },
voice: { type: 'string' }
}
}
}
}, async (req, reply) => {
const audio = await speeko.tts(req.body);
reply.type('audio/mpeg').send(audio);
});
app.listen({ port: 3000 });Error Handling
try {
const audio = await speeko.tts({ text, voice });
} catch (err) {
if (err.code === 'rate_limit_exceeded') {
await sleep(err.retryAfter * 1000);
} else if (err.code === 'insufficient_credits') {
notifyBilling();
} else {
throw err;
}
}Production Checklist
- Use environment variables for API keys
- Enable request timeout (30s default is fine)
- Log request IDs for debugging
- Cache common phrases (see our caching article)
- Set up structured logging (pino recommended)
- Health check endpoint that calls TTS once an hour