Guía de inicio rápido de Speech Engine

Añade voz a tu agente de chat con el SDK de ElevenLabs.

Esta guía te explica cómo crear un agente de voz con Speech Engine. Configurarás un servidor que conecta tu LLM a ElevenLabs y, después, un cliente en el navegador para que usuarios puedan mantener conversaciones por voz con tu agente.

Usa la skill de ElevenLabs Speech Engine para añadir voz a tu agente de chat:

npx skills add elevenlabs/skills --skill speech-engine

Cómo funciona Speech Engine

Speech Engine conecta tu LLM a ElevenLabs para que usuarios puedan hablar con tu agente y escuchar su respuesta. ElevenLabs se encarga de convertir voz a texto y texto a voz; tu servidor proporciona la lógica del LLM.

Cada conexión WebSocket representa una conversación. Cuando el usuario habla, ElevenLabs transcribe el audio y envía la transcripción a tu servidor. Tu servidor la pasa a tu LLM y, después, transmite la respuesta. ElevenLabs convierte el texto en voz y lo reproduce en el navegador. El SDK gestiona las conexiones, los turnos de conversación y la detección de interrupciones.

Requisitos previos

Este tutorial usa la API de OpenAI para el LLM. Necesitas una clave de API de OpenAI configurada en la variable de entorno OPENAI_API_KEY.

Configuración del servidor

1

Crea una clave de API

Crea una clave de API aquí, en el panel, que usarás para acceder a la API de forma segura.

Guarda la clave como un secreto gestionado y pásala a los SDK como variable de entorno mediante un archivo .env, o directamente en la configuración de tu aplicación, según prefieras.

.env
ELEVENLABS_API_KEY=<your_api_key_here>
2

Instala las dependencias

pip install elevenlabs openai python-dotenv
3

Expón el servidor

Speech Engine necesita una URL accesible públicamente. Usa ngrok para exponer tu servidor local. El servidor aún no está creado, pero ngrok debe estar ejecutándose primero para que tengas la URL para el siguiente paso.

ngrok http 3001

