第042期:OffScreen、WebCodecs、WebTransport的花火碰撞

广告位招租
扫码页面底部二维码联系

Hello,这里是FM Robust,本期是第42,欢迎收听,本期的话题将向你介绍一些相对偏门的Web接口,以及把它们组合使用的一些奇思妙想。

在线播放

在节目开始之前,我想先自我推广一下,Robust已经做了40多期,在不同的平台上获得了非常不错的收听率,前几天小宇宙app给我推了订阅数跨过3000的通知,没想到我一个自说自话的声音节目能受到那么多人的欢迎,受宠若惊的同时,感谢你的支持,希望今后可以贡献更多的优质内容。

你可以在喜马拉雅、苹果的Podcast、小宇宙app等平台上收听Robust,同时,你也可以关注我的个人微信公众号 wwwtangshuangnet 与我私下交流,收藏我的博客 www.tangshuang.net ,节目的文字版都会发布在我的博客中。另外,你还可以在哔哩哔哩中搜索“否子戈”关注我,我会时不时发一些技术视频。

如果你觉得本期的内容不错,可以对我进行捐赠,在关注我的公众号 wwwtangshuangnet 之后,随便找一篇付费文章付费后阅读即可。

好了,回到我们本期的主题。

首先,让我们先介绍一下今天的三位主角。

OffScreen即离屏渲染,顾名思义,就是浏览器在我们肉眼可见的窗口之外,提供了渲染能力。我们做前端往往只会称服务端为后台,实际上,在前端本身也存在后台,而OffScreen就是在后台完成,而非前台完成,因此,这里的离屏渲染,不是说把元素通过位置移动移出可视区域,而是在浏览器后台提供了一个非可视化的渲染模块中完成渲染。

我们知道,浏览器本身作为最顶层的应用程序,能够将页面能容渲染到显示器上,需要经过“内核计算->缓冲->光栅化->输出到显示器”的过程,而离屏渲染则是只有前面两步,把要用于渲染的计算结果放到缓冲区后,就结束了,其他程序可以读取缓冲区内容后自己处理,可以用来进行下一步的展示,也可以不展示。

在浏览器中提供了OffscreenCanvas这个接口作为离屏渲染的载体,你可以创建一个OffscreenCanvas对象,对它进行操作。非常有意思的是,在webworker中同样支持该接口,这也就意味着,我们可以在非网页的主线程中,完成渲染工作。这是以前想都不敢想的操作。

相信很多同学都做过一个需求,就是把当前页面或其中的某个区域作为截图,让用户可以保存到自己电脑或手机上。我们经常会用到一个库,即html2canvas,这个库的原理是读取当前DOM解构和ComputedStyle,按照一定的规则绘制到一个canvas中,如果我们需要保存,可以把这个canvas导出为一张图片,在通过a标签的download属性实现下载。这个过程中的核心关键,就是需要有一个canvas来绘制。而现在这个过程是全部在主线程中完成的,并且我们会创建一个canvas标签来获得其上下文,这也就意味着上面提到的整个渲染过程都会被执行,那么浏览器就会花费不少资源在这个事情上,降低页面的运行性能。而如果我们使用离屏渲染,用OffscreenCanvas来绘制,此时浏览器不会真的把绘制效果渲染出来,而只是缓冲了绘制的计算结果,那么就可以减少光栅化和输出的过程。我们再进一步,我们把读取到的DOM和样式发送到一个webworker中,在这个worker中使用OffscreenCanvas进行绘制和图片生成,这样连计算过程都不在主线程执行,对主线程几乎没有任何影响。

不过离屏渲染也存在一些不足的地方,并非所有场景使用都能得到很好的性能提升效果。它主要有两点问题,1. 开辟新的缓冲区会占用大块内存2. 从一个缓冲区搬运数据到另外一个缓冲区,这个过程比线程间通信的效率还要低。因此,那些需要实时响应用户的渲染,不可以使用离屏渲染,例如canvas游戏、图表预览等等,只有那种作为候选结果的可以放在离屏渲染,比如作为预加载,或者如上面所说的不需要立即渲染出来,用户可以等待的场景。

