如果你正在做一个“能听会说”的 AI 应用,比如语音客服、会议助手、口语陪练、智能硬件语音交互,大概率会把“实时音视频通信”和“大模型 Agent”当作两条独立的技术路线来处理:一条用 WebRTC 解决音视频传输,另一条用 LangChain、OpenAI Function Calling 之类的框架写 Agent 逻辑。做完之后才发现,真正麻烦的不是单点功能,而是把这两条链路无缝接起来。

LiveKit Agents 就是冲着这个痛点来的。它不是一个单独的大模型应用框架,也不是一个新的音视频协议,而是把实时音视频基础设施和 AI Agent 运行时整合到了一套开发模型里。你可以把它理解成一个“给实时音视频房间装上 AI 大脑”的官方解决方案:开发者不需要自己处理音频流的采集、发布、订阅、打断、回声消除、语音活动检测,只要写 Agent 的业务逻辑,剩下的交给框架。

这篇文章会用一套完整思路讲清楚 LiveKit Agents 到底是什么、它适合谁、它解决了哪些实际工程问题,并给出一个可运行的最小语音助手示例。读完你可以判断:自己的项目要不要选它,以及真上生产时哪些地方最容易翻车。

1. 做实时语音 Agent,难点到底在哪

很多团队一开始以为,做一个语音 AI 助手就是把“语音转文字 + 大模型 + 文字转语音”三段拼接起来。这个想法方向没错,但一旦进入真实的实时对话场景,就会遇到单点拼接解决不了的问题。

1.1 语音链路不是三段,而是十段

从用户开口说话,到 Agent 的声音传到用户耳朵里,中间至少包含这么几个环节:

  • 音频采集:麦克风拿到原始 PCM 数据。
  • 前端处理:回声消除、降噪、自动增益。
  • 网络传输:把音频实时送到服务器,再送到对端。
  • 语音活动检测:识别用户什么时候开始说话、什么时候说完。
  • 流式语音识别:边说话边出文字,而不是等整段说完。
  • 大模型推理:基于上下文生成回复。
  • 流式语音合成:一边生成文字一边合成声音,减少等待。
  • 音频播放:把回复音频实时推回客户端。
  • 打断处理:用户插话时,Agent 要立刻停止当前回复。
  • 状态管理:对话历史、会话上下文、角色状态要贯穿始终。

如果这些全部自己写,相当于同时维护一个 WebRTC 服务端、一个实时音频处理管线、一个大模型编排系统。这不是不可能,但工程量非常大,而且每一步都有实时性要求,稍微处理不好就是几百毫秒到几秒的延迟。

1.2 传统方案的割裂感

传统开发方式通常分成两拨人:一拨人负责音视频网关,处理 WebRTC 连接、房间管理、媒体流转发;另一拨人负责 AI 服务,处理推理、对话、工具调用。两边通过 Webhook 或消息队列对接,问题就出在这里。

音视频网关对“音频帧”负责,AI 服务对“文本消息”负责,它们之间没有一个统一的、关于“对话轮次”和“说话状态”的抽象。于是会出现这些尴尬场景:

  • 用户在音频流里已经说完一句话,但服务端因为静音判断不准确,迟迟没有把这段语音送去识别。
  • Agent 开始回复时,不知道用户是不是已经结束说话,回复被直接打断。
  • 多方会议场景里,Agent 不知道该听谁的、该对谁说话。
  • 想控制 Agent 一次只回答一分钟内的问题,要自己维护定时器和队列。

这些问题不是单点功能缺失,而是缺乏一个“统一对话运行时”。LiveKit Agents 解决的正是这一层。

1.3 它的核心判断

LiveKit Agents 的核心判断是:实时 AI Agent 的开发,应该从“音视频房间”出发,而不是从“文本会话”出发。因为语音交互的天然载体就是一个实时通信房间,Agent 本身就是房间里的一个参与者,它订阅其他参与者的音视频轨道,处理后把结果发布回房间。

这个模型把“AI 服务”和“音视频基础设施”之间的边界打通了。Agent 不再通过 REST API 与音视频系统弱耦合对接,而是直接运行在音视频事件流里面,天然可以获得“谁在说话”“谁说完了”“轨道何时发布”“参与者何时加入”这些实时信息。

2. LiveKit 与 LiveKit Agents:基础概念和架构

