MediaStreamTrack的Insertable streams

本文中MediaStreamTrack主要指可以操作或用于生成新内容的媒体流。

背景

Media Capture和Streams API中,MediaStreamTrack接口代表流中的单媒体轨道,通常是音频或视频轨道,但也可能存在其他轨道类型。MediaStream对象由零个或多个MediaStreamTrack对象组成,代表各类音频或视频轨道。每个MediaStreamTrack可以有一个或多个通道。通道是媒体流的最小单位。比如与给定扬声器相关的音频信号,以及立体声音频轨道中的左声道或右声道。

什么是MediaStreamTrack的insertable stream?

MediaStreamTrac的insertable stream背后的核心思想是将MediaStreamTrack的内容作为(WHATWG Streams API所定义的)集合公开。这些流经操作可以用于引入新的组件。

授予开发者对视频(或音频)流的直接访问权,允许他们直接对流进行修改。相比之下,用传统方法实现同样的视频操作任务,需要开发者使用<canvas>元素这样的中介。(关于上述过程的细节,请看示例video + canvas = magic)。

使用案例

MediaStreamTrack的insertable stream用例包括,但不限于:

  • 视频会议的小工具,如“funny hats”或虚拟背景。
  • 语音处理,如vocoders软件。

现状

步骤及完成状态

1. 创建解释器——完成

2. 创建规范初稿——进行中

3. 收集反馈、迭代设计——正在进行中

4. origin trial——进行中

5. 启动——尚未开始

如何使用MediaStreamTrack的insertable stream

在origin trial阶段启用支持

从Chrome 90开始,MediaStreamTrack的insertable stream就作为Chrome中WebCodecs origin trial的一部分可用了。origin trial预计在Chrome 91(2021年7月14日)结束。如有必要,谷歌会对MediaStreamTrack的insertable stream进行单独的origin trial。

origin trial允许用户尝试新功能,并就其可用性、实用性和有效性向web标准社区提供反馈。欲了解更多信息,参见Origin Trials Guide for Web Developers。要报名参加这项或其他origin trial,请访问注册页面

注册origin trial

1. 给你的origin申请一个token。

2. 有两种方法可以把token添加到你自己的页面:

  • 在每个页面上方添加一个 origin-trial <meta> 标签。例如:
<meta http-equiv="origin-trial" content="TOKEN_GOES_HERE">
  • 如果你能配置自己的服务器,你也可以使用Origin-Trial HTTP报文来添加token。由此产生的响应报文如下:
Origin-Trial: TOKEN_GOES_HERE

通过chrome://flags #启用

要在本地试验MediaStreamTrack的insertable stream,不需要origin trial token,用户可以在chrome://flags中启用#enable-experimental-web-platform-features标志。

特征检测

你可以对支持MediaStreamTrack的insertable stream进行特征检测,方法如下:

if ('MediaStreamTrackProcessor' in window && 'MediaStreamTrackGenerator' in window) {
  // Insertable streams for `MediaStreamTrack` is supported.
}

核心概念

MediaStreamTrack的insertable stream建立在WebCodecs以前提出的概念上,并在概念上将MediaStreamTrack分成两个部分。

  • MediaStreamTrackProcessor,它消耗MediaStreamTrack对象的源并生成媒体帧流,特别是VideoFrameAudioFrame)对象。你可以把它看作是一个轨道sink,能够把轨道上未编码的帧作为ReadableStream公开。同时也为反方向的信号提供了一个控制通道。
  • MediaStreamTrackGenerator,它消耗一个媒体帧流并开放一个MediaStreamTrack接口。像getUserMedia()的轨道yiyang,它可以被提供给任何sink,可以接受媒体帧输入。此外,它还提供访问由sink产生的控制信号的路径。

MediaStreamTrackProcessor

一个MediaStreamTrackProcessor对象有两个属性:

  • Readable,可读。允许从MediaStreamTrack中读取帧。如果该轨道是一个视频轨道,从readable读取的块会是是VideoFrame的对象。如果该轨道是音频轨道,从可读的块中读取的会是AudioFrame的对象。
  • writableControl,可写控制。允许向轨道发送控制信号。控制信号是MediaStreamTrackSignal类型的对象。