第二位主角是WebCodecs

许多 Web API 在内部都使用了媒体编码器。例如,Web Audio API,以及 WebRTC API。然而,这些 API 不允许开发者处理视频流的单个帧和未合成的编码音频块或视频块。

视频领域,我们有非常多的视频格式,例如AVI、MPEG、QuickTime File Format、WMV等等。视频格式,决定了该视频文件内部的存储结构,因此,想要播放对应格式的视频文件,必须使用能够阅读该存储结构的播放器。

视频编码,是指对视频原始数据进行压缩处理。我们知道,视频是由一帧一帧的画面和声音组成,而视频编码的工作,就是对这些画面和声音进行压缩、去重、优化,使得视频文件既可以播放又方便传输。常见的视频编码方式有H.26X系列,例如H.261, H.263等等,MPEG系列,例如常见的MPEG-4,还有其他很多视频编码方式。

一个视频的原始数据进行视频编码之后,可以再用不同的视频格式进行封装,封装好之后就可以用来传输了。当然,不同的视频格式可能只支持其中少数的视频编码方式,有些视频编码后无法封装为一些视频格式。视频编码是视频文件的本质,视频格式是该文件的表现形式。另外,不同的编码方式会导致不同程度的失真,因为目的不同,压缩和优化时去掉的细节多少也就不同。

视频解码则是对视频编码的反向操作。视频编码是对原始视频数据的压缩、画面去重、优化等,而解码则是按照该视频编码的规则,使经过编码后的数据可以还原出视频本身用于播放。简单讲,经过视频编码后,文件内的数据就是一团乱序的数据,而非连续的视频帧,是无法直接用来播放的,而解码则是还原其为一帧一帧的视频数据,因此,如果我们想从一个视频文件中读取其中某一帧的画面,必须先进行解码,得到连续帧的视频数据之后才能读取到。

Web 开发者通常使用 WebAssembly 来绕过这一限制,例如将FFmpeg编译为wasm使用,并且在浏览器中使用媒体编解码器。然而,这需要额外的带宽来下载浏览器中已经存在的编解码器,降低了性能和能效,并增加了额外的开发成本。

WebCodecs API 提供了对浏览器中已存在的编解码器的访问能力。它可以访问原始视频帧、音频数据块、图像解码器、音频和视频的编码器及解码器。

举些简单的场景,我们在视频播放时,把鼠标移到进度条上,部分播放器会把鼠标位置对应的视频截图展示出来。再比如,我们把视频上传后需要选取一张视频封面。在比如我们需要把人物从弹幕下方浮到弹幕上方。比如我们需要对准备上传的视频或音频中是否包含了敏感信息进行提前检查。

这些场景都是我们常见的。以前,要么我们把这些活放在后端做,然后把处理好的素材发送给前端;要么,我们需要自己写解码编码器,或者通过wasm加载用c/c++写好的编码解码模块。这无疑大大增加了开发成本和运行效率。而WebCodecs直接提供了编码解码的能力,这也就意味着,我们不需要自己再去写解码器,而是直接调用浏览器的接口即可实现上述能力。

同时,我们还可以发挥一些创意,比如自己写一个视频剪辑工具,或者基于AI的视频创作工具,而无需掌握各种私有编码器的API。

第三位主角是WebTransport

在前端应用领域,联网的两台机器想要通信,有两种模式,一种是单工通信模式,另一种是双工通信模式。单工通信只能在一个方向上传输数据,我们最常用的HTTP协议就是单工通信。双工通信可以在两个方向上传输数据,网络层面还分半双工全双工,但在前端基本没有这个必要去区分,我们最常见的莫过于WebSocket。在传输模式上,分为文件传输和流式传输,前者一次性传输整个文件,而后者开启一个可持续的通道多次传输数据。

