流式传输#
通过 WebSocket 对浏览器视口进行流式传输,用于实时预览,或者让人类与 AI 代理一起观看和交互的“结对浏览”场景。
流式传输#
每个会话都会在操作系统分配的端口上自动启动一个 WebSocket 流服务器。该服务器会流式传输视口帧,并接受输入事件(鼠标、键盘、触摸)。
如果要绑定到特定端口,请设置 AGENT_BROWSER_STREAM_PORT:
AGENT_BROWSER_STREAM_PORT=9223 agent-browser open example.com你也可以在运行时管理流式传输:
agent-browser stream status # 显示流状态和绑定端口
agent-browser stream enable --port 9223 # 在指定端口上重新启用
agent-browser stream disable # 停止该会话的流式传输stream status 会返回启用状态、当前端口、浏览器连接状态,以及是否正在进行 screencast。stream disable 会拆除服务器并移除该会话的 .stream 元数据文件。
当你需要保存好的 WebM 产物,而不是实时 WebSocket 流时,请使用 视频录制。
运行时状态响应#
agent-browser stream status --json 会返回如下数据:
{
"enabled": true,
"port": 9223,
"connected": true,
"screencasting": true
}connected 表示守护进程当前是否连接着浏览器。screencasting 表示流服务器是否正在主动生成帧。
与 screencast 命令的关系#
stream enable 会创建 WebSocket 服务器,并让它在该会话中保持可用。随后 WebSocket 客户端会自动触发实时帧投递。
更底层的 screencast_start 和 screencast_stop 命令仍然可以直接控制显式的 CDP screencast。当你想要不带 WebSocket 运行时服务器的 screencast 时,可以使用它们。
WebSocket 协议#
连接到 ws://localhost:9223 以接收帧并发送输入。
帧消息#
服务器会发送带有 base64 编码图像的 frame 消息:
{
"type": "frame",
"data": "<base64-encoded-jpeg>",
"metadata": {
"deviceWidth": 1280,
"deviceHeight": 720,
"pageScaleFactor": 1,
"offsetTop": 0,
"scrollOffsetX": 0,
"scrollOffsetY": 0
}
}状态消息#
连接和 screencast 状态:
{
"type": "status",
"connected": true,
"screencasting": true,
"viewportWidth": 1280,
"viewportHeight": 720
}输入注入#
发送输入事件以远程控制浏览器。
鼠标事件#
// 点击
{
"type": "input_mouse",
"eventType": "mousePressed",
"x": 100,
"y": 200,
"button": "left",
"clickCount": 1
}
// 释放
{
"type": "input_mouse",
"eventType": "mouseReleased",
"x": 100,
"y": 200,
"button": "left"
}
// 移动
{
"type": "input_mouse",
"eventType": "mouseMoved",
"x": 150,
"y": 250
}
// 滚动
{
"type": "input_mouse",
"eventType": "mouseWheel",
"x": 100,
"y": 200,
"deltaX": 0,
"deltaY": 100
}键盘事件#
// 按键按下
{
"type": "input_keyboard",
"eventType": "keyDown",
"key": "Enter",
"code": "Enter"
}
// 按键松开
{
"type": "input_keyboard",
"eventType": "keyUp",
"key": "Enter",
"code": "Enter"
}
// 输入字符
{
"type": "input_keyboard",
"eventType": "char",
"text": "a"
}
// 带修饰键(1=Alt, 2=Ctrl, 4=Meta, 8=Shift)
{
"type": "input_keyboard",
"eventType": "keyDown",
"key": "c",
"code": "KeyC",
"modifiers": 2
}触摸事件#
// 触摸开始
{
"type": "input_touch",
"eventType": "touchStart",
"touchPoints": [{ "x": 100, "y": 200 }]
}
// 触摸移动
{
"type": "input_touch",
"eventType": "touchMove",
"touchPoints": [{ "x": 150, "y": 250 }]
}
// 触摸结束
{
"type": "input_touch",
"eventType": "touchEnd",
"touchPoints": []
}
// 多点触控(捏合缩放)
{
"type": "input_touch",
"eventType": "touchStart",
"touchPoints": [
{ "x": 100, "y": 200, "id": 0 },
{ "x": 200, "y": 200, "id": 1 }
]
}程序化 API#
对于高级用法,可以直接通过 TypeScript API 控制流式传输:
import { BrowserManager } from 'agent-browser';
const browser = new BrowserManager();
await browser.launch({ headless: true });
await browser.navigate('https://example.com');
// 使用回调启动 screencast
await browser.startScreencast((frame) => {
console.log('Frame:', frame.metadata.deviceWidth, 'x', frame.metadata.deviceHeight);
// frame.data 是 base64 编码图像
}, {
format: 'jpeg', // 或 'png'
quality: 80, // 0-100,仅 jpeg
maxWidth: 1280,
maxHeight: 720,
everyNthFrame: 1
});
// 注入鼠标事件
await browser.injectMouseEvent({
type: 'mousePressed',
x: 100,
y: 200,
button: 'left',
clickCount: 1
});
// 注入键盘事件
await browser.injectKeyboardEvent({
type: 'keyDown',
key: 'Enter',
code: 'Enter'
});
// 注入触摸事件
await browser.injectTouchEvent({
type: 'touchStart',
touchPoints: [{ x: 100, y: 200 }]
});
// 检查是否正在 screencast
console.log('Active:', browser.isScreencasting());
// 停止 screencast
await browser.stopScreencast();使用场景#
- 结对浏览 - 人类实时观看并辅助 AI 代理
- 远程预览 - 在单独的 UI 中查看浏览器输出
- 录制 - 捕获帧用于视频生成
- 移动测试 - 注入触摸事件以模拟移动设备
- 无障碍测试 - 在自动化测试期间进行人工交互