MediaStreamTrackGenerator

一个MediaStreamTrackGenerator对象也同样也有两个属性。

  • writable,可写。WritableStream允许将媒体帧写入MediaStreamTrackGenerator,它本身就是一个MediaStreamTrack。如果kind属性是“audio”,流会接受AudioFrame对象,不接受任何其他类型的对象。如果是“video”,流接受VideoFrame对象,不接受任何其他类型的对象。当一个框架被写入writable时,框架的close()方法会被自动调用,这样就不再能从JavaScript中访问它的媒体源了。
  • readableControl。ReadableStream允许读取从任何连接到MediaStreamTrackGenerator的sink中发送的控制信号。控制信号是MediaStreamTrackSignal类型的对象。

在MediaStream模型中,除了从源流向sink的媒体之外,还有反向流动的控制信号(即通过轨道从汇到源头)。一个MediaStreamTrackProcessor是一个sink,它允许通过其writableControl(可写控制)属性向其轨道和源发送控制信号。MediaStreamTrackGenerator是一个轨道,可以通过向其writable可写字段写入媒体帧来实现自定义源。这样的源可以通过其readableControl(可读控制)属性接收sink发送的控制信号。

总结

核心思想是创建一个处理链,如下所示:

平台track→processor→转换→generator→平台sink

比如说条形码扫描器的应用,它的链如下所示:

const stream = await getUserMedia({ video: true });
const videoTrack = stream.getVideoTracks()[0];

const trackProcessor = new MediaStreamTrackProcessor({ track: videoTrack });
const trackGenerator = new MediaStreamTrackGenerator({ kind: 'video' });

const transformer = new TransformStream({
  async transform(videoFrame, controller) {
    const barcodes = await detectBarcodes(videoFrame);
    const newFrame = highlightBarcodes(videoFrame, barcodes);
    videoFrame.close();
    controller.enqueue(newFrame);
  },
});

trackProcessor.readable.pipeThrough(transformer).pipeTo(trackGenerator.writable);

trackGenerator.readableControl.pipeTo(trackProcessor.writableControl);

本文只是大致概括了所有的可能性,但并没能深入讨论细节。获取更多样例,请参阅video processing demoaudio processing demo。你可以在GitHub上找到这两个演示的源代码。

演示

你可以用电脑或手机浏览器观看上面提到的二维码扫描器演示的操作。将一个二维码放在摄像头前,应用程序会检测到它并高亮显示。你可以在Glitch上查看该应用程序的源代码。

安全和隐私问题

这个API的安全性取决于web平台的现有机制。由于使用VideoFrame和AudioFrame接口开放数据,这些接口处理有来源的数据的规则加以适用。例如,因为目前有访问此类资源的限制,所以我们无法访问来自跨origin资源的数据(例如不能访问跨origin图像或视频元素的像素)。此外,对来自摄像头、麦克风或屏幕的媒体数据的访问要经过用户授权。这个API开放媒体数据通过其他API可用。除了媒体数据之外,该API还公开了一些控制信号,如对新帧的请求。这些信号旨在作为提示,并不构成重大的安全风险。

反馈

Chromium团队希望收到你对MediaStreamTrack的insertable stream的评价。

告诉我们API设计的不妥之处

API哪些功能没有像你预期的那样展开?是否没有你实现想法所需的方法或属性?你对安全模型有什么问题或意见吗?在相应的GitHub repo上提交一个规格问题,或者将你的想法添加到现有的问题中。

反馈实施中的问题

你是否发现Chromium的实现有bug?或者实现与规范不同?你可以在new.crbug.com上提交bug。请务必包括尽可能多的细节,简单的重现说明,并在组件框中输入Blink>MediaStream。Glitch对于分享快速和简单的再现非常有用。

支持API

你打算使用MediaStreamTrack的insertable stream吗?你的公开支持有助于Chromium团队确定功能的优先级,并向其他浏览器厂商展示支持这些功能的重要性。

文章地址:https://web.dev/mediastreamtrack-insertable-media-processing/

原文作者:Thomas Steiner

填写常用邮箱,接收社区更新

WebRTC 中文社区由

运营