要理解 LiveKit Agents,先理解 LiveKit 本身。

2.1 LiveKit:开源实时音视频基础设施

LiveKit 是一个开源的 WebRTC 基础设施项目,核心是一个用 Go 编写的 SFU(Selective Forwarding Unit)服务器。它提供房间管理、音视频轨道的发布与订阅、数据消息、Token 鉴权、录制、远端混合等功能。

可以这样理解:如果你的应用需要多人实时音视频通话,LiveKit 就是那个帮你管理“房间”的服务端。客户端通过 Token 鉴权后,进入某个房间,发布自己的摄像头、麦克风或屏幕共享轨道,同时订阅房间内其他人的轨道。LiveKit 负责转发媒体流和维持连接。

它既有云服务,也可以自托管。很多团队选择它是因为自托管成本可控,又比从零搭建 WebRTC 信令和媒体服务简单得多。

2.2 LiveKit Agents:AI Agent 的运行时

LiveKit Agents 是 LiveKit 官方推出的 AI Agent 框架,支持 Python 和 Node.js。它让开发者把大模型驱动的 Agent 注册为“房间里的参与者”,自动接收房间内音频流,经过语音识别、大模型推理、语音合成,再把生成的语音发布回房间。

这里几个关键概念必须理解清楚:

概念 通俗解释
Room 一个实时音视频会话空间,相当于一个“虚拟会议室”
Participant 房间里的参与者,可以是人,也可以是 Agent
Track 参与者发布的音频或视频流,比如麦克风轨道、Agent 回复轨道
Worker 一个常驻进程,负责接收 LiveKit 服务器分配的任务,启动 Agent
Job 一次 Agent 运行实例,比如一个用户进入房间后,Worker 启动一个对话任务
Agent 你写的 AI 逻辑,订阅轨道、处理、发布结果
Dispatch 决定 Agent 何时启动的一种机制,可以配置成有人进房间就自动启动

新手最容易把 Worker 和 Agent 混为一谈。Worker 是“运行环境”,Agent 是“业务逻辑”。一个 Worker 进程可以同时管理多个 Agent 实例,只要并发允许。

2.3 Agent 的软件栈

LiveKit Agents 自带了一个很实用的组件抽象层,把常见语音任务包装成可插拔插件:

  • VAD:语音活动检测,判断用户开始说话和结束说话。
  • STT:语音转文字。
  • LLM:大语言模型推理。
  • TTS:文字转语音。
  • 实时模型:像 OpenAI Realtime API 那样支持端到端语音对话的模型。

这意味着你可以自由组合供应商。比如用 Silero 做 VAD、Deepgram 做 STT、OpenAI 做 LLM、Cartesia 做 TTS;也可以换成你自建的模型服务。框架不锁定某一家厂商。

3. 环境准备与前置条件

在动手写代码之前,先把环境准备好。这一节偏实际操作,建议按顺序执行。

3.1 需要一个 LiveKit 服务端

你可以选择 LiveKit Cloud,也可以自托管 LiveKit Server。自托管时,官方推荐用 Docker 部署,但具体版本以官方仓库为准。这里演示通用的准备思路:

  1. 准备一个 LiveKit Server 地址,例如 wss://your-livekit-server.example.com 。
  2. 生成一套 API Key 和 API Secret。
  3. 保证客户端和 Agent Worker 都能访问到这个 Server。

如果是本地开发,LiveKit Server 支持通过 Docker Compose 快速启动,还需要配合 Redis 使用,因为 Agent 调度依赖它。自托管时,LiveKit Agents 要求 Server 开启 Agent 调度相关配置。

3.2 准备好模型和语音服务的 API Key

LiveKit Agents 本身不提供大模型能力,它负责把各家能力编排起来。所以你还需要:

  • 大模型服务商 API Key,例如 OpenAI。
  • 语音识别服务商 API Key,例如 Deepgram、Azure Speech 等。
  • 语音合成服务商 API Key,例如 Cartesia、ElevenLabs、OpenAI TTS 等。
  • VAD 模型一般可以本地加载,例如 Silero。

如果你只想先跑通流程,可以先用 silero 做 VAD,或使用框架内置的模拟插件,暂时不接真实 STT/TTS,先测试 Agent 能否被调度起来。

