查看原文
其他

【第3078期】W3C:WebCodecs 说明

刘俊 前端早读课 2024-03-05

前言

介绍了 WebCodecs 的问题与动机以及解决方案。当前的 Web API 在使用媒体编解码器方面存在一些限制和不足,导致开发者不得不使用 JavaScript 或 WebAssembly 来实现自己的媒体编解码器。WebCodecs 的目标是提供一种通用的方式来配置和使用内置的媒体编解码器,以支持流式传输、高效性能、灵活性等特性。它提供了一组核心接口,包括编码和解码的音视频数据,以及一种机制将媒体流转换为可读流。本文还讨论了 WebCodecs 的设计细节和未来的考虑。今日前端早读课文章由 @刘俊翻译投稿分享。

@刘俊:Bilibili 资深工程师,Github:https://github.com/hughfenghen

正文从这开始~~

WebCodecs Github:https://github.com/w3c/webcodecs

WebCodecs Demo:https://w3c.github.io/webcodecs/samples/

问题与动机

已有许多 Web API 在内部使用媒体编解码器来支持特定用途,比如:

  • HTMLMediaElement and Media Source Extensions

  • WebAudio (decodeAudioData)

  • MediaRecorder

  • WebRTC

但是还没有一种通用的方式来灵活地配置和使用这些媒体编解码器。因此,许多 Web 应用程序仍然选择 JavaScript 或 WebAssembly 来实现媒体编解码器,尽管存在劣势:

  • 增加了网络消耗去下载浏览器中已有的编解码器

  • 降低了性能

  • 增加了功耗

它们这样做可能是因为当前开放的 Web API 在特定场景都存在难以克服的障碍:

  • WebAudio 允许将媒体文件 (以二进制缓冲区的形式) 解码为 PCM,但它需要是一个有效且完整的媒体文件。它不支持数据流,不提供解码的进度信息。当然,也不支持解码视频,更不支持编码。

  • MediaRecorder 允许对具有音频和视频轨道的 MediaStream 进行编码。可以粗略地控制一些参数 (比特率、带编解码器字符串的 mimetype),但它是非常高层次的。它不支持超过现实速度来快速编码;由于输出可能被缓冲,因此不适合低延迟编码。编码比特流被封装在一个容器中,这为需要自定义容器格式的使用场景增加了开销。许多事情不透明:数据不足时会发生什么,编码速度太慢而无法实时时会发生什么。它对于基础应用非常友好,但缺少许多功能。(译注:总结来说,这是一个高层次的 API,无法做到偏底层的精细控制)

  • WebRTC PeerConnection 允许对网络 RTP 流进行编码和解码,并且与其他 WebRTC 和 MediaStream API 高度耦合,实际上无法用于其他用途。它也非常不透明,JavaScript 无法访问编码后的数据。(译注:WebRTC Insertable Stream 已支持访问编码后的数据)

  • HTMLMediaElement 和 Media Source Extensions 允许在流式传输压缩数据的同时实时解码媒体。视频和音频输出几乎没有灵活性 (可以通过 canvas 调整视频,但不是很高效)。对解码速度的控制方法很少,唯一的可能性是通过 playbackRate,但这会增加音频的频率。无法得到已解码新图像的通知,也无法决定提前解码多少。不能以设备极限的最快速度解码图像数据并对数据运行计算。编码比特流必须以特定的容器格式提供,这限制了非浏览器原生支持的视频容器格式的应用。

目标

为 Web 应用程序提供高效访问内置 (软件和硬件) 媒体编码器和解码器的途径,以编码和解码具有以下属性的媒体:

  • 流式传输:能够对不是全部在内存中的数据流进行操作的能力 (可能从网络、磁盘上读取)。

  • 效率:能够利用用户代理、系统或主机上的可用硬件,使编解码过程更高效。限制垃圾量 (在 “垃圾回收” 意义上),将 GC 压力降到最低,避免 GC 带来的固有非确定性,允许编码和解码脱离主线程运行(译注:可在 WebWorker 中运行)。

  • 组合性:与其他 Web API (如 Streams、WebTransport 和 WebAssembly) 配合良好。

  • 可恢复性:在出现问题时能够恢复的能力 (网络不足、资源缺乏导致的帧下降等)。

  • 灵活性:能够用于各种用例的能力 (硬实时、软实时、非实时),能在此之上实现类似 MSE 或 WebRTC 的功能,且能达到同等级别的功耗和延迟。

  • 对称性:编码和解码具有相似的模式。

非目标

  • 直接操作媒体容器的 API (封装 / 解封装)

  • 在 JavaScript 或 WebAssembly 中实现编解码器

关键用例

  • 极低延迟直播 (<3 秒延迟)

  • 云游戏

  • 直播推流

  • 非实时编码 / 解码 / 转码,例如本地音视频文件编辑

  • 高级实时通信:

    • 端到端加密

    • 对缓冲行为的控制

    • 空间和时间可扩展性(译注:指能够控制或改变视频的分辨率、帧率等)

  • 解码和编码图片

  • 对多个输入媒体流重新编码,以便将许多编码媒体流合并为一个编码媒体流(译注:音视频常见的 “合流”)。

提案的解决方案

WebCodecs 接口模仿了流行平台和软件编解码器的 API。这种 API 形态经过时间的验证,对于具有音视频开发者来说也很直观。

