
有了Canvas可以更灵活的展示体验更好的视频,能够与页面更好的融合。
文 / Matthew McClure
译 / John
原文 https://mux.com/blog/canvas-adding-filters-and-more-to-video-using-just-a-browser/
视频无疑是网页中最引人关注的元素之一。在一个兼容性良好的网页内,视频的动态画面让网页内容能够更加生动地展现给用户,而那些可响应用户行为并与网页浏览者互动的网页视频元素则将这种美妙体验提升到了新的高度。
这里我想为大家介绍Canvas API!为实现更加高阶的视觉效果,Canvas API向开发人员提供了一种通过<canvas>元素在DOM中绘制图形的方法。此方法的一项常见用例就是处理图像,这也使其成为处理连续图像也就是视频的一大利器。我们希望通过以下几个典型案例为大家分享视频+画布并实现更生动精彩的网页交互效果,探索该项技术的无限可能。
样板参数
为了保证这些案例能够客观充分反映Canvas API的优势,我们确立了以下测试样板参数:首先,我们使用Mux为每个视频附予播放ID,而player.js仅仅是一个用于抓住页面中的所有视频元素与data-playback-id属性,并初始化每一个 HLS.js 的小工具;其次,我们的每个测试小样都有一个用于演示的Processor class。这些演示文件都是自包含的,即便是简单示例与高级示例之间也具有足够相似性,这样便于控制变量以精确比较他们之间的差异。
拷贝视频:从视频元素渲染到Canvas
(此处有视频,链接:https://gp0hk.csb.app/1-simple.html)
注意:这些CodeSandbox演示可能无法在Safari上运行。
在此示例中,我们所做的只是将video元素以canvas元素的输出形式呈现。这里展示的是一个带有video和canvas元素的裸露HTML文件(接下来的每个例子都使用与此完全相同的文件)。当我们创建类的新示例Processor时,我们抓取video和canvas元素然后从画布中获取2D上下文。接下来,通过设置一个监听器来启动我们所构造的函数集合,以便于在视频元素开始播放时应用这些优化。
当play事件被触发时,updateCanvas方法开始被调用。在这种情况下,被调用的只是drawImage上下文,用以确保video元素中的内容能够准确被绘制。当此调用完成后我们会使用requestAnimationFrame立即再次调用该函数。
也许你想问:这里为什么不使用setTimeout而使用requestAnimationFrame?这样做最重要的原因是避免丢帧或剪切。与setTimeout不同,requestAnimationFrame和显示器的刷新率同步,使用requestAnimationFrame能够有效规避对终端显示设备帧率与刷新率的不必要猜测。
让我们用图像创造点什么吧!
(此处有视频,链接:https://gp0hk.csb.app/2-filter.html)
上述示例与我们之前的示例几乎完全相同。但是,在这里我们不是仅仅完全复制整个video元素,而是在将图像绘制到上下文之前操作图像。
在如原先那样绘制图像之后,我们可以将该图像数据以记录了每个像素RGBA值的数组的形式从该上下文中取出。不能不说这是一件令人兴奋的事情,因为这意味着我们可以遍历每个像素并在此基础上实现我们期待的任何功能。而在此情形下,我们要做的是将把绚丽的彩色视频转换为灰阶版本。
最终我们只是采用了 Mozilla团队描述 的方法,也就是将每个RGB估值器设置为其中所有3个的平均值。随后我们更新图像数据数组中的这些值,并将更新后的版本写入到上下文中。
一个接近实际的例子:分析和利用视频的细节
这里我想与大家分享一下Phil痛苦——2015年以来,他一直任职于Demuxed 公司。今年除了常规领域,他还一直致力于 Demuxed 2019网站 ,该 网站 页面的顶部有一个大型动画,设计此动画的目标是希望其与网页背景完美融合。动画可以使用JavaScript和SVG完成,但这样会导致动画文件非常臃肿,以至于完全占据了MacBook Pro的处理器核心。我们的讨论以该命题为重点,我们希望使用合适的编码方案已实现高效的视频动画展示效果。

Phil把视频放在了hero上,并且他注意到视频的背景颜色与CSS中指定的背景颜色不完全匹配。但这并不要紧,Phil做了任何明智的开发者都会做的事情——使用颜色提取工具抓取了视频背景的十六进制颜色值,随后统一两种背景的颜色。

当Phil在不同的浏览器或设备中打开该网页时,他意识到了我们正在处理的色彩空间问题——在解码视频时,不同的浏览器或硬件处理颜色空间的方式不同,因此就像我们试图做的那样,这里基本上没有办法可靠地匹配不同解码器的十六进制值。