3.3 创建 Python 项目

LiveKit Agents 的 Python SDK 包名是 livekit-agents ,建议在虚拟环境里安装:

python -m venv .venv
source .venv/bin/activate
pip install livekit-agents livekit-plugins-openai livekit-plugins-deepgram livekit-plugins-cartesia livekit-plugins-silero

如果你用的是 Node.js,对应包名是 livekit-agents ,安装方式类似,但本文示例以 Python 为主。

3.4 配置环境变量

创建 .env 文件,把服务地址和密钥放进去。注意不要提交到代码仓库:

LIVEKIT_URL=wss://your-livekit-server.example.com
LIVEKIT_API_KEY=your_api_key
LIVEKIT_API_SECRET=your_api_secret

OPENAI_API_KEY=your_openai_key
DEEPGRAM_API_KEY=your_deepgram_key
CARTESIA_API_KEY=your_cartesia_key

这一步很关键,因为 Agent Worker 启动时要用 LIVEKIT_URL 、 LIVEKIT_API_KEY 、 LIVEKIT_API_SECRET 连接 LiveKit Server 注册自己。缺失这些配置,Worker 无法启动。

4. Agent 的工作流程:一句话从麦克风到音箱的旅程

理解 LiveKit Agents 的工作流程,最好的方式是跟着一个用户从“开口说话”到“听到回复”走一遍。

4.1 从用户进房到 Agent 注册

用户通过客户端 SDK 加入一个 Room,比如:

// 简化伪代码,实际要配合 LiveKit client SDK
const room = new Room();
await room.connect(token, { autoSubscribe: true });

当用户进入房间后,如果这个 Room 配置了 Agent Dispatch,LiveKit Server 会向注册的 Worker 队列发布一个 Job。Worker 收到 Job 后,启动 Agent 实例,Agent 以房间参与者的身份加入。

这一步很重要:Agent 是“实时加入房间”的,所以它能够获取到房间里已经发布的音频轨道。

4.2 订阅轨道与语音活动检测

Agent 加入房间后,根据 AutoSubscribe 策略自动订阅参与者的音频轨道。框架内置的 VAD 组件会持续分析音频流:

  • 检测到用户开始说话,VAD 从“静音”状态进入“讲话”状态。
  • 检测到用户停顿或说完,VAD 判定一个完整的语音片段结束。

VAD 的灵敏度直接影响体验。过于敏感,会在每个短停顿处打断识别;过于迟钝,用户说完很久 Agent 才反应。配置里通常有阈值参数,生产环境建议在目标场景里录一段真实对话来调参。

4.3 语音识别、LLM、语音合成

VAD 判定用户说完后,STT 组件把这段音频转成文字。文字被送入 LLM,框架会把历史对话作为上下文传入,保证多轮对话连贯。

LLM 生成回复文本后,TTS 组件把文本转成音频。框架根据生成进度和网络情况,边合成边发布音频轨道,用户不需要等整段话合成完才能听到。

这就绕开了“先录完整段再播放”的笨办法,显著降低首字延迟。

4.4 打断与并发控制

如果用户听到一半想插话,VAD 检测到新的语音输入,框架会触发打断机制:

  • 停止当前 TTS 播放。
  • 丢弃还没说完的合成音频。
  • 清空部分待处理的 LLM 生成状态。
  • 立即处理用户刚刚说出的新请求。

打断是语音助手最影响“拟人感”的功能。一个反应迟钝、只能等 Agent 说完才能继续说话的助手,体验是灾难性的。LiveKit Agents 把打断作为一等公民处理,这也是它相比“API 拼接方案”最大的优势之一。

5. 完整示例:一个可打断的语音助手 Agent

下面我们写一个最小但完整的语音助手 Agent。它使用 Silero 做 VAD,Deepgram 做 STT,OpenAI 做 LLM,Cartesia 做 TTS。如果你没有某些服务的 Key,可以先替换成模拟插件,重点是把框架流程跑通。

5.1 项目文件结构

建议使用下面的目录结构:

livekit-agent-demo/
├── .env
├── requirements.txt
└── agent.py

5.2 requirements.txt

livekit-agents
livekit-plugins-openai
livekit-plugins-deepgram
livekit-plugins-cartesia
livekit-plugins-silero

5.3 agent.py

import os
from dotenv import load_dotenv