Copia la URL de reenvío (por ejemplo, https://abc123.ngrok.io).

4

Crea una instancia de Speech Engine

Usa el SDK para crear una instancia de Speech Engine y pasa como URL de WebSocket tu URL de ngrok con la ruta /ws añadida.

import asyncio
from dotenv import load_dotenv
from elevenlabs import AsyncElevenLabs
load_dotenv()
elevenlabs = AsyncElevenLabs(
api_key=os.getenv("ELEVENLABS_API_KEY"),
)
async def main():
engine = await elevenlabs.speech_engine.create(
name="My Speech Engine",
speech_engine={
# Note we use the wss protocol instead of https
"ws_url": "wss://abc123.ngrok.io/ws",
},
)
print(f"Speech Engine ID: {engine.engine_id}")
if __name__ == "__main__":
asyncio.run(main())

Ejecuta este script y copia el ID de Speech Engine (por ejemplo, seng_8k3m9xr4hjnfg983brhmhkd98n6) para el siguiente paso.

5

Crea el servidor

Crea un archivo llamado server.py o server.mts con el siguiente contenido. Configura un servidor, conecta Speech Engine en la ruta /ws y usa OpenAI para generar respuestas.

import asyncio
import os
from dotenv import load_dotenv
from openai import AsyncOpenAI
from elevenlabs import AsyncElevenLabs
load_dotenv()
# Replace with your Speech Engine ID from step 4
SPEECH_ENGINE_ID = "seng_8k3m9xr4hjnfg983brhmhkd98n6"
openai = AsyncOpenAI(
api_key=os.getenv("OPENAI_API_KEY"),
)
elevenlabs = AsyncElevenLabs(
api_key=os.getenv("ELEVENLABS_API_KEY"),
)
def on_init(conversation_id, session):
print(f"Session started: {conversation_id}")
async def on_transcript(transcript, session):
stream = await openai.responses.create(
model="gpt-4o",
instructions="You are a helpful voice assistant. Keep responses concise and conversational.",
input=[
{"role": "assistant" if m.role == "agent" else m.role, "content": m.content}
for m in transcript
],
stream=True,
)
await session.send_response(stream)
def on_close(session):
print(f"Session ended: {session.conversation_id}")
def on_error(err, session):
print(f"Error: {err}")
async def main():
engine = await elevenlabs.speech_engine.get(SPEECH_ENGINE_ID)
await engine.serve(
port=3001,
path="/ws",
debug=True,
on_init=on_init,
on_transcript=on_transcript,
on_close=on_close,
on_error=on_error,
)
if __name__ == "__main__":
asyncio.run(main())

El callback onTranscript / on_transcript recibe el historial completo de la conversación y la sesión actual. El SDK de TypeScript también proporciona un AbortSignal que se activa si el usuario interrumpe durante una respuesta. Al pasar signal a la llamada de OpenAI, la solicitud al LLM se cancela automáticamente cuando hay una interrupción.

sendResponse() / send_response() acepta una cadena, un iterable asíncrono o un stream de OpenAI, Anthropic o Google Gemini. El SDK extrae automáticamente el contenido de texto.

En el ejemplo anterior, se pasa al LLM la transcripción completa del usuario. En un entorno de producción, deberías añadir medidas de protección para evitar intentos de inyección o manipulación de prompts.

6

Inicia el servidor

python server.py

Configuración del cliente

1

Instala el SDK del cliente

npm install @elevenlabs/react
2

Crea una ruta de token

Añade una ruta del lado del servidor que genere un token de conversación. Así tu clave de API no se expone en el navegador y se usa WebRTC para obtener la mejor calidad de audio.

import os
from dotenv import load_dotenv
from flask import Flask, jsonify
from elevenlabs import ElevenLabs
load_dotenv()
app = Flask(__name__)
elevenlabs = ElevenLabs(
api_key=os.getenv("ELEVENLABS_API_KEY"),
)
@app.route("/api/token")
def get_token():
# Replace with your Speech Engine ID from step 4 of the server setup
speech_engine_id = "seng_8k3m9xr4hjnfg983brhmhkd98n6"
response = elevenlabs.conversational_ai.conversations.get_webrtc_token(
agent_id=speech_engine_id,
)
return jsonify(token=response.token)
if __name__ == "__main__":
app.run(port=3002)
3

Crea la interfaz de conversación

Obtén el token de conversación de tu servidor y úsalo para iniciar una sesión.

App.tsx
import { useConversation } from "@elevenlabs/react";
import { useCallback } from "react";
async function getToken(): Promise<string> {
const response = await fetch("/api/token");
if (!response.ok) {
throw Error("Failed to get conversation token");
}
const data = await response.json();
return data.token;
}
export default function App() {
const conversation = useConversation({
onConnect: () => console.log("Connected"),
onDisconnect: () => console.log("Disconnected"),
onError: (error: Error) => console.error("Error:", error),
});
const startConversation = useCallback(async () => {
await navigator.mediaDevices.getUserMedia({ audio: true });
const token = await getToken();
await conversation.startSession({ conversationToken: token });
}, [conversation]);
const stopConversation = useCallback(async () => {
await conversation.endSession();
}, [conversation]);
return (
<div>
<p>Status: {conversation.status}</p>
<button onClick={startConversation} disabled={conversation.status === "connected"}>
Start conversation
</button>
<button onClick={stopConversation} disabled={conversation.status !== "connected"}>
End conversation
</button>
</div>
);
}
4

Pruébalo

Asegúrate de que hay tres procesos en ejecución:

  1. ngrok: reenvío al puerto 3001
  2. Tu servidor de Speech Engine: python server.py o npx tsx server.mts
  3. El servidor de tokens: npx tsx token-server.mts o python token_server.py

Abre tu aplicación cliente en el navegador y haz clic en Iniciar conversación. Concede acceso al micrófono cuando se te solicite y empieza a hablar. Deberías oír la respuesta del agente por los altavoces.

Si tienes debug: true activado en el servidor, verás las transcripciones entrantes y las respuestas salientes registradas en la consola.

Eventos de sesión

EventoCallback de TypeScriptCallback de PythonDescripción
user_transcriptonTranscripton_transcriptVoz del usuario transcrita. Incluye el historial completo de la conversación y una señal de cancelación.
initonIniton_initSesión inicializada con un ID de conversación.
closeonCloseon_closeDesconexión correcta de ElevenLabs.
disconnectedonDisconnecton_disconnectConexión WebSocket interrumpida inesperadamente.
erroronErroron_errorError de protocolo o de WebSocket.

Configuración del primer mensaje del agente

De forma predeterminada, el agente espera a que el usuario hable primero. Para que el agente salude al usuario cuando empiece la conversación, configura un primer mensaje en la opción overrides del cliente al iniciar la sesión.

1

Para permitir que el agente hable primero, debemos actualizar el recurso de Speech Engine para permitir configurarlo desde el cliente.

engine = await elevenlabs.speech_engine.update(
speech_engine_id="seng_8k3m9xr4hjnfg983brhmhkd98n6",
overrides={
"first_message": True,
},
)
2

Después configuramos el primer mensaje en el SDK del cliente.

conversation.startSession({
conversationToken: token,
overrides: {
agent: {
firstMessage: "Hello! How can I help you today?",
},
},
});

El agente pronuncia el primer mensaje en cuanto se establece la conexión. No activa el callback onTranscript en tu servidor; se gestiona por completo en ElevenLabs.

Siguientes pasos