Code Examples
Integration examples and code samples for Supernal TTS
📦 Supernal TTS Examples
:::note Development Examples These examples are based on the current development version of Supernal TTS. Code samples and API endpoints may change as the project evolves. Always refer to the latest documentation. :::
This section provides practical examples for integrating Supernal TTS into various applications and use cases.
🚀 Basic Examples
Simple Text-to-Speech
// Basic usage with mock provider (no API key needed)
const response = await fetch('https://tts.supernal.ai/api/v1/generate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
text: "Hello, this is a test of Supernal TTS!",
options: { provider: 'mock' }
})
});
const data = await response.json();
console.log('Audio URL:', data.audioUrl);
// Play the audio
const audio = new Audio(data.audioUrl);
audio.play();
With Real Provider
// Using OpenAI provider with custom voice
const response = await fetch('https://tts.supernal.ai/api/v1/generate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
text: "Welcome to our premium audio experience!",
options: {
provider: 'openai',
voice: 'fable',
speed: 1.1,
quality: 'high'
}
})
});
const data = await response.json();
console.log('Generated audio:', data);
🌐 Web Integration Examples
React Component
import React, { useState, useRef } from 'react';
const TTSComponent = () => {
const [isLoading, setIsLoading] = useState(false);
const [audioUrl, setAudioUrl] = useState(null);
const audioRef = useRef(null);
const generateAudio = async (text) => {
setIsLoading(true);
try {
const response = await fetch('https://tts.supernal.ai/api/v1/generate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
text,
options: {
provider: 'openai',
voice: 'nova'
}
})
});
const data = await response.json();
setAudioUrl(data.audioUrl);
} catch (error) {
console.error('TTS Error:', error);
} finally {
setIsLoading(false);
}
};
const playAudio = () => {
if (audioRef.current) {
audioRef.current.play();
}
};
return (
<div className="tts-component">
<textarea
placeholder="Enter text to convert to speech..."
onBlur={(e) => generateAudio(e.target.value)}
/>
{isLoading && <div>Generating audio...</div>}
{audioUrl && (
<div>
<audio ref={audioRef} src={audioUrl} controls />
<button onClick={playAudio}>Play Audio</button>
</div>
)}
</div>
);
};
export default TTSComponent;
Vue.js Component
<template>
<div class="tts-component">
<textarea
v-model="text"
placeholder="Enter text to convert..."
@blur="generateAudio"
/>
<div v-if="loading">Generating audio...</div>
<div v-if="audioUrl" class="audio-controls">
<audio :src="audioUrl" controls ref="audioPlayer" />
<button @click="playAudio">Play</button>
<button @click="downloadAudio">Download</button>
</div>
</div>
</template>
<script>
export default {
name: 'TTSComponent',
data() {
return {
text: '',
loading: false,
audioUrl: null
};
},
methods: {
async generateAudio() {
if (!this.text.trim()) return;
this.loading = true;
try {
const response = await fetch('https://tts.supernal.ai/api/v1/generate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
text: this.text,
options: {
provider: 'cartesia',
voice: 'confident-british-man',
speed: 1.0
}
})
});
const data = await response.json();
this.audioUrl = data.audioUrl;
} catch (error) {
console.error('TTS Error:', error);
} finally {
this.loading = false;
}
},
playAudio() {
this.$refs.audioPlayer.play();
},
downloadAudio() {
const link = document.createElement('a');
link.href = this.audioUrl;
link.download = 'audio.mp3';
link.click();
}
}
};
</script>
📱 Mobile App Examples
React Native
import React, { useState } from 'react';
import { View, Text, TextInput, TouchableOpacity, Alert } from 'react-native';
import { Audio } from 'expo-av';
const TTSScreen = () => {
const [text, setText] = useState('');
const [sound, setSound] = useState(null);
const [loading, setLoading] = useState(false);
const generateAndPlayAudio = async () => {
if (!text.trim()) return;
setLoading(true);
try {
// Generate audio
const response = await fetch('https://tts.supernal.ai/api/v1/generate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
text,
options: {
provider: 'openai',
voice: 'alloy',
format: 'mp3'
}
})
});
const data = await response.json();
// Play audio
const { sound: audioSound } = await Audio.Sound.createAsync(
{ uri: data.audioUrl }
);
setSound(audioSound);
await audioSound.playAsync();
} catch (error) {
Alert.alert('Error', 'Failed to generate audio');
console.error('TTS Error:', error);
} finally {
setLoading(false);
}
};
return (
<View style={{ padding: 20 }}>
<TextInput
value={text}
onChangeText={setText}
placeholder="Enter text to convert to speech..."
multiline
style={{
borderWidth: 1,
borderColor: '#ccc',
padding: 10,
marginBottom: 20,
minHeight: 100
}}
/>
<TouchableOpacity
onPress={generateAndPlayAudio}
disabled={loading}
style={{
backgroundColor: loading ? '#ccc' : '#007AFF',
padding: 15,
borderRadius: 5,
alignItems: 'center'
}}
>
<Text style={{ color: 'white' }}>
{loading ? 'Generating...' : 'Generate & Play'}
</Text>
</TouchableOpacity>
</View>
);
};
export default TTSScreen;
🖥️ Desktop App Examples
Electron App
// main.js
const { app, BrowserWindow, ipcMain } = require('electron');
const fetch = require('node-fetch');
const fs = require('fs');
const path = require('path');
let mainWindow;
function createWindow() {
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
});
mainWindow.loadFile('index.html');
}
// Handle TTS generation
ipcMain.handle('generate-tts', async (event, text, options) => {
try {
const response = await fetch('https://tts.supernal.ai/api/v1/generate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text, options })
});
const data = await response.json();
// Download audio file locally
const audioResponse = await fetch(data.audioUrl);
const audioBuffer = await audioResponse.buffer();
const audioPath = path.join(__dirname, 'temp', `${data.hash}.mp3`);
fs.writeFileSync(audioPath, audioBuffer);
return { ...data, localPath: audioPath };
} catch (error) {
throw new Error(`TTS Generation failed: ${error.message}`);
}
});
app.whenReady().then(createWindow);
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<title>TTS Desktop App</title>
</head>
<body>
<div>
<textarea id="textInput" placeholder="Enter text..."></textarea>
<button id="generateBtn">Generate Speech</button>
<audio id="audioPlayer" controls style="display: none;"></audio>
</div>
<script>
const { ipcRenderer } = require('electron');
document.getElementById('generateBtn').addEventListener('click', async () => {
const text = document.getElementById('textInput').value;
const audioPlayer = document.getElementById('audioPlayer');
try {
const result = await ipcRenderer.invoke('generate-tts', text, {
provider: 'openai',
voice: 'fable'
});
audioPlayer.src = result.localPath;
audioPlayer.style.display = 'block';
audioPlayer.play();
} catch (error) {
alert('Error: ' + error.message);
}
});
</script>
</body>
</html>
🤖 Bot Integration Examples
Discord Bot
const { Client, GatewayIntentBits } = require('discord.js');
const { joinVoiceChannel, createAudioPlayer, createAudioResource } = require('@discordjs/voice');
const fetch = require('node-fetch');
const client = new Client({
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.GuildVoiceStates]
});
client.on('messageCreate', async (message) => {
if (message.content.startsWith('!tts ')) {
const text = message.content.slice(5);
try {
// Generate audio
const response = await fetch('https://tts.supernal.ai/api/v1/generate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
text,
options: {
provider: 'cartesia', // Low latency for real-time
voice: 'confident-british-man'
}
})
});
const data = await response.json();
// Join voice channel and play
const voiceChannel = message.member.voice.channel;
if (voiceChannel) {
const connection = joinVoiceChannel({
channelId: voiceChannel.id,
guildId: message.guild.id,
adapterCreator: message.guild.voiceAdapterCreator,
});
const player = createAudioPlayer();
const resource = createAudioResource(data.audioUrl);
player.play(resource);
connection.subscribe(player);
}
} catch (error) {
message.reply('Sorry, I couldn\'t generate that audio.');
}
}
});
client.login('YOUR_BOT_TOKEN');
Slack Bot
const { App } = require('@slack/bolt');
const fetch = require('node-fetch');
const app = new App({
token: process.env.SLACK_BOT_TOKEN,
signingSecret: process.env.SLACK_SIGNING_SECRET
});
app.command('/tts', async ({ command, ack, respond }) => {
await ack();
const text = command.text;
if (!text) {
await respond('Please provide text to convert to speech.');
return;
}
try {
const response = await fetch('https://tts.supernal.ai/api/v1/generate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
text,
options: {
provider: 'openai',
voice: 'nova'
}
})
});
const data = await response.json();
await respond({
text: `🎙️ Generated audio for: "${text}"`,
attachments: [{
fallback: 'Audio file',
title: 'Click to play audio',
title_link: data.audioUrl,
color: 'good'
}]
});
} catch (error) {
await respond('Sorry, I couldn\'t generate that audio.');
}
});
(async () => {
await app.start(process.env.PORT || 3000);
console.log('⚡️ Slack TTS bot is running!');
})();
🎓 Educational Examples
E-Learning Platform
class LessonPlayer {
constructor(apiUrl) {
this.apiUrl = apiUrl;
this.currentLesson = null;
this.audioCache = new Map();
}
async loadLesson(lessonId) {
const lesson = await this.fetchLesson(lessonId);
this.currentLesson = lesson;
// Pre-generate audio for all lesson segments
await this.preGenerateAudio(lesson.segments);
}
async preGenerateAudio(segments) {
const promises = segments.map(async (segment) => {
if (this.audioCache.has(segment.id)) return;
try {
const response = await fetch(`${this.apiUrl}/api/v1/generate`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
text: segment.content,
options: {
provider: 'openai',
voice: 'fable',
speed: 0.9 // Slightly slower for learning
}
})
});
const data = await response.json();
this.audioCache.set(segment.id, data.audioUrl);
} catch (error) {
console.error(`Failed to generate audio for segment ${segment.id}`);
}
});
await Promise.all(promises);
}
async playSegment(segmentId) {
const audioUrl = this.audioCache.get(segmentId);
if (!audioUrl) {
throw new Error('Audio not available for this segment');
}
const audio = new Audio(audioUrl);
return new Promise((resolve) => {
audio.onended = resolve;
audio.play();
});
}
async playFullLesson() {
for (const segment of this.currentLesson.segments) {
await this.playSegment(segment.id);
// Pause between segments
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
}
// Usage
const player = new LessonPlayer('https://tts.supernal.ai');
await player.loadLesson('lesson-123');
await player.playFullLesson();
📰 Content Management Examples
Blog Audio Generation
class BlogAudioManager {
constructor(apiUrl) {
this.apiUrl = apiUrl;
}
async generateBlogAudio(blogPost) {
// Extract and clean content
const content = this.extractContent(blogPost);
// Split into manageable chunks
const chunks = this.splitIntoChunks(content, 4000);
// Generate audio for each chunk
const audioSegments = await Promise.all(
chunks.map((chunk, index) => this.generateChunkAudio(chunk, index))
);
// Combine metadata
return {
blogId: blogPost.id,
totalDuration: audioSegments.reduce((sum, seg) => sum + seg.duration, 0),
segments: audioSegments,
generatedAt: new Date().toISOString()
};
}
extractContent(blogPost) {
// Remove HTML tags and extract readable content
let content = blogPost.content
.replace(/<[^>]*>/g, '') // Remove HTML tags
.replace(/\s+/g, ' ') // Normalize whitespace
.trim();
// Add title and meta information
content = `${blogPost.title}. ${content}`;
return content;
}
splitIntoChunks(text, maxLength) {
const chunks = [];
const sentences = text.split(/[.!?]+/);
let currentChunk = '';
for (const sentence of sentences) {
if (currentChunk.length + sentence.length > maxLength) {
if (currentChunk) {
chunks.push(currentChunk.trim());
currentChunk = '';
}
}
currentChunk += sentence + '. ';
}
if (currentChunk) {
chunks.push(currentChunk.trim());
}
return chunks;
}
async generateChunkAudio(text, index) {
const response = await fetch(`${this.apiUrl}/api/v1/generate`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
text,
options: {
provider: 'openai',
voice: 'fable',
quality: 'high'
},
metadata: {
chunkIndex: index,
contentType: 'blog'
}
})
});
return await response.json();
}
}
// Usage
const audioManager = new BlogAudioManager('https://tts.supernal.ai');
const blogPost = {
id: 'post-123',
title: 'Introduction to AI',
content: '<p>Artificial Intelligence is...</p>'
};
const audioData = await audioManager.generateBlogAudio(blogPost);
console.log('Generated audio:', audioData);
🎮 Gaming Examples
Game Dialogue System
class GameDialogueSystem {
constructor(apiUrl) {
this.apiUrl = apiUrl;
this.characterVoices = {
'hero': { provider: 'openai', voice: 'nova' },
'villain': { provider: 'cartesia', voice: 'barbershop-man' },
'narrator': { provider: 'openai', voice: 'fable' },
'npc': { provider: 'azure', voice: 'en-US-JennyNeural' }
};
this.audioCache = new Map();
}
async preloadDialogue(dialogueTree) {
const promises = [];
for (const node of dialogueTree.nodes) {
for (const line of node.lines) {
promises.push(this.generateDialogueLine(line));
}
}
await Promise.all(promises);
}
async generateDialogueLine(line) {
const cacheKey = `${line.character}-${line.id}`;
if (this.audioCache.has(cacheKey)) {
return this.audioCache.get(cacheKey);
}
const voiceConfig = this.characterVoices[line.character] || this.characterVoices['npc'];
try {
const response = await fetch(`${this.apiUrl}/api/v1/generate`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
text: line.text,
options: {
...voiceConfig,
speed: line.emotion === 'excited' ? 1.2 : 1.0
},
metadata: {
character: line.character,
emotion: line.emotion,
lineId: line.id
}
})
});
const data = await response.json();
this.audioCache.set(cacheKey, data);
return data;
} catch (error) {
console.error(`Failed to generate dialogue for ${line.character}:`, error);
return null;
}
}
async playDialogue(lineId, character) {
const cacheKey = `${character}-${lineId}`;
const audioData = this.audioCache.get(cacheKey);
if (!audioData) {
console.error('Audio not found for dialogue line');
return;
}
const audio = new Audio(audioData.audioUrl);
// Add character-specific audio effects
if (character === 'villain') {
// Add reverb or distortion effect
const audioContext = new AudioContext();
const source = audioContext.createMediaElementSource(audio);
const reverb = audioContext.createConvolver();
source.connect(reverb);
reverb.connect(audioContext.destination);
}
return new Promise((resolve) => {
audio.onended = resolve;
audio.play();
});
}
}
// Usage in game
const dialogueSystem = new GameDialogueSystem('https://tts.supernal.ai');
const gameDialogue = {
nodes: [
{
id: 'intro',
lines: [
{ id: 'intro-1', character: 'narrator', text: 'Welcome to the adventure!', emotion: 'neutral' },
{ id: 'intro-2', character: 'hero', text: 'I\'m ready for this quest!', emotion: 'excited' }
]
}
]
};
await dialogueSystem.preloadDialogue(gameDialogue);
await dialogueSystem.playDialogue('intro-1', 'narrator');
🔧 Utility Examples
Batch Processing Script
#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
const fetch = require('node-fetch');
class BatchTTSProcessor {
constructor(apiUrl, outputDir) {
this.apiUrl = apiUrl;
this.outputDir = outputDir;
this.processed = 0;
this.errors = 0;
}
async processTextFiles(inputDir) {
const files = fs.readdirSync(inputDir)
.filter(file => file.endsWith('.txt'));
console.log(`Found ${files.length} text files to process`);
for (const file of files) {
await this.processFile(path.join(inputDir, file));
}
console.log(`\nProcessing complete:`);
console.log(`- Processed: ${this.processed}`);
console.log(`- Errors: ${this.errors}`);
}
async processFile(filePath) {
const filename = path.basename(filePath, '.txt');
const outputPath = path.join(this.outputDir, `${filename}.mp3`);
// Skip if already processed
if (fs.existsSync(outputPath)) {
console.log(`Skipping ${filename} (already exists)`);
return;
}
try {
const text = fs.readFileSync(filePath, 'utf8');
console.log(`Processing ${filename}...`);
const response = await fetch(`${this.apiUrl}/api/v1/generate`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
text,
options: {
provider: 'openai',
voice: 'fable',
quality: 'high'
}
})
});
const data = await response.json();
// Download audio file
const audioResponse = await fetch(data.audioUrl);
const audioBuffer = await audioResponse.buffer();
fs.writeFileSync(outputPath, audioBuffer);
console.log(`✓ Generated ${filename}.mp3 (${data.duration}s)`);
this.processed++;
} catch (error) {
console.error(`✗ Failed to process ${filename}:`, error.message);
this.errors++;
}
}
}
// Usage
const processor = new BatchTTSProcessor('https://tts.supernal.ai', './output');
processor.processTextFiles('./input');
These examples demonstrate various integration patterns and use cases for Supernal TTS. For more specific implementations or custom requirements, check the API Reference or reach out for support.