流式传输

通过 WebSocket 流式传输浏览器视口,实现实时预览或“配对浏览”,让人类可以实时观察并与人工智能代理协同操作。

启用流式传输

设置 AGENT_BROWSER_STREAM_PORT 环境变量以启动 WebSocket 服务器:

AGENT_BROWSER_STREAM_PORT=9223 agent-browser open example.com

该服务器会流式传输视口帧,并接收输入事件(鼠标、键盘、触摸)。

WebSocket 协议

连接到 ws://localhost:9223 以接收帧并发送输入。

帧消息

服务器发送经过 base64 编码的图像的帧消息:

{
  "type": "frame",
  "data": "<base64-encoded-jpeg>",
  "metadata": {
    "deviceWidth": 1280,
    "deviceHeight": 720,
    "pageScaleFactor": 1,
    "offsetTop": 0,
    "scrollOffsetX": 0,
    "scrollOffsetY": 0
  }
}

状态消息

连接和屏幕广播状态:

{
  "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');

// 开始屏幕广播并传入回调函数
await browser.startScreencast((frame) => {
  console.log('帧:', 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 }]
});

// 检查是否正在进行屏幕广播
console.log('正在播放:', browser.isScreencasting());

// 停止屏幕广播
await browser.stopScreencast();

使用场景

  • 配对浏览 - 人类实时观察并协助人工智能代理
  • 远程预览 - 在独立界面中查看浏览器输出
  • 录制 - 捕获帧以生成视频
  • 移动端测试 - 注入触摸事件以模拟移动端
  • 可访问性测试 - 在自动化测试过程中进行手动交互