ContenidoAvanzado40 min
Voice AI: Whisper + TTS
Speech-to-text · text-to-speech · ElevenLabs · pipelines de voz completos
VoiceWhisperTTS
✓ Guía gratuita · Acceso completo
Mapa rápido · salta al paso que te interese
01
Speech-to-Text con Whisper
Whisper de OpenAI es el estándar para transcripción. Soporta 99 idiomas, detecta el idioma automáticamente, y maneja acentos y ruido de fondo.
lib/voice/transcribe.ts
import OpenAI from 'openai'
import fs from 'fs'
const openai = new OpenAI()
export async function transcribeAudio(audioPath: string): Promise<string> {
const transcription = await openai.audio.transcriptions.create({
file: fs.createReadStream(audioPath),
model: 'whisper-1',
language: 'es', // Opcional: forzar idioma
response_format: 'text',
})
return transcription
}
// Con timestamps para subtítulos
export async function transcribeWithTimestamps(audioPath: string) {
const transcription = await openai.audio.transcriptions.create({
file: fs.createReadStream(audioPath),
model: 'whisper-1',
response_format: 'verbose_json',
timestamp_granularities: ['segment'],
})
return transcription.segments // Array con start, end, text
}Tip Pro
Para audio largo (+25MB), divide en chunks de 10 minutos. Whisper tiene límite de 25MB por request.
02
Text-to-Speech con ElevenLabs
lib/voice/synthesize.ts
const ELEVENLABS_API_KEY = process.env.ELEVENLABS_API_KEY!
const VOICE_ID = 'EXAVITQu4vr4xnSDxMaL' // Sarah - natural voice
export async function synthesizeSpeech(text: string): Promise<ArrayBuffer> {
const response = await fetch(
`https://api.elevenlabs.io/v1/text-to-speech/${VOICE_ID}`,
{
method: 'POST',
headers: {
'xi-api-key': ELEVENLABS_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
text,
model_id: 'eleven_multilingual_v2',
voice_settings: {
stability: 0.5,
similarity_boost: 0.75,
},
}),
}
)
return response.arrayBuffer()
}
// Alternativa: OpenAI TTS (más barato, menos natural)
export async function synthesizeWithOpenAI(text: string) {
const openai = new OpenAI()
const mp3 = await openai.audio.speech.create({
model: 'tts-1-hd',
voice: 'nova',
input: text,
})
return mp3.arrayBuffer()
}03
Pipeline completo: voice assistant
app/api/voice-chat/route.ts
import { transcribeAudio } from '@/lib/voice/transcribe'
import { synthesizeSpeech } from '@/lib/voice/synthesize'
import Anthropic from '@anthropic-ai/sdk'
const anthropic = new Anthropic()
export async function POST(req: Request) {
const formData = await req.formData()
const audioFile = formData.get('audio') as File
// 1. Guardar audio temporalmente
const buffer = await audioFile.arrayBuffer()
const tempPath = `/tmp/${Date.now()}.webm`
await Bun.write(tempPath, buffer)
// 2. Transcribir
const userText = await transcribeAudio(tempPath)
console.log('User said:', userText)
// 3. Procesar con LLM
const response = await anthropic.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 500,
messages: [{ role: 'user', content: userText }],
})
const assistantText = response.content[0].type === 'text'
? response.content[0].text
: ''
// 4. Sintetizar respuesta
const audioBuffer = await synthesizeSpeech(assistantText)
// 5. Devolver audio
return new Response(audioBuffer, {
headers: { 'Content-Type': 'audio/mpeg' },
})
}¿Quieres el sistema completo?
500+ páginas, 25 capítulos, código de producción, acceso a todas las guías del Arsenal.
Curso Completo · €29PayPal · Acceso inmediato