跳转到内容
搜索文档

WebSocket 适配器

最后更新 查看 MarkdownAgent 设置

在 WebRTC 轨道与 WebSocket 端点之间流式传输音频和视频。支持从 WebSocket 源引入音频,以及向 WebSocket 消费者发送 WebRTC 音频和视频。视频出网支持为约 1 FPS 的 JPEG 格式。

您可以构建什么

  • 具有用于音频处理的 WebSocket API 的 AI 服务
  • 自定义音频处理管道
  • 旧版系统桥接
  • 服务器端音频生成和消费
  • 视频快照和缩略图
  • 计算机视觉引入(低 FPS)

工作原理

从外部音频创建 WebRTC 轨道

通过 WebSocket 从外部源引入音频,以创建用于分发的 WebRTC 轨道。

graph LR
    A[外部系统] -->|音频数据| B[WebSocket 端点]
    B -->|适配器| C[Realtime SFU]
    C -->|新会话| D[WebRTC 轨道]
    D -->|WebRTC| E[WebRTC 客户端]

使用场景:

  • AI 文本转语音(TTS)生成流式传输到 WebRTC
  • 来自后端服务或数据库的音频
  • 来自外部系统的实时音频源

关键特性:

  • 自动创建新的会话 ID
  • 使用 buffer 模式进行分块音频传输
  • 每个 WebSocket 消息最大 32 KB

将 WebRTC 音频和视频流式传输到外部系统

通过 WebSocket 将现有 WebRTC 轨道中的音频和视频流式传输到外部系统以进行处理或存储。

graph LR
    A[WebRTC 源] -->|WebRTC| B[Realtime SFU 会话]
    B -->|适配器| C[WebSocket 端点]
    C -->|媒体数据| D[外部系统]

使用场景:

  • 实时语音转文本(转录)
  • 音频录制和归档
  • 实时音频处理管道
  • 视频快照和缩略图
  • 计算机视觉引入(低 FPS)

关键特性:

  • 需要带有轨道的现有会话 ID
  • 音频:在生成 PCM 帧时单独发送;每个帧都包含时间戳和序列号
  • 视频:以大约 1 FPS 发送单个 JPEG 帧;每个帧都包含时间戳(序列号可能未设置)
  • 在短暂断开连接或端点重启后,自动重试相同的 WebSocket 端点,最长可持续 5 秒。请参阅流式传输自动重新连接

API 参考

创建适配器

POST /v1/apps/{appId}/adapters/websocket/new

请求体

{
  "tracks": [
    {
      "location": "local",
      "trackName": "string",
      "endpoint": "wss://...",
      "inputCodec": "pcm",
      "mode": "buffer"
    }
  ]
}

参数

参数 类型 描述
location string 必填。必须为 "local" 以便引入音频
trackName string 必填。要创建的新 WebRTC 轨道的名称
endpoint string 必填。要从中接收音频的 WebSocket URL
inputCodec string 必填。传入音频的编解码器。目前仅支持 "pcm"
mode string 必填。本地模式下必须为 "buffer"

响应

{
  "tracks": [
    {
      "trackName": "string",
      "adapterId": "string",
      "sessionId": "string",    // 自动生成的新会话 ID
      "endpoint": "string"      // 请求端点的回显
    }
  ]
}

请求体

{
  "tracks": [
    {
      "location": "remote",
      "sessionId": "string",
      "trackName": "string",
      "endpoint": "wss://...",
      "outputCodec": "pcm"
    }
  ]
}

参数

参数 类型 描述
location string 必填。必须为 "remote" 以便将媒体流出
sessionId string 必填。包含该轨道的现有会话 ID
trackName string 必填。要流式传输的现有轨道的名称
endpoint string 必填。要将媒体发送到的 WebSocket URL
outputCodec string 必填。传出媒体的编解码器。音频使用 "pcm",视频使用 "jpeg"(仅限出网)

响应

