LiveKit Agents Browser 插件实战:基于 Chromium Embedded Framework 的浏览器实时自动化与 AI 代理
【免费下载链接】agentsA framework for building realtime voice AI agents 🤖🎙️📹项目地址: https://gitcode.com/GitHub_Trending/agen/agents
本文围绕 livekit-plugins-browser 插件 展开,介绍如何在 LiveKit Agents 实时语音/视频 Agent 体系中嵌入一个真实的 Chromium 浏览器内核(CEF),将网页画面与声音实时推入 LiveKit 房间,并通过 LLM 的 computer_use 工具驱动浏览器完成点击、输入、导航等操作。读完本文,你将掌握该插件的安装方式、核心 API(BrowserContext、BrowserSession、PageActions、BrowserAgent)的用法,以及人类用户与 AI 代理共享浏览器焦点的协作机制。
插件定位:为 LiveKit Agents 提供 Chromium 内核
livekit-plugins-browser是 LiveKit Agents 生态中的一个官方插件,其核心定位一句话即可概括:Chromium Embedded Framework (CEF) for LiveKit Agents(README)。它把 CEF 渲染出来的网页变成 LiveKit 房间里的一个"可被看到、可被听到、可被操作"的实时参与者:
- 看到:页面每一帧画面(
PaintData)以屏幕共享轨道的形式推流给房间内的所有参与者; - 听到:页面产生的音频(
AudioData)以屏幕共享音频轨道推流; - 可被操作:既支持人类用户通过数据通道直接注入鼠标、键盘、滚轮事件,也支持 AI Agent 通过 Anthropic computer_use 工具集执行截图、点击、输入等动作。
插件源码位于 livekit-plugins/livekit-plugins-browser/livekit/plugins/browser,__init__.py对外统一导出 7 个符号:AudioData、BrowserAgent、BrowserContext、BrowserPage、BrowserSession、PageActions、PaintData。其中BrowserContext、BrowserPage、AudioData、PaintData来自底层的livekit-browser包(模块内注释为 "Re-export from livekit-browser for convenience"),而BrowserSession、PageActions、BrowserAgent是本插件在 LiveKit Agents 侧封装的会话、输入与代理逻辑。
安装与首次启动
安装命令十分简单(README):
pip install livekit-plugins-browser从 pyproject.toml 可以看到该插件当前的版本约束与依赖关系:
- Python 版本要求
>=3.12.0; - 依赖
livekit-agents>=1.8.0(提供Plugin、llm、rtc等基础设施); - 依赖
livekit-browser>=0.1.4(提供 CEF 底层运行时BrowserContext、BrowserPage)。
pyproject.toml中声明了livekit-agents与livekit-browser的exclude-newer策略为 0 天,即始终解析到这两个依赖的最新发布版本,避免缓存过期版本导致行为不一致。
一个重要的启动细节在 README 中专门说明:CEF 二进制文件会在首次使用时通过livekit.browser.download()自动下载,无需手动安装 Chromium。插件侧的BrowserPlugin类(__init__.py)实现了download_files()钩子,内部正是调用livekit.browser.download(),并在模块导入时通过Plugin.register_plugin(BrowserPlugin())自动注册。这意味着只要安装了插件,LiveKit CLI 的download-files流程即可触发 CEF 二进制拉取。
核心 API 全景
插件把"浏览器"拆成了四个不同抽象层次的对象,理解它们的分工是使用该插件的第一步:
| 对象 | 职责 | 源码位置 |
|---|---|---|
BrowserContext | 浏览器进程上下文,负责初始化 CEF、创建页面、管理 Playwright 桥接 | 来自livekit-browser包,经 __init__.py 再导出 |
BrowserPage | 单个网页标签页,暴露paint/audio/cursor_changed/url_changed事件及输入注入方法 | 来自livekit-browser包 |
BrowserSession | 把BrowserPage接入 LiveKit 房间:发布音视频轨道、管理焦点、转发输入 | session.py |
PageActions | 类型化的页面操作 API(点击、拖拽、滚动、打字、按键组合等),并缓存最近一帧画面 | page_actions.py |
BrowserAgent | 高层封装:把BrowserSession+PageActions+ AnthropicComputerTool组装成一个可对话、可浏览的 AI 代理 | browser_agent.py |
此外,_keys.py(源码)提供了键码映射基础设施,被BrowserSession(人类输入)和ComputerTool(AI 输入)两侧共用,后文会详述。
实战一:用 BrowserSession 把网页实时推流进房间
仓库自带的示例 examples/browser_agent.py 展示了最底层的接入方式,直接使用BrowserContext+BrowserPage+BrowserSession,不依赖高层BrowserAgent:
from livekit.agents import AgentServer, AutoSubscribe, JobContext, cli from livekit.plugins.browser import ( AudioData, BrowserContext, BrowserSession, PaintData, ) server = AgentServer() @server.rtc_session() async def entrypoint(ctx: JobContext) -> None: browser_ctx = BrowserContext(dev_mode=False) await browser_ctx.initialize() page = await browser_ctx.new_page( url="https://news.ycombinator.com", width=1280, height=720, framerate=30, ) @page.on("paint") def on_paint(data: PaintData): # data.frame 为 rtc.VideoFrame(BGRA),另有 data.width/height、data.dirty_rects pass @page.on("audio") def on_audio(data: AudioData): # data.frame 为 rtc.AudioFrame,data.pts 为时间戳 pass # 通过 Playwright(CDP)做编程式浏览器控制 async with browser_ctx.playwright() as browser: pages = browser.contexts[0].pages if pages: title = await pages[0].title() logger.info("page title: %s", title) await ctx.connect(auto_subscribe=AutoSubscribe.SUBSCRIBE_NONE) session = BrowserSession(page=page, room=ctx.room) await session.start() async def cleanup(): await session.aclose() await page.aclose() await browser_ctx.aclose() ctx.add_shutdown_callback(cleanup)这段代码揭示了几个关键点:
1. 页面创建:new_page()接受url、width、height、framerate四个参数,其中framerate直接决定了推流帧率上限,也与BrowserSession内部_video_loop的节拍(interval = 1.0 / fps,见 session.py)一一对应。
2. 事件模型:BrowserPage暴露四类事件,BrowserSession.start()中逐一挂载(session.py):
paint:新画面帧到达,_on_paint把最新帧缓存到_last_frame,再由_video_loop定时捕获进rtc.VideoSource;audio:音频帧到达,首次触发时按帧的sample_rate/num_channels创建rtc.AudioSource(队列 100ms)并发布browser-audio轨道,之后经有界队列(容量 50)持续灌入;cursor_changed:CEF 光标类型经_CEF_CURSOR_MAP映射为 CSS 光标名后广播;url_changed:URL 变化广播到browser-urltopic。
3. 推流参数(session.py):视频以SOURCE_SCREENSHARE源发布,编码上限max_bitrate=8_000_000(8 Mbps)、max_framerate取自页面配置、关闭simulcast;音频以SOURCE_SCREENSHARE_AUDIO源发布。也就是说浏览器画面在房间中表现为标准的屏幕共享轨道,任何订阅者都能直接观看。
4. 清理顺序:cleanup依次关闭session、page、browser_ctx,与BrowserSession.aclose()内部"先摘除事件监听、再取消视频/音频/输入任务、最后 unpublish 音视频轨道"的顺序一致(session.py)。
实战二:BrowserAgent —— 让 LLM 直接"操作"浏览器
BrowserAgent是插件面向 AI 场景的高层封装,构造参数在 browser_agent.py 中定义:
| 参数 | 默认值 | 说明 |
|---|---|---|
url | "https://www.google.com/" | Agent 启动时打开的初始页面 |
llm | 必填 | 驱动浏览器操作的 LLM 实例 |
instructions | "You are a helpful AI assistant that can browse the web. Use the computer tool to interact with the browser." | 系统提示词,通常会要求模型优先使用 computer 工具 |
width/height | 1280/720 | 视口尺寸,同时作为ComputerTool的display_width_px/display_height_px |
framerate | 30 | 页面渲染与推流帧率 |
tools | None | 额外的 LLM 工具列表,与内置工具合并 |
chat_enabled | True | 是否监听房间内的browser-agent-chat数据通道接收用户文本 |
start(room=...)的内部编排顺序清晰可读(browser_agent.py):
- 创建并初始化
BrowserContext(dev_mode=False); new_page()打开url;- 构建
BrowserSession并start()(画面/声音开始推流); - 创建
PageActions,并用其构建 AnthropicComputerTool(id="computer"); - 注册三个导航函数工具:
navigate(跳转 URL)、go_back、go_forward; - 初始化
llm.ChatContext并写入系统提示词; - 若
chat_enabled,监听data_received中 topic 为browser-agent-chat的 JSON 负载({"text": ...})写入待处理队列; - 启动
_agent_loop后台任务。
_agent_loop与_run_llm_loop(browser_agent.py)构成了 Agent 的核心循环,本质是一个"截图-决策-执行"闭环:
- 收到用户消息 → 广播
thinking状态 → 调用self._llm.chat(...); - 工具集为
computer_tool.tools + 导航工具 + 额外工具的并集; - 当模型调用
computer工具时,解析参数后先广播光标位置(browser-agent-cursortopic,含x/y/action/visible/width/height),再广播acting状态,随后执行computer_tool.execute(action, **args); - 对
left_click/middle_click/key/type四类动作,执行后额外await asyncio.sleep(0.8)(_POST_ACTION_DELAY),等待页面稳定后再截图; - 执行结果以
FunctionCall+FunctionCallOutput形式写回ChatContext,其中输出为_screenshot_content()生成的 base64 PNG 图片内容(browser_agent.py); - 导航类工具(
navigate/go_back/go_forward)直接调用PageActions对应方法,同样等待 0.8s 后截图回传; - 模型文本回复通过
browser-agent-chat通道以{"text": ..., "sender": "agent"}形式发回房间。
值得注意的中断协作:BrowserSession.agent_interrupted事件一旦被人类抢占焦点置位,_agent_loop会在每轮 LLM 调用前与每两个工具调用之间检查,发现后立即暂停并向房间发送"(paused — you have control)",随后调用reclaim_agent_focus()重新夺回焦点继续任务。这为"人与 AI 同屏协作、随时接管"提供了机制保障。
实战三:PageActions —— 类型化的页面输入 API
PageActions是对BrowserPage底层输入方法的类型化封装(page_actions.py),文档注释给出了最小用法:
actions = PageActions(page=page) await actions.left_click(100, 200) frame = actions.last_frame它内部持有asyncio.Lock串行化所有输入,并通过订阅paint事件持续缓存last_frame,供截图回传使用。支持的动作一览:
| 类别 | 方法 | 说明 |
|---|---|---|
| 鼠标 | left_click(x, y, modifiers=...) | 左键单击,支持ctrl/shift/alt/meta等修饰键组合 |
| 鼠标 | right_click/middle_click | 右键、中键单击 |
| 鼠标 | double_click/triple_click | 双击、三击 |
| 鼠标 | mouse_move/left_mouse_down/left_mouse_up | 移动、按下、抬起 |
| 鼠标 | left_click_drag(start_x, start_y, end_x, end_y) | 拖拽(移动间含 50ms 停顿模拟真实拖拽) |
| 滚动 | scroll(x, y, direction="down", amount=3) | 方向支持down/up/left/right,每amount单位换算为amount * 120像素 |
| 键盘 | type_text(text) | 逐字符输入文本,自动处理大小写与 Shift 符号 |
| 键盘 | key(text) | 按键组合,如"ctrl+l"、"return" |
| 键盘 | hold_key(text, duration=0.5) | 按住组合键持续指定秒数 |
| 其他 | wait() | 等待 1 秒 |
| 导航 | navigate(url)/go_back()/go_forward() | 页面导航 |
键码映射机制(_keys.py)是这套 API 能跨平台工作的关键:
KEY_NAME_TO_VK:把"return"、"tab"、"escape"、"arrowup"、"f1"–"f12"、"ctrl"/"meta"/"command"等名称映射为 JS keyCode(Windows VK 码);SHIFTED_CHAR_TO_VK:把!、@、#等 21 个需要 Shift 的上档字符映射到基础 VK 码;MODIFIER_MAP与MOD_SHIFT/MOD_CTRL/MOD_ALT/MOD_META:CEF 修饰键位标志;NATIVE_KEY_CODES:按平台生成——macOS 使用 Cocoa 键码(如 Backspace=51、Enter=36),Linux 使用 X11 键码(如 Backspace=22、Enter=36),Windows 返回空映射(因为 Windows 下windows_key_code已足够,模块注释明确说明这一设计取舍);NON_CHAR_KEYS:Backspace/Tab/Enter/Escape、方向键、翻页键、修饰键及 F1–F12 等不需要CHAR事件的按键集合。
type_text对每个字符的发送序列是RAWKEYDOWN → CHAR → KEYUP,需要 Shift 的字符会先按下 Shift(RAWKEYDOWN)再按主键、结束后释放 Shift,这保证了混合大小写文本与符号的可靠输入。
焦点协作与房间协议:人类和 AI 如何共享浏览器
当房间里有多个参与者时,BrowserSession通过"焦点(focus)"机制决定谁能向浏览器注入输入(session.py):
- Agent 启动时调用
reclaim_agent_focus()获得焦点(focus_identity = "__agent__"); - 人类通过 RPC 方法
browser/request-focus请求焦点:无人持有时直接授予;Agent 持有时允许"抢占",同时置位agent_interrupted事件通知BrowserAgent暂停; - 持焦点者通过 RPC
browser/release-focus主动释放;持有者断开连接时焦点自动清除; - RPC
browser/navigate、browser/go-back、browser/go-forward允许任何参与者编程式导航页面; - 焦点变更通过
browser-focustopic 广播(负载{"identity": ...})。
输入事件走browser-input数据通道:持焦点参与者把 JSON 事件数组发布到该 topic,BrowserSession校验packet.participant.identity == self._focus_identity后逐个分发(session.py)。事件类型包括mousemove、mousedown、mouseup、wheel、keydown、keyup、char,其中keydown/keyup/char会经NATIVE_KEY_CODES查表后调用page.send_key_event(...)。所有输入经由容量 256 的_input_queue单任务串行发送,避免并发注入导致的事件乱序。
各数据通道 topic 汇总如下(均可在对应源码中核实):
| Topic | 方向 | 内容 |
|---|---|---|
browser-input | 参与者 → Session | 人类注入的输入事件数组 |
browser-focus | Session → 房间 | 焦点持有者身份广播 |
browser-url | Session → 房间 | 当前页面 URL 变化 |
cursor_changed | Session → 房间 | CSS 光标名(经 CEF 光标类型映射) |
browser-agent-chat | 双向 | BrowserAgent的对话文本({"text", "sender"}) |
browser-agent-status | Agent → 房间 | 状态:thinking/acting/idle |
browser-agent-cursor | Agent → 房间 | AI 操作时的光标位置与动作(x/y/action/visible/width/height) |
这套协议为前端页面渲染"AI 正在看哪里、正在做什么"提供了现成的数据源,是构建可视化浏览器 Agent 演示的基础。
与 Anthropic ComputerTool 的联动
BrowserAgent使用的ComputerTool定义在 livekit-plugins-anthropic 插件的 computer_tool.py,它把 Anthropic 的 computer_use 动作协议逐一映射到PageActions:
screenshot→ 直接返回当前帧编码的 base64 PNG;left_click/right_click/double_click/triple_click/middle_click→ 对应鼠标方法,其中left_click还把text参数解析为修饰键(如"ctrl")一并按下;left_click_drag、left_mouse_down、left_mouse_up、scroll(scroll_direction/scroll_amount)、mouse_move→ 一一对应;type→type_text;key→key;hold_key(duration);wait→wait();- 未知动作抛出
ValueError。
每个动作执行后都会await asyncio.sleep(0.3)并抓取last_frame编码为图片返回给 LLM(computer_tool.py)。在BrowserAgent侧,点击/输入类动作还会额外叠加 0.8s 的页面稳定等待,形成"动作 → 稳定 → 截图 → 反馈给模型"的标准 computer_use 循环。
何时选择哪一层 API
综合上面三层封装,可以根据场景快速选型:
- 只需要把网页画面/声音推流进房间,或做纯人类共享浏览:用
BrowserContext+BrowserPage+BrowserSession(见 examples/browser_agent.py); - 需要 LLM 自主操作浏览器完成 Web 任务:直接用
BrowserAgent,一行start()即可获得完整的截图决策循环; - 需要自定义 LLM 循环,但想复用类型化输入:独立使用
PageActions,配合ComputerTool或自己的工具实现。
总结
livekit-plugins-browser把 CEF 的能力完整接入 LiveKit Agents:通过 session.py 完成页面画面与音频的实时推流,通过 page_actions.py 与 _keys.py 提供跨平台的类型化输入,通过 browser_agent.py 结合 Anthropic computer_use 工具集实现 AI 自主浏览,并借助焦点协议让人类随时接管。安装只需pip install livekit-plugins-browser,CEF 二进制由livekit.browser.download()在首次使用时自动拉取。无论是构建"AI 帮用户填表、搜索、下单"的实时语音助手,还是实现多人在线共享浏览器画面的协作工具,这个插件都提供了开箱即用的完整链路。
【免费下载链接】agentsA framework for building realtime voice AI agents 🤖🎙️📹项目地址: https://gitcode.com/GitHub_Trending/agen/agents
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考