from livekit.agents import (
    Agent,
    AgentSession,
    AutoSubscribe,
    JobContext,
    RoomInputOptions,
    RoomOutputOptions,
    WorkerOptions,
    cli,
    llm,
)
from livekit.plugins import cartesia, deepgram, openai, silero

load_dotenv()

SYSTEM_PROMPT = (
    "你是一个实时语音助手,说话简洁自然。"
    "回答要口语化,避免长篇大论。"
    "如果用户没有明确要求,不要输出列表或代码。"
)


class VoiceAssistant(Agent):
    def __init__(self) -> None:
        super().__init__(instructions=SYSTEM_PROMPT)


async def entrypoint(ctx: JobContext):
    # 连接房间,并仅自动订阅音频轨道
    await ctx.connect(auto_subscribe=AutoSubscribe.AUDIO_ONLY)

    # 创建 Agent 会话,装配 VAD/STT/LLM/TTS
    session = AgentSession(
        vad=silero.VAD.load(),
        stt=deepgram.STT(),
        llm=openai.LLM(),
        tts=cartesia.TTS(),
    )

    # 将 Agent 作为房间参与者启动
    await session.start(
        room=ctx.room,
        agent=VoiceAssistant(),
        room_input_options=RoomInputOptions(),
        room_output_options=RoomOutputOptions(),
    )


if __name__ == "__main__":
    cli.run_app(
        WorkerOptions(
            entrypoint_fnc=entrypoint,
            agent_name="voice-assistant-demo",
        )
    )

这段代码的核心逻辑集中在 entrypoint 函数里:

  1. ctx.connect(AutoSubscribe.AUDIO_ONLY) :Agent 加入房间,只订阅音频,不看视频,减少带宽和计算开销。
  2. AgentSession :把 VAD、STT、LLM、TTS 组合成一个可对话的运行环境。
  3. session.start :让 Agent 开始监听房间内参与者的语音输入,并发布回复音频。

这个示例没有写复杂的业务逻辑,但已经具备一个完整语音助手的基本骨架:进房、听话、思考、回话、被打断。

注意: openai.LLM() 默认使用 OpenAI 的 Chat Completions 接口,并开启流式输出。实际使用时,可以在参数里指定模型名,例如 openai.LLM(model="gpt-4o-mini") 。具体模型名称和可用范围以服务商为准。

5.4 运行 Worker

在项目根目录执行:

python agent.py dev

dev 是 livekit-agents CLI 提供的一个命令,它会读取本地 .env ,连接 LiveKit Server,并启动一个开发模式的 Worker。启动成功后,终端会输出 Worker 已连接、正在等待任务之类的日志。

如果日志显示无法连接 LiveKit Server,优先检查 LIVEKIT_URL 是否以 wss:// 或 ws:// 开头,以及 API Key 和 Secret 是否配对。

5.5 通过 Playground 测试交互

LiveKit 官方提供了一个基于浏览器的测试工具:Agents Playground。你可以打开测试页面,填写 LiveKit Server 地址和 Token 后连接,然后选择对应的 Agent,开始语音对话。

如果你没有现成的 Token,可以在服务端按 LiveKit 的权限规则生成。一个最小 Token 应该包含房间名、参与者身份、权限声明。Token 有效期不宜过长,生产环境一般限制在几分钟到几小时。

也可以用一段简单的 Python 代码调用服务端 SDK 生成 Token,但这部分需要结合你实际使用的 livekit-api 版本,建议以官方文档为准。

6. 运行与验证:怎样才能确认它真的跑通了

跑通和“真跑通”是两回事。很多人在本地启动 Worker 后,看到日志里出现“waiting for job”就觉得成功了。实际上这只能说明 Worker 连上了 LiveKit Server,并不能说明 Agent 能正常对话。建议按下面的顺序验证。

6.1 验证 Worker 注册成功

启动 Worker 后,日志中应该能看到类似“connected to LiveKit server”和“agent registered”的信息。如果 Worker 没有注册成功,后续所有进入房间的请求都不会触发 Agent。

6.2 验证 Agent 被调度

用一个客户端进入配置了 Agent Dispatch 的房间,观察 Worker 日志。如果调度成功,你会看到一条新的 Job 日志,里面包含任务 ID、房间名、参与者信息。这一步证明 LiveKit Server 能正确识别到了“该启动 Agent”的事件。