{
  "tracks": [
    {
      "trackName": "string",
      "adapterId": "string",
      "sessionId": "string",    // 与请求的 sessionId 相同
      "endpoint": "string"      // 请求端点的回显
    }
  ]
}

关闭适配器

POST /v1/apps/{appId}/adapters/websocket/close

请求体

{
	"tracks": [
		{
			"adapterId": "string"
		}
	]
}

媒体格式

WebRTC 轨道

  • 编解码器:Opus
  • 采样率:48 kHz
  • 声道:立体声

WebSocket 二进制格式

媒体使用 Protocol Buffers。音频使用 PCM 负载;视频使用 JPEG 负载:

  • 16 位有符号小端(little-endian)PCM
  • 48 kHz 采样率
  • 立体声(左右交错)
  • 视频:JPEG 图像负载(每条消息一帧)
message Packet {
    uint32 sequenceNumber = 1;  // 仅在 Stream 模式下使用
    uint32 timestamp = 2;       // 仅在 Stream 模式下使用
    bytes payload = 5;          // 媒体数据
}

引入模式 (buffer):仅使用 payload 字段,包含音频数据分块。

Stream 模式 (egress)

  • 对于音频帧:
    • sequenceNumber:递增的数据包计数器
    • timestamp:用于同步的时间戳
    • payload:单个 PCM 音频帧数据
  • 对于视频帧 (JPEG):
    • timestamp:用于同步的时间戳
    • payload:JPEG 图像数据(每条消息一帧)
    • 注意:对于视频帧,sequenceNumber 可能未设置

视频 (JPEG)

  • 支持的 WebRTC 输入编解码器:H264、H265、VP8、VP9
  • 通过 WebSocket 输出:大约 1 FPS 的 JPEG 图像

连接协议

连接到您的 WebSocket 端点:

  1. WebSocket 升级握手
  2. 针对 wss:// URL 的安全连接
  3. 媒体流式传输开始

消息格式

Buffer 模式(引入)

  • 二进制消息:分块的 PCM 音频数据
  • 最大消息大小:每个 WebSocket 消息 32 KB
  • 重要提示:在对音频缓冲区进行分块时,应考虑到序列化开销
  • 以小而频繁的分块发送音频,而不是大批量发送

Stream 模式 (egress)

  • 二进制消息:带有元数据的单个帧(音频或视频)
  • 音频帧包括:
    • 时间戳信息
    • 序列号
    • PCM 音频帧数据
  • 视频帧包括:
    • 时间戳信息
    • JPEG 图像数据
    • 注意:对于视频帧,序列号可能未设置
  • 从 WebRTC 轨道到达的帧会被单独发送
  • 视频帧以大约 1 FPS 的速度发出

连接生命周期

  1. 连接到 WebSocket 端点
  2. 音频流式传输开始
  3. 视频流式传输开始(如果已配置)
  4. 对于 WebRTC 到 WebSocket 的流式传输,在断开连接后短暂重试相同的端点
  5. 在关闭、出错或自动重新连接窗口耗尽后,连接将关闭

流式传输自动重新连接

当您使用 WebSocket 适配器的 Stream 模式 (egress)将实时音频或视频从 SFU 发送到您自己的 WebSocket 端点 (WebRTC → WebSocket) 时,SFU 会在端点发生短暂断开连接或重启后自动重新连接。

SFU 会自动重试相同的 WebSocket 端点,最长可持续 5 秒。不需要修改 API。如果端点在重新连接窗口过后仍不可用,适配器将关闭,您的应用程序必须创建一个新的适配器才能恢复流式传输。

重新连接期间的媒体缓冲

当 WebSocket 端点暂时不可用时,自动重新连接会使用实时优先(live-first)缓冲:

  • 音频缓冲:SFU 保留一个短暂的、有界的音频帧积压。如果中断持续时间超过积压所能覆盖的范围,旧音频可能会被丢弃,从而使重新连接恢复保持在有界范围内。
  • 视频缓冲:SFU 仅保留最新的可用 JPEG 帧。重新连接时,新帧会替换旧帧,因此视频会以接近实时的状态恢复,而不是重放陈旧的帧。
  • 递送行为:缓冲减少了短暂中断期间的媒体丢失,但它不是重放机制,不保证无缝或恰好一次(exactly-once)的递送。

