随着网站设计变得越来越动态,有时需要整合复杂的动画元素。从 CSS 过渡到画布上的 3D 渲染,再到动画 SVG,有很多方法可以做到。但使用 <video>
通常更简单,因为它们相当高效,而且几乎可以实现任何视觉效果。
但如果需要该视频的透明背景,以便它可以叠加在页面上的其他内容之上并与之交互,该怎么办?这是可能的,但可能会很棘手,尤其是在跨浏览器方面。让我们来探讨一下。
示例
为了了解透明视频叠加的工作原理,我准备了一个示例,希望它既有趣又相关。这个想法是将视频与底部的交互式内容集成在一起,以便随着滑块的移动,视频后面的内容也会发生变化。这是一个带有真实狗视频叠加的狗粮广告滑块,我相信真实的、可爱的狗会提高转化率!
您可以按照本文的步骤,自己重现此演示。要创建这样的视频,您需要一个“图像序列”(一系列我们将拼接成视频的 alpha 透明图像)。我将提供我在示例中使用的图像。
探索可能性
为了实现这种效果,我首先搜索了任何能够让我在页面上插入具有透明背景的动画内容的解决方案。
GIF
首先想到的是 GIF。 尽管 GIF 格式是在 30 多年前推出的,但它至今仍在广泛使用。不幸的是,它也有其局限性。虽然它非常适合简单的小型动画图形,但对于色彩丰富的长视频素材并不太理想,它的色域有限,而且对于复杂的视频,文件大小会大幅增加。
APNG
我考虑的下一个选项是 APNG, 由于某种原因,它不像 GIF 那样流行,但实际上要好得多。(我甚至不知道它存在,你知道吗?)APNG 的工作原理类似于动画 GIF 文件,同时支持 24 位图像和 8 位透明度。它还与普通 PNG 向后兼容。如果浏览器不支持 APNG,则会显示第一帧。它得到主流浏览器的支持,但在 Internet Explorer 11 中不支持(是的,有些人仍然需要支持它)。虽然它一度看起来像是可行方案,但我不满意它的文件大小和性能。
有趣的事实: Apple 将 APNG 格式作为iOS 10 iMessage 应用程序中动画贴纸的首选格式。
循环遍历 PNG
接下来,一个粗略但可行的想法浮现在脑海:使用一堆 PNG,并使用 JavaScript 循环遍历它们来模拟视频。 但这需要大量的传输数据(每个视频帧都是一个单独的图像)和动画资源(可能会迅速耗尽用户的电池,或者让他们的电脑风扇疯狂转动)。
我很快就放弃了这个想法,但它后来被证明很有用。我会在文章的最后回到这一点。
具有 alpha 透明度的 WebM
由于所有 <img>
格式在这里都失效了,我开始研究视频。我发现一篇关于Chrome 视频中的 alpha 透明度的文章,发表在 2013 年,宣布 Google Chrome 支持具有 alpha 通道的 WebM。它甚至展示了一个示例,并分享了使用它的技巧。我通读了这篇文章,它立即让我感觉像是可行方案。将我的图像序列转换为 WebM 后,我更加确信了,因为虽然 GIF 的大小为 5.8 MB,但具有透明度的 WebM 使用相同的帧速率和全色仅为 540 KB!这比它小 10 倍以上,同时提供了更好的性能和质量。太棒了!
然而,我的喜悦并没有持续太久。当我打开 iOS 手机上的网站时,我意识到我应该一开始就检查浏览器兼容性。不幸的是,Safari(iOS 和 macOS)不支持 WebM 中的透明度。虽然我的视频在 Chrome、Firefox 和 Edge 上完美运行,但 Safari 却给了我一个难看的黑色背景。
搜索仍在继续…
一个好方案
值得庆幸的是,我发现了一段来自 WWDC 2019 的视频,宣布从 iOS 13 和 macOS Catalina 开始,Safari 支持带有 Alpha 的 HEVC 视频。它似乎提供与 WebM 相同的功能,但在 Apple 设备上得到支持。因此,我决定使用混合方案:Safari 使用 HEVC,其他浏览器使用 WebM。
这似乎是一个完美的解决方案。但现在我们有两个任务
- 创建带有 alpha 透明度的 HEVC
- 检测 Safari(以及版本)以提供正确的格式
创建透明视频
我们从简单的部分开始:创建 WebM 文件。如果您需要创建、转换甚至编辑视频文件,FFmpeg 是您的不二之选。它是一个功能极其强大的开源多媒体框架,如果您需要处理多媒体文件,我建议从这里开始,因为它能够完成许多事情。我可以说,FFmpeg 帮助我将视频文件大小缩小了 10 倍以上,而图像质量没有任何明显的下降。但让我们回到透明度上。
根据我的经验,如果您需要将动画元素整合到网站布局中,您会得到一组 PNG 格式的视频帧。即使在我的示例项目中,一个从视频中移除背景的工具也为我生成了一个图像集。因此,我将继续假设我们正在从一组图像中构建视频(请记住,您可以下载我们的图像集),但即使您得到的是视频文件,过程也类似(根据您的需求调整 FFmpeg 选项)。
现在我们准备创建视频。使用命令行,我们将导航到包含 PNG 文件的文件夹,并运行以下命令
ffmpeg -framerate 25 -i unscreen-%3d.png -c:v libvpx-vp9 -pix_fmt yuva420p output.webm
您可以调整参数以满足您的需求
framerate
: 输出视频的 1 秒中使用多少张图像-i unscreen-%3d.png
: 输入文件名和格式。我的文件编号从 001 到 150,所以我使用%3d
作为掩码来选择名称中包含三位数字的所有文件。-c:v
: 指定要使用的编解码器。我希望视频使用 VP9 进行编码,它得到大多数网络浏览器的支持。-pix_fmt
: 指定要使用的像素格式。在我们的案例中,它应该支持 alpha 通道。如果您运行ffmpeg
--pix_fmts
,您可以看到所有支持的格式。output.webm
: 作为最后一个参数提供所需的输出文件名
还有更多选项可用,但我不会深入细节,因为这可能需要不止一篇文章才能介绍完。示例命令中提供的选项足以满足我们的使用场景。
处理完成后,我们应该会看到一个新的 output.webm
文件,如果你在支持的浏览器中打开它,你就会看到一个视频。很简单,对吧?
创建 HEVC Alpha
既然我们已经准备好了 WebP 文件,现在该转到我们要使用的第二种格式了:带 Alpha 通道的 HEVC。不幸的是,在撰写本文时,FFmpeg 不支持 HEVC,所以我们必须使用其他工具。据我所知,创建带 Alpha 通道的 HEVC 的唯一方法是在 Mac 上使用 Finder 或 Compressor。如果你使用的是 PC,你可能需要找一个 Mac 用户帮你完成这个操作。Compressor 应用程序只与 Final Cut Pro 捆绑在一起,所以我不会使用它,虽然如果你需要自定义设置,它可能值得考虑。
从 macOS Catalina 开始,Finder 内置了一个编码媒体工具,可以用于转换视频。它很简单(而且免费),所以它满足了我们的需求。
Finder 期望一个视频文件作为输入,所以首先,我们必须将图像序列转换为 ProRes 4444。这是非常重要的一步,因为编码媒体工具不会接受任何视频 - 除非你提供它接受的格式,否则它会失败。它让我头疼了好一阵子,直到我找到了输入文件的正确编码方式。
我们可以使用 FFmpeg 创建输入视频。就像我们创建 WebM 时一样,我们只需要使用正确的参数运行 FFmpeg 即可
ffmpeg -framerate 25 -i unscreen-%3d.png -c:v prores_ks -pix_fmt yuva444p10le -alpha_bits 16 -profile:v 4444 -f mov -vframes 150 output.mov
从现在开始,就需要一台 Mac 了。但这个过程很简单,不需要在终端中输入任何内容,所以即使你请一个不懂技术的朋友帮忙,我相信他们也能搞定。
准备好 ProRes4444 视频后,你就可以在 Finder 中导航到包含该视频的文件夹,右键单击它,然后在上下文菜单中选择“编码选定的视频文件”。