核心接口包括:

  • EncodedAudioChunks and EncodedVideoChunks 包含指定格式的已编码字节数据.

  • AudioFrame 包含解码后的音频数据。它可以通过 AudioWorklet (opens new window) 渲染为 AudioBuffer (opens new window)。(译注:音频帧 AudioFrame 对应的 API 实现为 AudioData)

  • VideoFrame 包含解码后的视频数据。它将提供一个 ImageBitmap (opens new window) 用于在 WebGL、Canvas 进行操作和渲染。它还能 访问 YUV 数据 (opens new window), 但是其设计目前尚未确定。

  • AudioEncoder 编码 AudioFrames (音频帧)生成 EncodedAudioChunks.

  • VideoEncoder 编码 VideoFrames(视频帧)生成 EncodedVideoChunks.

  • AudioDecoder 解码 EncodedAudioChunks 生成 AudioFrames.

  • VideoDecoder 解码 EncodedVideoChunks 生成 VideoFrames.

WebCodecs 还将定义了从 getUserMedia() 导入内容的机制。

  • MediaStreamTrackProcessor (opens new window) 将音视频 MediaStreamTrack 转换为 ReadableStream<AudioFrame | VideoFrame>。

示例

可运行的 DEMO

请注意,下面概述的示例仅为了简洁起见而留下了几个未实现的方法。要获取完整的工作示例,请参阅:

  • https://w3c.github.io/webcodecs/samples/(opens new window)

  • https://web.dev/webcodecs/

译注:省略了代码示例没有翻译,因为 WebCodecs API 已经在浏览器中实现,跟原先设计有一点点差异;如果你想了解真实可运行的示例代码,可参前面官方示例源码

详细的设计讨论

执行环境

编码器和解码器对象可在主线程和专用 Worker 上实例化。编解码器的输入和输出可以使用 postMessage() 在上下文之间传输。传输序列化将使用移动语义实现,并避免复制。

编码和解码操作的计算成本非常高。因此,用户代理必须与启动操作的 JavaScript 异步执行这些操作。编解码器的执行环境由用户代理定义。一些可能性包括:在内部线程池上顺序执行或并行执行,或在硬件加速单元(如 GPU)上执行。

用户代理应谨慎高效地处理昂贵的资源(如视频帧内容、GPU 资源句柄)。

编解码器配置

许多编解码器实现都是高度可配置的。WebCodecs 打算支持当今编解码器中可用的大多数配置选项,以有效地支持高级用例。

当编解码器状态不是 “closed” 时,编解码器可以随时重新配置。传递给 decode() 或 encode() 的块 / 帧 (Chunks/Frames) 将根据最近对 configure() 的调用进行解码 / 编码。

WebCodecs 定义了一组可与任何编解码器一起使用的配置参数。特定于编解码器的参数由编解码器在 https://www.w3.org/TR/webcodecs-codec-registry/ (opens new window) 中注册时定义。对特定设置的支持可能与具体实现有关。支持的配置可使用静态方法 isConfigSupported () 进行支持性检测。

考虑过的替代设计

Media Source Extensions (MSE)

MSE 已被广泛用于低延迟流媒体。但也存在一些问题:

  • 触发 "低延迟模式" 的方式是隐式的,没有标准化,也不是所有主要浏览器都支持。

  • 应用程序必须绕过 MSE 默认的 "欠载(数据不足)时停止" 行为

  • 应用程序必须在将输入添加到缓冲区之前将其容器化

  • 不需要历史记录的应用程序(云游戏)必须设法删除 / 禁用历史记录

  • 应用程序无法轻松访问解码输出(用于渲染以外的用途,如转码)

所有这些问题都可以通过扩展 MSE API 来解决,以明确支持低延迟控制。但这只能解决解码方面的问题,而不能解决编码方面的问题。

与 WhatWG Streams 集成

早期的设计将编码器和解码器定义为 WhatWG 流规范中的 TrasformStreams。这是一个很有吸引力的模型;从概念上讲,编解码器是具有输入和输出流的转换器。但在 Streams 的基础上实现基本的编解码器控制(配置、刷新、重置)会导致设计复杂,我们无法向用户隐藏这种复杂性(更多详情此处 (opens new window))。我们选择如上所述定义编解码器接口。用户可以根据需要将这些接口封装到 Streams 中。

未来的考虑

早期的提案将 AudioTrackWriter 和 VideoTrackWriter 定义为向 <video> 传输解码媒体以进行演示的一种方式。大多数潜在用户都表示他们更喜欢通过 Canvas 来管理演示,因此 <video> 演示 " 目前已不再优先考虑。

未来的另一个想法是公开一个编解码器 "worklet",用户可以在其中实现自己的编解码器,以便在现有的媒体管道中使用。例如,WASM 解码器可与现有的 MSE 和 <video> API 结合使用。

关于本文
译者:@刘俊
译文:https://hughfenghen.github.io/posts/2023/10/02/webcodecs-explainer/
原文:https://github.com/w3c/webcodecs/blob/main/explainer.md#webcodecs-explainer

这期前端早读课
对你有帮助,帮” 
 “一下,
期待下一期,帮”
 在看” 一下 。

继续滑动看下一个

【第3078期】W3C:WebCodecs 说明

向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存