发布时间:2021 年 5 月 4 日
在 Media Capture and Streams API 的上下文中,MediaStreamTrack 接口表示流中的单个媒体轨道。通常,这些是音轨或视频轨道,但也可能存在其他轨道类型。
MediaStream 对象包含零个或多个 MediaStreamTrack 对象,这些对象表示各种音轨或视频轨道。每个 MediaStreamTrack 可以有一个或多个渠道。声道表示媒体流的最小单位,例如与给定扬声器(如立体声音轨中的左声道或右声道)关联的音频信号。
什么是 MediaStreamTrack 的可插入流?
MediaStreamTrack 可插入流的核心思想是将 MediaStreamTrack 的内容公开为一组流(由 WHATWG Streams API 定义)。可以对这些流进行处理,以引入新组件。
授予开发者直接访问视频(或音频)流的权限后,他们便可以直接对该流进行修改。相比之下,如果使用传统方法实现相同的视频操作任务,开发者需要使用 <canvas> 元素等中介。(如需详细了解此类流程,请参阅视频 + 画布 = 神奇等文章。)
浏览器支持
从 Chrome 94 开始,支持 MediaStreamTrack 的可插入媒体流。
使用场景
可插播的视频流的用例(适用于 MediaStreamTrack)包括但不限于:
- 视频会议小工具,例如“搞笑帽子”或虚拟背景。
- 语音处理,例如软件声码器。
如何为 MediaStreamTrack 使用可插入的流
按如下方式检测可插入的媒体流是否支持 MediaStreamTrack。
if ('MediaStreamTrackProcessor' in window && 'MediaStreamTrackGenerator' in window) {
// Insertable streams for `MediaStreamTrack` is supported.
}
核心概念
MediaStreamTrack 的可插入流基于 WebCodecs 之前提出的概念,并在概念上将 MediaStreamTrack 拆分为两个组件:
MediaStreamTrackProcessor,它会使用MediaStreamTrack对象的来源并生成媒体帧(具体为VideoFrame或AudioFrame)的流。您可以将其视为能够将轨道中的未编码帧作为ReadableStream公开的轨道接收器。MediaStreamTrackGenerator,用于使用媒体帧流并公开MediaStreamTrack接口。它可以提供给任何接收器,就像getUserMedia()中的轨道一样。它以媒体帧作为输入。
MediaStreamTrackProcessor
MediaStreamTrackProcessor 对象公开了一个属性:readable。它允许从 MediaStreamTrack 读取帧。如果轨道是视频轨道,则从 readable 读取的块将是 VideoFrame 对象。如果轨道是音轨,则从 readable 读取的块将是 AudioFrame 对象。
MediaStreamTrackGenerator
MediaStreamTrackGenerator 对象同样公开了一个属性 writable,该属性是一个 WritableStream,可用于将媒体帧写入 MediaStreamTrackGenerator(本身是一个 MediaStreamTrack)。如果 kind 属性为 "audio",则该流接受 AudioFrame 对象,但会因任何其他类型而失败。如果 kind 为 "video",则该流接受 VideoFrame 对象,但会因任何其他类型而失败。当帧写入 writable 时,系统会自动调用帧的 close() 方法,以便 JavaScript 无法再访问其媒体资源。
MediaStreamTrackGenerator 是一种轨道,可以通过将媒体帧写入其 writable 字段来实现自定义来源。
综合应用
核心思想是创建如下处理链:
平台轨道 → 处理器 → 转换器 → 生成器 → 平台接收器
以下示例展示了条形码扫描器应用的此链,该应用会在实时视频流中突出显示检测到的条形码。
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);
const videoBefore = document.getElementById('video-before');
const videoAfter = document.getElementById('video-after');
videoBefore.srcObject = stream;
const streamAfter = new MediaStream([trackGenerator]);
videoAfter.srcObject = streamAfter;
演示
您可以在桌面版或移动版浏览器上观看上文中的 QR 码扫描器演示。将二维码放在摄像头前,应用会检测到并突出显示该二维码。您可以在 GitHub 上查看应用的源代码。

安全性和隐私权注意事项
此 API 的安全性依赖于 Web 平台中的现有机制。由于数据是通过 VideoFrame 和 AudioFrame 接口公开的,因此这些接口处理源污染数据的规则适用。例如,由于对访问跨源资源存在限制,因此无法访问跨源资源中的数据(例如,无法访问跨源图片或视频元素的像素)。此外,对来自摄像头、麦克风或屏幕的媒体数据的访问也需要获得用户授权。此 API 公开的媒体数据已通过其他 API 提供。
反馈
Chromium 团队希望了解您在使用可插入流进行 MediaStreamTrack 方面的体验。
请告诉我们有关 API 设计的信息
API 是否存在未按预期运行的情况?或者,是否有缺少的方法或属性需要您来实现自己的想法?您对安全模型有任何疑问或意见吗?在相应的 GitHub 代码库中提交规范问题,或在现有问题中添加您的想法。
报告实现方面的问题
您是否发现 Chromium 的实现存在 bug?或者,实现是否与规范不同?
请前往 new.crbug.com 提交 bug。请务必尽可能详细地说明问题,提供重现说明,并在组件框中输入 Blink>MediaStream。
对 API 的支持
您是否计划为 MediaStreamTrack 使用可插入的视频流?您的公开支持有助于 Chromium 团队确定功能优先级,并向其他浏览器供应商展示支持这些功能的重要性。
使用 #ChromiumDev 标签向 @ChromiumDev 发送推文,告诉我们您在何处以及如何使用它。#InsertableStreams
实用链接
致谢
MediaStreamTrack 规范的可插入流由 Harald Alvestrand 和 Guido Urdaneta 编写。本文由 Harald Alvestrand、Joe Medley、Ben Wagner、Huib Kleinhout 和 François Beaufort 审核。