将弹出一个窗口。选择所需的 HEVC 质量(有两个选项可供选择),并选中“保留透明度”选项。然后单击“继续”按钮。

过了一会儿,你应该会看到一个新文件,它使用带 Alpha 通道的 HEVC 编码。完成了!在 Safari 中打开这个文件,确认透明度有效。

最后,该在网站上使用视频了!
为所有浏览器提供透明视频
我们可以使用 <video>
元素来提供视频。如果浏览器支持 src
属性中给出的格式,它就会直接播放。但正如我提到的,我们需要为 Safari 提供 HEVC,为其他浏览器提供 WebM。
还有一件事需要注意:有些浏览器支持 WebM 或 HEVC 本身,但没有透明度。这些浏览器会播放视频,但背景是黑色而不是 Alpha 通道。例如,Safari 12 播放 HEVC 时没有透明度。这对我们来说是不可接受的。
通常,我会使用 <source />
元素来提供视频以及多个格式作为回退,浏览器会选择它支持的格式。但是,由于我们只想在特定版本的 Safari 上显示 HEVC,因此我们必须使用 JavaScript 来设置视频的 src
属性。
带透明度的 HEVC 在 iOS 13 和 Mac Safari 13 中受支持,所以我们先检测它们。根据支持情况调整网站功能的推荐方法是检测 API 的存在,而不是查看用户代理,但我没有找到任何简单的方法来检测浏览器是否支持视频格式的透明度。相反,我找到了自己的解决方案。它并不完美,但它能完成任务。
function supportsHEVCAlpha() {
const navigator = window.navigator;
const ua = navigator.userAgent.toLowerCase()
const hasMediaCapabilities = !!(navigator.mediaCapabilities && navigator.mediaCapabilities.decodingInfo)
const isSafari = ((ua.indexOf('safari') != -1) && (!(ua.indexOf('chrome')!= -1) && (ua.indexOf('version/')!= -1)))
return isSafari && hasMediaCapabilities
}
这通过查看 navigator.mediaCapabilities
来针对 Safari 13 及更高版本,该功能在旧版本中不受支持,同时也查看浏览器是否为 Safari。如果函数返回 true
,那么我就可以使用 HEVC Alpha 了。对于其他情况,我将加载 WebM 视频。
以下是如何在 HTML 中组合使用它们的示例
<video id="player" loop muted autoplay playsinline></video>
<script>
const player = document.getElementById('player');
player.src = supportsHEVCAlpha() ? 'output.mov' : 'output.webm';
</script>
如果你对视频元素上的 loop muted autoplay playsinline
参数感到好奇,它们是用来复制类似 GIF 的体验的
- 没有
muted
,视频在没有用户交互的情况下不会播放。 - 使用
playsinline
,在 iOS 上,视频会直接在布局中的位置播放,而不是全屏打开。 - 使用
loop
,视频会循环播放。 - 使用
autoplay
,视频会在页面加载时自动开始播放(只要我们也设置了muted
)。
就是这样!我们得到了一种轻量级、高性能、高质量的透明视频解决方案,它适用于大多数现代浏览器(至少是最近两个版本的 Chrome、Firefox、Safari 和 Edge)。我们可以添加一些基本的 HTML 和 CSS 来将静态内容与之集成,并使其更接近真实场景,或者直接使用我演示中的相同思路。这并不难,对吧?
嘿,但是 IE 11 怎么办?我整个公司都在使用它!
一般来说,我建议将这样的功能限制在现代浏览器,并在 IE 中隐藏视频。视频可能不是网站的关键元素。不过,我以前曾参与一个商业项目,该项目必须支持 IE 11,我被迫想办法在 IE 11 中显示透明视频。最后,我使用 JavaScript 来循环播放 PNG 图像。我减少了帧数,并使用计时器在它们之间切换。当然,性能很糟糕,但它确实有效。视频对于整个设计来说非常重要,所以我们有意决定在 IE 11 上牺牲性能,以提供完整的体验。
总结
我希望我已经为你节省了一些研究透明视频的想法的时间,现在你应该能够在你的网站上使用这种动画元素了。我敢说你会用到的!
你有没有不同的透明视频使用方法?或者你有没有这方面的经验?请在评论中告诉我。
也许可以将一个画布元素覆盖在视频之上,并将其写入作为透明度层?
很棒的文章!
我研究这个问题已经好几年了,终于看起来浏览器开始做正确的事情了。
感谢分享!
感谢你的分享。
不幸的是,仅仅检查 Safari 版本是不够的。在台式电脑上,HEVC 解码仅在 Mac OS 10.15(Catalina)及更高版本中受支持。
在更早的版本中,视频会呈现为黑色背景。关于如何改进功能检测的任何建议都将不胜感激。
这正是我遇到的问题。希望有一个解决方案,可以为 MacOS <10.14 播放另一个版本,比如 GIF?
很棒的指南,感谢你的分享。
感谢你分享这个优秀的教程!我是 FFmpeg 的新手,我遇到了这个错误
与编解码器“libvpx-vp9”不兼容的像素格式“yuva420p”,自动选择格式“yuv420p”
我四处查找了一番,有人建议“将本机解码器更改为提供 Alpha 通道的 libvpx 解码器”,但不幸的是,他们没有提供如何操作的说明。你遇到过这个问题吗?你有什么建议吗?
提前感谢,非常感谢你的这篇文章!
这在 Mac、Windows 和 Android 浏览器上运行完美,但在 iPhone 上无法显示视频。有什么办法解决吗?播放器中已经包含“playsinline”了。
我知道可能我有点晚了,但无论如何:你还要添加“preload=metadata”属性,并在“src”值的末尾添加元数据。该值为要显示的视频的时间戳。示例如下
太棒了!!!一直在找这个。谢谢。你能帮忙吗?如何将新闻主播的视频浮动在我的 HTML(一个旋转的地球 js)之上?我需要用户控制并旋转地球。你在这里解释了所有这些吗?如果我想让我的视频成为直播怎么办?
那篇文章真是太棒了!非常感谢!
顺便说一下,值得一提的是,所有在 iOS 上的移动浏览器都应该被视为 Safari。例如,iOS 上的 Chrome 不支持 .webm 容器,其他浏览器也不支持,但 iOS 上的 Chrome 和其他浏览器支持 .mov 容器!
在关于“所有 iOS 上的移动浏览器都应被视为 Safari”的上一条评论中,我的意思是针对透明视频问题。
很棒的教程,但有没有办法在低于 13 版的 Safari 上播放不透明的 .mp4 视频,而在其他浏览器上播放脚本中的透明 .webm 视频?因为脚本只在 Safari 不低于 13 版的情况下才调用 .webm,但 Safari 仅从 15 版开始支持 webm。谢谢!