自动重新连接仅在配置为 Stream 模式 (egress) 时适用。它仅重试相同的端点,不提供多端点故障转移。

计费

目前处于 Beta 阶段,免费使用。

一旦正式发布(GA),计费将遵循标准的 Cloudflare Realtime 定价,即每 GB 出网流量 0.05 美元。仅从 Cloudflare 流向 WebSocket 端点的流量会产生费用。从 WebSocket 端点引入到 Cloudflare 的流量不收取费用。

使用量会计入您的 1,000 GB Cloudflare Realtime 免费额度中。

最佳实践

连接管理

  • 关闭一个已经关闭的实例将返回成功
  • 会话结束时关闭
  • 当使用 Stream 模式 (egress) 时,请在 5 秒的流式传输自动重新连接窗口耗尽后,处理适配器关闭。
  • 当从 WebSocket 引入到 WebRTC 时,如果连接中断,请在您的 WebSocket 客户端中实现重新连接逻辑。
  • 使您的 WebSocket 端点具备重启安全性,以便在短暂重启期间能够接受对相同 URL 的重新连接。

性能

  • 将 WebSocket 端点部署在靠近 Cloudflare 边缘的位置
  • 使用适当的缓冲区大小
  • 监控连接质量

安全

  • 对 WebSocket 端点采用身份验证以确保安全
  • 在生产环境中使用 wss://
  • 实施速率限制

限制

  • WebSocket 负载:引入和流式传输支持 PCM(音频);流式传输支持 JPEG(视频)
  • Beta 状态:API 可能会在未来的版本中发生变化
  • 视频支持:仅限出网 (JPEG)
  • 视频帧率:大约 1 FPS(Beta 阶段;不可配置)
  • 流式传输重新连接:使用 Stream 模式 (egress) 时,SFU 仅在短暂断开连接时自动重试相同的 WebSocket 端点。它不会故障转移到备用端点。
  • 尽力而为恢复:短暂的重新连接可以减少媒体丢失,但不保证无缝或恰好一次(exactly-once)的递送。
  • 视频重新连接行为:视频从最新的可用 JPEG 帧恢复,而不是重放较旧的帧。
  • 单向流:每个实例处理一个方向

错误处理

错误代码 描述
400 请求参数无效
404 未找到会话或轨道
503 未找到适配器(用于关闭操作)

参考实现

从自定义桥接迁移

  1. 将自定义信令替换为适配器 API 调用
  2. 更新 WebSocket 端点以处理 PCM 格式
  3. 实现适配器生命周期管理
  4. 移除自定义 STUN/TURN 配置

常见问题

问:我可以使用同一个适配器来实现双向音频吗?

答:不能,每个实例都是单向的。分别为发送和接收创建独立的适配器。

问:如果 WebSocket 连接中断会发生什么?

答:当使用 Stream 模式 (egress) 时,SFU 会在最长 5 秒内自动重试相同的 WebSocket 端点。如果端点在此窗口内恢复连接,流式传输将自动恢复。

音频使用短暂且有界的积压缓冲区来减少短暂中断期间的听觉丢失。视频从最新的可用 JPEG 帧恢复,而不是重放较旧的帧。

如果端点在 5 秒的流式传输自动重新连接窗口过后仍不可用,则适配器关闭并必须重新创建。

当从 WebSocket 引入到 WebRTC 时,您的 WebSocket 客户端应根据需要重新连接并重新创建适配器。

问:并发适配器数量是否有限制?

答:限制遵循标准的 Cloudflare Realtime 配额。如有特定需求,请联系支持团队。

问:创建适配器后我能更改音频格式吗?

答:不能,音频格式在创建时即固定。对于不同格式,请创建新的适配器。

这篇文档对您有帮助吗?