了解完这些知识后你会发现,想要做到边下载边播放还没那么容易,我们知道可以采用流式传输来实现多次传输,在前面拿到数据之后,就可以立即使用。然而,作为一个视频文件,它的视频编码方式决定了它能不能支持这种拿到部分数据后就可以开始播放的能力。因为前面讲到,视频编码就是进行压缩、优化,那么如果通过流式传输拿到的数据片段无法进行解码会怎样?这也就是为什么我说这里没那么容易的原因。实际上,只有部分视频编码方式和部分视频格式支持流式传输后用来进行播放。

我们之所以需要这些思考,是因为我们当下的行业中,往往需要解决直播、视频会议、同声传译等实时性要求极高的、传输数据体积很大的场景。

我们面临的核心需求是:我们希望继承现代Web的安全保护技术,换句话说,我们需要TLS(安全传输层协议)加密;我们想要某种类型的拥塞控制;我们仍想要客户端-服务器体系结构,我们不希望它建立在p2p的模型上,因为p2p连接体系结构会话的启动难度不小;我们在大多数应用程序中也想使用双向通信,我们需要发送可靠和有序的数据,我们将这种数据称为“流”。流遵循先进先出的模式,因此在此过程中不会丢失任何内容;我们还希望以最小的延迟来实现流,但同时我们还需要发送非可靠和无序的数据报文,这和UDP报文非常相似,它们都是小数据包,关键在于传输的速度,如果速度太慢,其中一些数据可能会丢失,但只要我们能够实现高速传输,就能解决这个问题;我们还需要持续地给发送端提供反馈,我们不能漫无目的地发射接收无法处理的数据。并且它们应该使用URI进行资源定位,因为Web中的URI和URL是我们定位Internet内容的核心中枢,所以我们不想改变这种机制,我们想要一些符合URI机制的东西;我们想要进行定制化的RTC传输,自己可以自定义传输协议,有更多自由发挥的空间。

成年人的世界就是这样,全都想要。却不知道,这里面的困难是有多难。

我们看下当下的Web通信都有哪些备选项:HTTP1/2, WebSocket, WebRTC。但这些方案每一个都不那么完美,各有优缺点。HTTP慢,但HTTP2安全。Websocket全双工,但是阻塞,没有原生支持流。WebRTC支持实时流,点对点通信理论上效率高,但是建立P2P连接成本太高,还要解决各种奇怪的穿透问题等连不通的问题。为了满足开发者们的需求,WebTransport的标准被提了出来,通过WebTransport就可以满足上述的大部分需求。在WebTransport下,我们可以支持双工+流的理想组合,类似直播这样的可互动视频应用将会越来越多。

目前部分浏览器已经支持WebTransport了,但是想要用它,你的服务端必须部署支持HTTP3才行。WebTransport是基于HTTP3的协议框架,而HTTP3又是基于QUIC协议的,虽然目前HTTP3还没有那么流行,部署和维护成本还比较高,但是QUIC已经是比较成熟的协议,未来一定会逐渐成熟,并有可能逐渐取代当下的应用协议。

好了,我们的三位主角已经悉数登场介绍完毕。

接下来,我们来聊一聊基于这三位主角,我们可以畅想一些可能的应用。

首先我想到的是互动电影或者互动直播,以往,我们的电影或直播的内容生产是中心化的,电影公司拍什么,我们看什么,但是,随着AIGC的逐渐成熟,以及上述技术的应用,未来我们可能实现多人联机的UGC实时互动电影生产模式,你可以理解为屏幕版的黑客帝国(或者你可以带上苹果的VisionPro参与)。

这个可能比较科幻未来。

我说一个当下的,前面我们讲到通过html2canvas实现截图,那么通过结合OffscreenCanvas, WebCodecs, WebTransport,我们就可以便捷的实时观察用户在页面中的操作,从而提供方便的客服。

当然啦,还有很多很多可能场景,我这里只是抛砖引玉,你如果有自己的想法,可以在下方留言,发表你的idea。

好了今天的节目就到这里,动动你的小手指,给个一键三连,好运连连,记得关注我的微信公众号 wwwtangshuangnet 给我捐赠哦,我们下期再见。

2023-10-14 1026

为价值买单,打赏一杯咖啡

本文价值10.26RMB