关于 realtime
这项 ElevenLabs Realtime 技能指导开发者配置 ElevenAgents 实时语音模式,或将基于 OpenAI Realtime SDK 的浏览器应用迁移到 ElevenLabs API。内容涵盖模型选择、限制检查、配置验证和迁移注意事项。
主要功能
- 01配置 ElevenAgents 实时语音模式
- 02比较 Mini 与 Max 模型适用条件
- 03检查合规与数据驻留限制
- 04发布并验证 Agent 配置
- 05迁移浏览器实时语音应用
适用场景
- 01为 ElevenAgents Agent 启用 Realtime 模型
- 02评估模型与工作区限制是否匹配
- 03将 OpenAI Realtime 浏览器应用改接 ElevenLabs
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ elevenlabs/ skills --skill realtime安装后在 Claude Code 中输入/realtime确认已加载。
附带文件references/browser-audio.mdreferences/session-config.md
详细介绍
ElevenLabs Realtime
Realtime 模型是 ElevenLabs 专为低延迟语音对话打造的模型。有两种使用方式:
- ElevenAgents Agent(Agent ID、控制面板,或带有
agent_configs/的elevenlabs agents项目):将 Agent 的 Voice mode 设置为 Realtime,并使用conversation_config.realtime_model,ElevenLabs 会管理其 LLM、TTS 模型和 ASR 设置。请参阅在 Realtime 模型上运行 Agent。 - 基于 OpenAI Realtime SDK 构建的浏览器应用:保留 SDK,并将其指向兼容 OpenAI 的 ElevenLabs Realtime API:
wss://api.elevenlabs.io/v1/convai/realtime。请参阅将应用从 OpenAI Realtime 迁移。
如果用户是从零开始,且无法确定他们想要哪种方式,请先询问。Agent 提供托管的系统提示词、工具、知识库、widget 和电话功能;Realtime API 则适合已经使用 OpenAI 实时事件的代码,是更快捷的选择。对于语音模式以外的 Agent 功能(提示词、工具、工作流、widget),请使用 agents 技能。
Models
| Model | Model ID | Optimized for |
|---|---|---|
| Eleven Realtime v1 Mini | eleven_realtime_v1_mini | 延迟和成本最低。默认选项。 |
| Eleven Realtime v1 Max | eleven_realtime_v1_max | 响应前会进行推理,适用于复杂指令和多步工具调用。成本较高。 |
从 Mini 开始。如果任务涉及较长或复杂的指令、多步工具调用,而 Mini 的响应不够理想,或者要迁移的应用使用了更大型的 OpenAI 模型来处理推理密集型任务,请选择 Max。Agent 还会受到合规性和数据驻留要求的限制;请参阅选择模型。
在 Realtime 模型上运行 Agent
每个语音 Agent 都有 Voice mode。在 Custom 模式下,Agent 的 LLM、TTS 模型和 ASR 设置分别单独选择。在 Realtime 模式下,Agent 使用 Realtime 模型运行,由 ElevenLabs 管理这些设置。此模式由一个字段控制:conversation_config.realtime_model 设置为模型 ID 时表示 Realtime,设置为 null 时表示 Custom。
系统提示词、第一条消息、语音、语言、温度、工具、知识库和对话流程设置(轮次积极程度、超时、中断)在两种模式下的工作方式相同。
开始之前
- 以下步骤会调用 ElevenLabs API。CLI 和 SDK 会从环境中读取
ELEVENLABS_API_KEY;如果尚未设置,请使用setup-api-key技能。绝不要要求用户在对话中粘贴密钥。 - Realtime 模型正在逐步开放。如果 API 因
Realtime models are not available for this workspace.而拒绝realtime_model,说明该工作区尚未获得访问权限。请停止操作并告知用户;修改配置无法解决此问题。
步骤 1:检查 Agent 是否能使用 Realtime
对于现有 Agent,先获取其配置(elevenlabs agents pull --agent <agent-id>,或在 SDK 中调用 agents.get)。将 Agent 保持在 Custom 模式;如果符合以下任一情况,请向用户说明原因:
| 阻碍 | 查看位置 |
|---|---|
| 自定义 LLM 或 Amazon Bedrock | conversation_config.agent.prompt.llm 为 custom-llm 或 Bedrock 模型 |
| 通过其他 ElevenLabs 产品创建,例如 Speech Engine | 如不确定,请询问用户;只有 ElevenAgents Agent 才能使用 Realtime 模型 |
| 需要特定的 LLM 或 TTS 模型 | 询问用户当前的 agent.prompt.llm 或 tts.model_id 是否为必需项 |
工作流节点覆盖了托管设置或 agent.prompt.max_tokens | Agent 的 workflow 下的节点覆盖项 |
| 与 Custom 模式的 Agent 相互转接 | 此 Agent 以及任何转接到此 Agent 的 Agent 上的 transfer_to_agent 工具和 agent_transfer 工作流节点 |
| 纯文本 Agent | conversation_config.conversation.text_only 为 true;Realtime 模型专为语音打造 |
可以移除工作流覆盖项,也可以将转接对象切换为 Realtime,但必须征得用户同意:这两项操作都会改变其设置中其他部分的行为。
步骤 2:选择模型
从 eleven_realtime_v1_mini 开始。如果 Agent 需要遵循冗长或复杂的指令、依赖多步工具调用且 Mini 的效果不够好,或者 Agent 必须符合 Zero Retention Mode 或 HIPAA 要求,则选择 eleven_realtime_v1_max。然后检查可用性:
| 环境 | eleven_realtime_v1_mini | eleven_realtime_v1_max |
|---|---|---|
| US | 可用 | 可用 |
| EU 数据驻留 | 可用 | 可用 |
| India 数据驻留 | 可用 | 不可用 |
| Singapore 数据驻留 | 可用 | 不可用 |
| Zero Retention Mode 和 HIPAA | 不可用 | 在 US 和 EU 可用 |
无论 Zero Retention Mode 是在工作区强制启用,还是在 Agent 上启用,均适用。如果项目中无法明确工作区的数据驻留或合规设置,请询问用户。如果 Agent 所处环境无法使用这两种模型,则将其保持在 Custom 模式。
Max 还要求 agent.prompt.max_tokens 至少为 1024,或设为 -1 表示不限制。
步骤 3:设置模型
对于现有 Agent,只更改 realtime_model;其余配置保持不变。
使用 CLI 拉取 Agent,在 agent_configs/ 下的文件中设置该字段,然后推送:
elevenlabs agents pull --agent <agent-id>
{
"conversation_config": {
"realtime_model": "eleven_realtime_v1_mini"
}
}
elevenlabs agents push --agent <agent-id>
使用 SDK:
from elevenlabs import ElevenLabs
elevenlabs = ElevenLabs()
elevenlabs.conversational_ai.agents.update(
agent_id="<agent-id>",
conversation_config={
"realtime_model": "eleven_realtime_v1_mini",
},
)
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";
const elevenlabs = new ElevenLabsClient();
await elevenlabs.conversationalAi.agents.update("<agent-id>", {
conversationConfig: {
realtimeModel: "eleven_realtime_v1_mini",
},
});
对于新 Agent,将 realtime_model(TypeScript 中为 realtimeModel)放入传递给 agents.create 的 conversation_config 中,与提示词、第一条消息和语音一并设置。不要为其选择 LLM 或 TTS 模型;Realtime Agent 会忽略这些模型。
若要关闭 Realtime,请将 realtime_model 设为 null(Python 中为 None)。Agent 将恢复使用其中存储的 LLM、TTS 模型和 ASR 设置。
由系统管理的设置
设置了 Realtime 模型时,Agent 会忽略 conversation_config 中这些字段的已存储值。Agent 切换到 Custom 后会重新使用这些值,因此不要清除它们,也不要为了调整 Realtime Agent 而修改它们:
| 设置 | 字段 |
|---|---|
| LLM | agent.prompt.llm |
| 推理力度 | agent.prompt.reasoning_effort |
| 思考预算 | agent.prompt.thinking_budget |
| 并行工具调用 | agent.prompt.enable_parallel_tool_calls |
| 级联超时 | agent.prompt.cascade_timeout_seconds |
| TTS 模型 | tts.model_id |
| 表现力模式 | tts.expressive_mode |
| ASR 提供方 | asr.provider |
agent.prompt.max_tokens 仍然生效。温度设置也仍然生效,但控制面板会在 Realtime 模式下隐藏该设置,因此请通过 CLI 或 API 修改。如果 Realtime 模型出错或未能及时响应,Agent 会回退到备用 LLM(LLM 级联);等待时长由 Realtime 模型设置决定。
步骤 4:发布并验证
步骤 1 中的规则会在发布 Agent 时检查,而不是在保存草稿时检查:违反规则的草稿仍可保存,但发布会失败,并指出需要更改的设置。
- 拉取 Agent,并确认
conversation_config.realtime_model中保存的是所选模型。如果推送、更新或用户在控制面板中的发布失败,请对照下方的错误说明。 - 找出所有会转接到此 Agent 的 Agent,并确认它们也处于 Realtime 模式。Custom 模式的 Agent 转接到 Realtime Agent 的问题,只有在该 Agent 下次发布时才会被发现;在此之前,转接会在对话中途被拒绝,呼叫者会留在当前 Agent。
- 让用户进行一次测试对话。
错误
| 错误 | 原因和解决方法 |
|---|---|
Realtime models are not available for this workspace. | 此工作区尚未获得访问权限。无需更改配置。 |
Transfers between default and Realtime model modes are not supported. | 不支持转接到或转接自 Custom 模式的 Agent(“default”表示 Custom)。将两个 Agent 设为相同模式。 |
| 错误中提及 Realtime 模型 | 根据 Agent 的合规性或数据驻留设置,该模型不可用。请参阅步骤 2。 |
| 发布失败,错误中提及某项设置 | 这是步骤 1 中的某项阻碍因素,或 Max 的令牌限制。更改该设置,或让 Agent 保持在 Custom 模式。 |
定价
Realtime Agent 按 ElevenAgents 标准分钟费率计费,此外还会按 Realtime 模型的费率对输入、缓存输入和输出令牌计费;Max 的每令牌费用高于 Mini。请引导用户前往 https://elevenlabs.io/pricing,而不要直接引用费率。
将应用从 OpenAI Realtime 迁移
ElevenLabs Realtime 使用与 OpenAI GA Realtime API 相同的线路协议:通过 WebSocket 传输相同的客户端和服务端事件。基于 OpenAI Realtime SDK 构建的应用会继续使用该 SDK;迁移需要更改凭据的生成方式、传输连接的 URL,以及模型、语音和会话配置。
唯一的结构性变化是:ElevenLabs Realtime 仅支持 WebSocket。在浏览器中,RealtimeSession 默认使用 WebRTC,由它负责连接麦克风和扬声器。切换到 WebSocket 传输后,应用必须自行采集和播放音频。
本文适用于由浏览器发起实时连接的应用。不适用于由服务端发起连接,并通过自己的协议(例如定制 WebSocket 中继或电话桥接)向客户端传输音频的应用。从服务端连接 ElevenLabs Realtime 应该可行,但本指南没有相关步骤。请告知用户这一点,并建议他们在 https://github.com/elevenlabs/skills 提交 issue 或 pull request,描述其设置,而不要猜测服务端迁移方式。
第 0 步:盘点应用
编辑前,找出应用中所有涉及 OpenAI Realtime 的位置:
grep -rnE "api\.openai\.com/v1/realtime|client_secrets|realtime/sessions|@openai/agents-realtime|@openai/agents/realtime|gpt-realtime|gpt-4o(-mini)?-realtime|OpenAIRealtimeWebRTC|OpenAIRealtimeWebSocket|RealtimeSession|OPENAI_API_KEY" --include='*.{ts,tsx,js,jsx,mjs,py}' .
对找到的内容进行分类,因为每一部分的迁移方式都不同:
- 凭据生成:调用
/v1/realtime/client_secrets(GA)或/v1/realtime/sessions(beta)的服务端路由。在第 1 步迁移。 - 浏览器会话:
RealtimeSession、OpenAIRealtimeWebRTC、OpenAIRealtimeWebSocket,或手动实现的WebSocket/RTCPeerConnection。在第 2 至第 4 步迁移。 - 服务端实时连接:由 Node 或 Python 进程自行建立实时套接字,例如通过自己的 WebSocket 协议向客户端传输音频的中继、电话桥接、
openaiPython 的client.realtime.connect(),或在 Node 中使用完整 API 密钥运行的RealtimeSession。本文不涉及此类情况;请参阅上述适用范围。如果应用也有浏览器会话,只在用户同意后迁移该部分。 - 语音对话以外的功能:函数工具、交接、护栏、MCP 服务、图像输入、SIP。ElevenLabs 仅记录了语音对话流程。保留这部分代码,告知用户这些功能尚未经过与 ElevenLabs 的兼容性验证,并让用户进行测试。
OPENAI_API_KEY 通常也用于其他 OpenAI 调用。只有在没有其他用途时才将其移除。
第 1 步:从 ElevenLabs 签发客户端密钥
浏览器不会接触 ElevenLabs API 密钥。服务端路由会签发一个短期有效的客户端密钥,并且只返回它的 value。
| 内容 | OpenAI | ElevenLabs |
|---|---|---|
| URL | POST https://api.openai.com/v1/realtime/client_secrets | POST https://api.elevenlabs.io/v1/convai/realtime/client_secrets |
| Auth header | Authorization: Bearer $OPENAI_API_KEY | xi-api-key: $ELEVENLABS_API_KEY |
session.model | gpt-realtime,…… | eleven_realtime_v1_mini 或 eleven_realtime_v1_max |
| 响应 | { value, expires_at, session } | 结构相同 |
请求正文保持 GA 结构 { session, expires_after }。此处发送的 session 配置是该凭证的权威初始 session。model 字符串会直接选择 Agent 行为;这里没有 agent_id。
使用 ElevenLabs SDK 签发(npm install @elevenlabs/elevenlabs-js 或 pip install elevenlabs),SDK 会代你发送 xi-api-key 标头:
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";
const elevenlabs = new ElevenLabsClient();
const clientSecret =
await elevenlabs.conversationalAi.realtime.createClientSecret({
session: {
type: "realtime",
model: "eleven_realtime_v1_mini",
instructions:
"You are a helpful, friendly voice assistant. Keep replies concise.",
outputModalities: ["audio"],
audio: {
input: {
format: { type: "audio/pcm", rate: 24000 },
turnDetection: { type: "semantic_vad", eagerness: "medium" },
},
output: {
format: { type: "audio/pcm" },
voice: "brian",
},
},
},
expiresAfter: { anchor: "created_at", seconds: 600 },
});
import os
from elevenlabs import (
CreateClientSecretRequest,
ExpiresAfter,
OpenAiAudioConfigInput,
OpenAiAudioInputConfigInput,
OpenAiAudioInputFormat,
OpenAiAudioOutputConfigInput,
OpenAiAudioOutputFormat,
OpenAiSessionConfigInput,
OpenAiTurnDetection,
)
from elevenlabs.client import ElevenLabs
elevenlabs = ElevenLabs(api_key=os.environ["ELEVENLABS_API_KEY"])
client_secret = elevenlabs.conversational_ai.realtime.create_client_secret(
request=CreateClientSecretRequest(
session=OpenAiSessionConfigInput(
type="realtime",
model="eleven_realtime_v1_mini",
instructions="You are a helpful, friendly voice assistant. Keep replies concise.",
output_modalities=["audio"],
audio=OpenAiAudioConfigInput(
input=OpenAiAudioInputConfigInput(
format=OpenAiAudioInputFormat(type="audio/pcm", rate=24000),
turn_detection=OpenAiTurnDetection(type="semantic_vad", eagerness="medium"),
),
output=OpenAiAudioOutputConfigInput(
format=OpenAiAudioOutputFormat(type="audio/pcm"),
voice="brian",
),
),
),
expires_after=ExpiresAfter(anchor="created_at", seconds=600),
),
)
只将 clientSecret.value(Python 中为 client_secret.value)返回给浏览器。
保留路由现有的框架、路径和响应约定;只更改上游调用。如果应用通过 beta /v1/realtime/sessions 端点签发密钥,其前端会读取 client_secret.value。你可以更新前端,让它读取顶层的 value;也可以让路由返回 { client_secret: { value } },这样前端就无需改动。
第 2 步:将 session 配置转换为 GA 结构
发送 GA session 结构。基于 OpenAI beta API 编写的应用使用扁平字段(modalities、voice、input_audio_format、turn_detection 等),需要将其转换;而且 ElevenLabs 会直接拒绝已弃用的 modalities 字段。这对于签发请求正文和任何手动编写的 session.update 尤其重要:SDK 的 config 选项会为你将已弃用的驼峰命名字段转换为 GA 线路格式,不过将它们也改为 GA 格式可以消除弃用警告。
请阅读Session 配置映射,了解完整的 beta 到 GA 字段对照表、语音处理方式,以及 SDK 的 config 选项使用的驼峰命名形式。
第 3 步:将浏览器 session 指向 ElevenLabs
将传输方式替换为指向 ElevenLabs URL 的 OpenAIRealtimeWebSocket,在 session 上设置模型,并将签发的 value 作为 API 密钥传入:
import {
OpenAIRealtimeWebSocket,
RealtimeAgent,
RealtimeSession,
} from "@openai/agents-realtime";
const { value: clientSecret } = await fetch("/api/token").then((res) =>
res.json(),
);
const agent = new RealtimeAgent({
name: "Assistant",
instructions:
"You are a helpful, friendly voice assistant. Keep replies concise.",
});
const transport = new OpenAIRealtimeWebSocket({
url: "wss://api.elevenlabs.io/v1/convai/realtime",
});
const session = new RealtimeSession(agent, {
transport,
model: "eleven_realtime_v1_mini",
config: {
outputModalities: ["audio"],
audio: { output: { voice: "brian" } },
},
});
await session.connect({ apiKey: clientSecret });
保留应用现有的 RealtimeAgent 名称、指令和事件处理程序。移除仅适用于 WebRTC 的选项(audioElement、mediaStream、changePeerConnection)以及任何 transport: "webrtc" 设置;WebSocket 没有对应选项。
第 4 步:接入音频(适用于原先使用 WebRTC 的应用)
如果应用之前使用 WebRTC(显式指定了 OpenAIRealtimeWebRTC、transport: "webrtc",或在浏览器中未指定传输方式),现在必须:
- 以 24 kHz 采集 PCM16 麦克风音频,并通过
session.sendAudio(...)流式发送。 - 播放 session 的
audio事件中的 PCM16 音频块。 - 在
audio_interrupted时停止播放。否则,用户插话后助手仍会继续说话,因为已缓冲的音频还会继续播放。 - 在拆卸时释放麦克风并关闭 session。
请阅读通过 WebSocket 传输浏览器音频,查看一个可运行的实现。它使用了 wavtools,这是 OpenAI 在其 WebSocket 示例中使用的辅助工具;文中还介绍了相关注意事项。
已经使用 OpenAIRealtimeWebSocket 的应用已完成这些接线;请检查采样率是否为 24 kHz,并保持不变。
第 5 步:验证
-
找出服务从哪里加载
OPENAI_API_KEY(.env、.env.local、部署密钥),并请用户将ELEVENLABS_API_KEY存放在那里。不要在对话中索要密钥,也不要自行将其写入文件。如果项目有.env.example,请添加空的ELEVENLABS_API_KEY=。 -
用户确认密钥已就位后,运行应用、开始对话并进行语音交流。
-
确认
session.created传输事件报告了eleven_realtime_*模型和所选语音:session.on("transport_event", (event) => { if (event.type === "session.created") console.log(event); }); -
在助手说到一半时打断它,并确认播放已停止。
-
告知用户第 0 步中的哪些功能仍未验证(工具、交接、防护措施等)。
故障排除
| 症状 | 原因和修复 |
|---|---|
WebSocket 以代码 4003 关闭 | 此 ElevenLabs 工作区未启用 Realtime。请联系 ElevenLabs;代码无法解决此问题。 |
WebSocket 以代码 4001 关闭 | 客户端密钥被拒绝:密钥已过期,或不是传递给 session.connect() 的已生成 value(作为 apiKey)。 |
| Mint 返回 401 | 仍在发送 Authorization: Bearer;ElevenLabs 使用 xi-api-key 标头。 |
Mint 或 session.update 被拒绝 | 使用了 Beta 格式的字段,例如 modalities。请根据映射进行转换。 |
| 已连接,但双方都没有音频 | 应用使用的是 WebRTC,且音频尚未接入。请参阅第 4 步。 |
| 音频是噪声、像花栗鼠一样快,或速度变慢 | 采样率或缓冲区不匹配。请以 24 kHz 采集和播放;音频参考中列出了相关注意事项。 |
| 助手在被打断后仍盖过用户说话 | 收到 audio_interrupted 时未停止播放。 |