RTCRtpScriptTransformer

基线 2025 *
新推出

自 2025 年 10 月起,此功能已在最新的设备和浏览器版本中可用。此功能可能不适用于较旧的设备或浏览器。

* 此特性的某些部分可能存在不同级别的支持。

RTCRtpScriptTransformer 接口是 WebRTC API 的一部分,它提供了一个工作线程(worker)端的 Stream API 接口,WebRTC Encoded Transform 可以使用该接口来修改 WebRTC 传入和传出的管道中的编码媒体帧。

注意:此功能在 专用 Web Worker 中可用。

实例属性

RTCRtpScriptTransformer.readable 只读

一个 ReadableStream,WebRTC 发送者或接收者管道中的编码帧可能会被添加到其中。

RTCRtpScriptTransformer.writable 只读

一个 WritableStream,编码帧应该被管道传输到其中。

RTCRtpScriptTransformer.options 只读

RTCRtpScriptTransform 构造函数 传递的选项,用于根据正在处理的是传入帧还是传出帧来配置转换代码。

实例方法

RTCRtpScriptTransformer.generateKeyFrame()

请求视频编码器生成一个关键帧。当处理传出帧时,可以在发送者管道中的转换器调用此方法。

RTCRtpScriptTransformer.sendKeyFrameRequest()

请求发送者发送一个关键帧。当处理传入的编码视频帧时,可以在接收者管道中的转换器调用此方法。

描述

RTCRtpScriptTransformer 实例是在关联的 RTCRtpScriptTransform 构建过程中创建的,该实例指定了创建转换器的 worker 以及将传递给它的选项。

通过工作线程上的 rtctransform 事件的 transformer 属性,转换器对 worker 可用。当创建关联的 RTCRtpScriptTransform 时,以及当编码帧被添加到 RTCRtpScriptTransformer.readable(来自编解码器(传出)或来自打包器(传入))时,会触发此事件。

转换器向 worker 公开了一个 readablewritable 流,以及一个在构建时提供给 RTCRtpScriptTransformoptions 对象。当关联的 RTCRtpScriptTransform 被分配给 RTCRtpSenderRTCRtpReceiver 时,WebRTC 发送者或接收者管道中的编码媒体帧会被添加到 readable 流中。

WebRTC Encoded Transform 必须从 transformer.readable 读取编码帧,根据需要进行修改,然后以相同的顺序写入 transformer.writable,并且不进行任何重复。 transformer.options 允许根据编码媒体帧是传入还是传出,使用适当的转换函数。转换通常通过将帧从 readable 管道传输到一个或多个 TransformStream 实例到 writable 来实现,根据需要进行转换。

该接口还提供了方法,允许发送者生成一个视频编码器来生成新的关键帧,或者允许接收者向发送者的编码器请求新的关键帧(视频编码器通常会发送一个包含构建图像所需全部信息的可视化帧,然后发送仅包含自上一帧以来已更改信息的可变帧)。

在接收者在收到新的关键帧之前无法解码传入帧的情况下,需要这些方法。例如,新加入会议的接收者将无法看到视频,直到他们收到一个新的关键帧,因为只能在拥有上一关键帧和所有后续可变帧的情况下才能解码可变帧。同样,如果帧是为接收者加密的,他们只有在收到第一个加密的关键帧后才能解码帧。

示例

此示例显示了在 worker 中运行的 WebRTC Encoded Transform 的代码。

该代码使用 addEventListener()rtctransform 事件注册一个处理函数,该事件将 RTCRtpScriptTransformer 暴露为 event.transformer

该处理函数创建一个 TransformStream,并将帧从 event.transformer.readable 通过它管道传输到 event.transformer.writable。该转换流的 transform() 实现会为流中排队的每个编码帧调用:它可以读取帧中的数据,在本例中是反转字节,然后将可修改的帧排入流。

js
addEventListener("rtctransform", (event) => {
  const transform = new TransformStream({
    start() {}, // Called on startup.
    flush() {}, // Called when the stream is about to be closed.
    async transform(encodedFrame, controller) {
      // Reconstruct the original frame.
      const view = new DataView(encodedFrame.data);

      // Construct a new buffer
      const newData = new ArrayBuffer(encodedFrame.data.byteLength);
      const newView = new DataView(newData);

      // Negate all bits in the incoming frame
      for (let i = 0; i < encodedFrame.data.byteLength; ++i) {
        newView.setInt8(i, ~view.getInt8(i));
      }

      encodedFrame.data = newData;
      controller.enqueue(encodedFrame);
    },
  });
  event.transformer.readable
    .pipeThrough(transform)
    .pipeTo(event.transformer.writable);
});

上面 TransformStream 的唯一特别之处在于,它排队的是编码媒体帧(RTCEncodedVideoFrameRTCEncodedAudioFrame),而不是任意“块”,并且 writableStrategyreadableStrategy 属性未定义(因为排队策略完全由用户代理管理)。

转换可以在传入或传出的 WebRTC 管道中运行。这在上面的代码中无关紧要,因为发送者可以使用相同的算法来反转帧,接收者也可以用相同的算法来恢复它们。如果发送者和接收者管道需要应用不同的转换算法,则必须将当前管道的信息从主线程传递。这可以通过在相应的 RTCRtpScriptTransform 构造函数 中设置 options 参数来实现,该参数然后可以在 RTCRtpScriptTransformer.options 中供 worker 使用。

下面我们使用 transformer.options 来选择发送者转换或接收者转换。请注意,对象的属性是任意的(只要值可以被序列化),并且还可以传输 MessageChannel 并使用它在 运行时与转换器进行通信,例如共享加密密钥。

js
// Code to instantiate transform and attach them to sender/receiver pipelines.
onrtctransform = (event) => {
  let transform;
  if (event.transformer.options.name === "senderTransform")
    transform = createSenderTransform();
  // returns a TransformStream (not shown)
  else if (event.transformer.options.name === "receiverTransform")
    transform = createReceiverTransform();
  // returns a TransformStream (not shown)
  else return;
  event.transformer.readable
    .pipeThrough(transform)
    .pipeTo(event.transformer.writable);
};

请注意,上面的代码是 使用 WebRTC Encoded Transforms 中提供的更完整示例的一部分。

规范

规范
WebRTC Encoded Transform
# rtcrtpscripttransformer

浏览器兼容性

另见