如果没有任何任务日志,很可能 Agent Dispatch 没有配置,或者房间名与 API 配置不匹配。可以在 LiveKit Server 配置里启用 Agent 调度,并为测试房间设置自动启动规则。

6.3 验证语音链路

在浏览器 Playground 里对 Agent 说一句“你好,现在几点”,正常反应是:

  1. 大约几百毫秒后,你看到语音转文字结果。
  2. Agent 开始有一段简短的语音回复。
  3. 你打断它,它能停下来处理新请求。

如果出现“文字识别出来了,但 Agent 没有回复”,大概率是 LLM 或 TTS 的 API Key 失效,或者模型配额不足。查日志时重点看 stt_completed 、 llm_start 、 llm_end 、 tts_start 、 tts_end 这几个事件。

6.4 通过日志排查

LiveKit Agents 默认会输出结构化日志。如果运行出现问题,第一步不是猜,而是看日志:

python agent.py dev -v

增加日志级别,可以看到更详细的媒体状态、VAD 事件和模型调用事件。在排查过程中,尽量保留完整错误堆栈,因为很多问题出在插件依赖版本不兼容上。

7. 常见问题与排查思路

根据社区常见问题,我整理了一张排查表。遇到问题时,先按表里说的顺序检查,能少走很多弯路。

问题现象 可能原因 排查方式 解决方案
Worker 启动失败,提示认证失败 LIVEKIT_API_KEY 或 LIVEKIT_API_SECRET 配置错误 检查 .env ,确认 Key 和 Secret 匹配 重新生成一套 API Key,确认环境变量生效
Worker 能启动,但用户进房后 Agent 不启动 Agent Dispatch 配置缺失 检查 LiveKit Server 配置,确认房间是否启用自动调度 为测试房间配置 Agent Dispatch,或手动触发 Job
Agent 进房后无响应 没有订阅到音频轨道 检查 AutoSubscribe 设置,确认客户端已发布麦克风轨道 改为 AutoSubscribe.AUDIO_ONLY ,确认客户端用了正确的设备
能识别到文字,但 Agent 不回复 LLM 或 TTS 服务报错 查看日志中的模型调用事件,检查 API Key 配额 更换或充值模型服务,确认模型名称存在
用户说话后长时间无反应 VAD 未检测到语音结束 查看 VAD 事件日志,调整灵敏度 调低静音阈值,或延长“结束等待时间”
语音回复被过早打断 VAD 把停顿误判为结束 调整 VAD 参数,观察用户语速 适当提高“结束判定”所需的静音时长
音质差,有回声 客户端没有启用回声消除 检查客户端音频配置 启用浏览器的自动增益和回声消除选项
Agent 回复内容过于书面化 LLM 提示词没有约束口语风格 修改 SYSTEM_PROMPT 在提示词里明确“口语化、简短、不要列点”
多人房间中 Agent 听错人 没有指定要收听的目标参与者 检查 AgentSession 的输入配置 按业务需求过滤参与者或指定目标 Participant

这些问题的共性是:大多数不在 Agent 业务代码本身,而在配置和依赖链路上。所以排查时不要一上来就怀疑框架有 Bug,先检查配置项。

8. 最佳实践与工程建议

本地跑通只是第一步。真要把它用到自己的产品里,有几个工程问题建议提前想清楚。

8.1 密钥和配置管理

不要把 API Key、Secret 写死在代码里,更不要提交到 Git 仓库。使用环境变量或密钥管理服务,比如 Docker Secret、云厂商的 Secret Manager、Vault。每次部署前检查是否需要轮换密钥。

8.2 Agent 会话的并发控制

一个 Worker 进程可以并发跑多个 Agent 实例。默认值可能不适合你的机器配置。如果 Agent 任务很重,尤其是本地加载 VAD 模型和调用大模型时,建议:

  • 设置合理的最大并发数。
  • 监控 CPU 和内存占用。
  • 部署多个 Worker,配合 LiveKit Server 做任务分发。

不要幻想一个 Worker 能扛住所有并发,它是异步的,但不是无限制的。

8.3 模型供应商的容灾与降级

