Renderz Studio
Academia
Proyectos
Servicios
Arsenal
Repo
Herramientas
Skills
El Oráculo
Guía Gratis
← El Arsenal
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

Speech-to-Text

Transcribir audio con Whisper

Text-to-Speech

Sintetizar voz con ElevenLabs

Pipeline completo

Voice assistant end-to-end

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' },
  })
}

Guías relacionadas

Streaming en Tiempo Real

Respuestas de voz en streaming

Videos con Remotion

Voiceovers para videos

¿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 · €29

PayPal · Acceso inmediato

¿Hablamos?