语音链路里任何一个上游服务挂了,用户感受到都是“Agent 不说话”或者“转文字失败”。生产环境应该考虑:

  • 为 STT、LLM、TTS 配置多个供应商,或者至少准备一个备用 Key。
  • 检测模型调用超时,触发自动降级。
  • 捕获 Agent 生命周期异常,保证 Worker 不会因单个任务崩溃。

语音助手对可用性要求很高,因为用户正在“实时对话”,等不起 30 秒超时。

8.4 用户指令的多轮上下文管理

LiveKit Agents 会维护对话上下文,但上下文长度需要控制。你可以设置历史消息的保留条数,或者根据会话时长清理早期消息。否则对话时间一长,Token 消耗和模型延迟都会明显上升。

更合理的做法是:只保留最近若干轮对话,以及用户画像、关键偏好等结构化信息,避免把整场对话无脑塞给大模型。

8.5 日志、监控与追踪

实时 Agent 的故障排查,比普通 Web 服务难得多,因为你面对的是多条异步流水线。建议:

  • 记录 room_name 、 participant_id 、 job_id ,方便关联分析。
  • 对 VAD 开始、STT 结果、LLM 结束、TTS 开始等关键节点打点。
  • 把延迟指标发送到监控系统,比如首字延迟、STT 延迟、TTS 合成延迟。
  • 对会话做超时控制和资源回收,避免 Agent 实例泄漏。

没有可观测性的实时语音系统,一旦出问题就是黑盒。这个建议不是可选项,对生产项目来说是必选项。

8.6 测试与评测体系

很多团队把语音 Agent 上线后才发现,它在某些口音、某些语速、某些噪声环境下表现很不稳定。这跟传统的纯文本 Agent 评测很不一样:你需要跑语音评测。

可以借鉴“Agent evals”的思路:用一种半自动化的方式,把一批测试问题录成音频,批量跑 Agent,然后对比回复是否达到预期。这个方向还比较新,但对提升语音 Agent 质量非常有价值。建议在项目早期就搭建一套可重复执行的评测集,而不是靠人工聊几句验证。

8.7 安全与权限边界

Agent 本质上是“能听能说”的房间参与者,权限边界必须清晰:

  • 给 Agent 生成最小必要权限的 Token,不要使用管理员级别 Token。
  • 如果 Agent 可以调用外部工具,对工具调用加白名单和审计日志。
  • 涉及录音时,遵守隐私与合规要求,提前获得用户同意。

实时语音数据比文本日志更敏感。日志里避免打印原始音频内容和完整对话记录,确有必要时做脱敏处理。

9. 总结与后续学习方向

LiveKit Agents 这个项目选了一个很讨巧的角度:不重新发明音视频,不重新发明大模型,而是把二者之间的“粘连层”做扎实。它把实时音视频房间里最麻烦的那部分工程问题,打包成一套可插拔、可扩展的 Agent 运行时。对于想快速验证语音交互产品、或者不想从零维护 WebRTC + AI 双链路的团队来说,这是一个值得优先评估的方案。

如果你接下来想深入,建议按这个顺序实践:

  1. 先把上面的最小示例跑通,体验一次“用户进房 → Agent 自动接入 → 实时对话 → 打断回复”的完整流程。
  2. 然后用自己的音色或多个模型替换默认插件,看看延迟、音质、识别准确率分别有什么变化。
  3. 再接入你的业务场景,比如客服知识库、智能硬件控制、会议纪要助手,通过工具调用或 RAG 扩展 Agent 能力。
  4. 最后补上评测和监控体系,用真实会话数据持续优化 VAD 参数、提示词和模型选择。

语音 Agent 还在快速演进,今天看起来要手工调参的地方,未来可能会变成框架默认能力。但底层那套“音视频基础设施 + AI 运行时”的架构思路,短期内不大可能变。尽早理解它,对你做任何实时语音产品都有长期价值。

Logo

火山引擎视频云技术社区,是面向 AI 音视频开发者的技术交流平台。这里汇聚源自抖音、豆包等亿级 DAU 产品的 RTC、直播、点播、AI 媒体处理、音视频互动技术,提供接入指南、最佳实践、性能调优、场景案例、Demo 代码、开源项目、白皮书和 API 文档。社区汇聚官方工程师与一线开发者,为 AI 视频通话、数字人、AI 视频处理等应用的开发与落地提供技术支持。

更多推荐