【ArchSummit架构师峰会】探讨数据与人工智能相互驱动的关系>>> 了解详情
写点什么

从 Flash 到 MP4,爱奇艺奇秀直播礼物特效精进之路

  • 2020-12-27
  • 本文字数:3425 字

    阅读完需:约 11 分钟

从Flash到MP4,爱奇艺奇秀直播礼物特效精进之路

虚拟礼物是主播和观众互动的重要道具,也是主播很大一部分的收入来源。当刷满足够礼物数量时,直播间就会飞出炫酷的礼物动效,它既能刺激主播更好地直播,也能满足用户在虚拟世界的荣誉感,越有诚意的礼物会触发越精彩的礼物动效,这也加深了主播和用户之间的羁绊。


随着直播平台的发展,设计人员不断创作出精美的礼物动效,相应的,动效加载时长和文件体积逐渐变大,而开发人员要需要能够吃下这些负担,在保证动效播放的高效和顺滑的同时,不给用户机器带来负担也不给设计人员的创作带去局限,这便是我们本文需要考虑的几个难点。本文将以奇秀 PCweb 端为例,从动效效果、性能、研发效率、兼容性等多角度谈谈礼物动效的发展。


演进之路


礼物动效的实现格式可以有很多种,不同文件格式之间各有利弊,从业务角度出发选取相对较优的方案是我们的目的。整条演进路上,我将带领大家从 Flash 时代开始了解多种动效格式,希望在了解多种方案后,你能找到适合自己业务的较优方案。


动效格式


●过去的王者:Flash


●动图:GIF、APNG、Webp


●开源和自研:Lottie、SVGA、IXD(自研)


●视频:MP4


Flash 时代


奇秀平台刚开始上线的时候,视频行业在网页端还是 Flash 的天下,基于 Flash 的流媒体播放器几乎是唯一选择,拿它实现动效制作也是很自然的事情,对设计师来说使用 Adobe Flash CC 导出 Flash 动画也是常规操作。


没多久,Flash 式微,html5 技术飞速发展,替换 Flash 变成迫切需要做的事情。彼时团队内部出现两种实现方向:


●APNG 动图


●自研新的动效方案


APNG 动图


APNG(Animated Portable Network Graphics)诞生于 2004 年,是一个基于 png 的位图动画格式,扩展方法类似主要用于网页的 GIF 89a,仍对传统 PNG 保留向下兼容,2017 年主流浏览器几乎都已经支持 APNG。由于当时平台上移动端一直是使用图片序列生成的 APNG/Webp 作为动效资源,为了保持多端的统一,PCweb 端也开始尝试使用动图作为后续的动效格式。



综合对比文件大小、效果以及浏览器兼容性,选择使用 APNG 作为新的动效格式。单纯使用<img>标签直接展示 APNG 会遇到如下几个问题:


●小部分浏览器不支持播放 APNG


●为了动效播放连贯性,需要预加载 APNG


●APNG 播放开始、过程、结束等时间点不受控


为了解决这几个问题,我们开始研究 APNG 的文件格式结构,包括 PNG 的结构和扩展的 acTL(动画控制块)、fcTL(帧控制块)、fdAT(帧数据块)。



基于对 APNG 的了解,对一些开源方案进行了调研测试,最终决定使用 apng-js 帮助我们解决上述几个问题。使用 apng-js 解析 APNG,可以得到 APNG 的很多信息,包括宽高、帧数、播放时长,以及播放过程中的每一帧画面,有了这些再配合 canvas 便可以将 APNG 绘制和控制起来。下面是设计的播放器参数的结构:


{     src: string, // 动效地址    selector: string            // dom容器    playStart: () => void, // 动画开始    playProgress: (index: number, totalTime: number, remainTime: number) => void, // 动画过程    playEnd: () => void, // 动画结束};
复制代码


上述设计以及播放、暂停、重播等使用方法,基本满足对 APNG 播放的控制,且在后续业务中也可直接实现支持音效礼物,只要在 start 处读配置播放对应的音频资源,end 处删除音频即可。为了提高动效播放的连贯性,在解析 APNG 后会将解析出的数据存入 indexedDB,后面在播放同一动效时便可省去下载和格式解析的耗时。


这种方案对于设计来说也很方便,AE 做好动画后,使用格式工具和插件直接导出动图即可。但是后面也发现了该方案的弊端,平台对动效的要求越来越高,越酷炫的动效体积越大,很多复杂动效甚至达到 5、6M。


自研 IXD


后 Flash 时代,另一部分同学开始了动效自研的路子。APNG 的本质是对 PNG 格式的扩展,除了向下兼容的 IDAT(图像数据块)块外,多了很多 fdAT(帧数据块),每一块都是完整的图像,每多一帧就会做一张位图的大小。如果每一数据块不是完整位图,而是图集素材,且数据块表示素材的位置、宽高、缩放等各种信息,那么素材复用率会极高,再辅以对应的解析,那么整体文件大小也会降低很多。



按照该思路去实现,封装了自研的 IXD 格式,原本 10M 的 PNG 序列可以被拆解压缩到 1M 以内,动效效果几乎没有收到影响。


对于使用端,只需要支持二进制数据和 PNG 位图的处理,再按照设定的格式解析数据块动态去渲染每一帧即可。对于开发人员,我们同步配套了 web 端 SDK。


为了方便设计师生产,也配套开发了动效编辑器,将素材导入到工具中,通过复用素材和组合效果的方式,支持叠加多个图层,最终导出 IXD 文件。对于有动态数据的动效,也支持变量占位,开发人员按照占位符取值,使得同一动效不同用户看到的各不一样。



同期市面上也出现了 Airbnb 的 Lottie 和 YY 的 SVGA 方案:


●Lottie 需要 AE 安装 Bodymovin 插件导出 JSON 文件给开发同学使用,有兴趣的同学可以去了解下。


●SVGA 也提供了 AE 插件,它做的事情其实和 IXD 类似。SVGA 从 AE 源文件里提取素材,并将素材在时间轴里的表现(位移、旋转、缩放等)导出,各端 parser 负责将这些还原到画布上。它比 IXD 优秀的点在于,提供了 IOS、Android 端的解析 SDK。


目前我们有 APNG 方案和 IXD 方案,包括市面上的 SVGA 方案,从播放可控到文件大小都有了一定的解决方案,似乎已经可以告一段落了。但这几个方案依旧有各自的缺陷:


MP4


有没有既能尽量保证 AE 动效,也能保证文件体积小的方案呢?有,用 MP4!肯定会有人以为我在开玩笑,MP4 都不支持透明,如何能够用来承担直播动效呢。我们先了解下透明是什么:图像的透明使用 Alpha 通道表示,即 RGBA 里的 A,该通道是一个 8 位灰度通道,由 256 级灰度来记录图像中的透明信息。说白了透明和 RGB 一样都是颜色信息,虽然 MP4 不支持透明通道,只要想办法给它展示出来就好了吧!还是 canvas 技术,只要我们可以用 canvas 把透明视频画出来就可以了。


通过和设计同学沟通,也参考了网络上的文章和讨论,最终决定将动效以上下同步的两块视频拼接而成。上面的视频保留原始的 RGB 信息,下面的视频将 A 信息用黑白来表示,当 MP4 播放的时候分别读取上下两块视频进行拼接,得到完整了 RGBA 像素信息,然后绘制在目标画布上。



代码很简单,canvas 入门的同学应该都可以写出来:


// 绘制视频buffer.drawImage(video, 0, 0, width, height * 2);// 读取上下视频图像数据let imageData = buffer.getImageData(0, 0, width, height).data;let alphaData = buffer.getImageData(0, height, width, height).data;// 塞alpha通道for (let i = 3, len = imageData.length; i < len; i = i + 4) {    imageData[i] = alphaData[i-1];}// 绘制canvasoutput.putImageData(image, 0, 0, 0, 0, width, height);
复制代码


本以为一切都特别顺利,结果进行性能测试发现动效绘制时 CPU 暴涨,根本无法投入生产。原因其实看代码也能发现,在视频播放过程中密集遍历处理像素点,计算频率太高,所以 CPU 暴涨。既然单纯 canvas2d 不行,我们就打算试试性能更好的 WebGL。WebGL(Web Graphics Library)基于 OpenGL,可以为 HTML5 Canvas 提供硬件 3D 加速渲染,也可以借助系统显卡来在浏览器里更流畅地展示 3D 场景和模型。WebGL 里的概念很多,有 scene、camera、texture 等,这里不会一一介绍,有兴趣的同学可以去了解下。在实现中为了便捷,我们借助 Three.js 来实现功能,利用 THREE.ShaderMaterial 自定义的着色器去处理,以下是核心代码:


gl_FragColor = vec4(    texture2D(texture, vec2(vUv.x, 0.5 + vUv.y/2.)).rgb,    texture2D(texture, vec2(vUv.x, vUv.y/2.)).r);
复制代码


经过性能测试和对比,动效播放时的 CPU 使用率显著降低:



总结


通过对以上各种方案的分析,从实际效果、资源大小、成本的角度我们得出以下表格:



我们的场景主要是直播间的礼物动效,暂时没有什么动效的用户交互需要,因此我们选择让设计同学充分发挥才能的 MP4 方案,设计同学无需学习第三方插件,也不用考虑资源大小而被迫抽帧导致降低动效质量。


我们坚持认为在礼物动效制作方面,MP4 的是未来的大趋势,视频编解码技术也在不断发展,H.265、H.266,视频文件体积将会不断缩小,用户等待的时长减少和带宽节省都是很不错的收益。


后续我们将继续深入 MP4 方案,在格式解析和动态素材占位上下功夫,尝试参照 IXD 的方案将配置信息写到文件中,创建一个新的 BOX 塞入 MP4 文件里,播放时候先取这个 BOX 读取配置信息,然后和后续的视频帧播放时结合起来达到实现动态素材的效果。也将继续研究 WebGL,寻求更加高效的渲染方式,争取进一步提高播放性能。


本文转载自:爱奇艺技术产品团队(ID:iQIYI-TP)

原文链接:从Flash到MP4,爱奇艺奇秀直播礼物特效精进之路

2020-12-27 07:002053

评论

发布
暂无评论
发现更多内容

数字钱包软件系统开发介绍(源码)

保姆级带你深入阅读NAS-BERT

华为云开发者联盟

推理 预训练模型 BERT NAS论文 NAS搜索

高效动画实现原理-Jetpack Compose 初探索

vivo互联网技术

动画 Google 框架 移动开发 Andriod

从单体架构到微服务架构

看山

微服务 10月月更

python 类中的那些小技巧,滚雪球第四季收尾篇

梦想橡皮擦

10月月更

“技术·探索”技术作家英雄会带你开启不一样的1024!

博文视点Broadview

一场穿越千年的智能矿山“梦游记”

白洞计划

Python代码阅读(第40篇):通过两个列表生成字典

Felix

Python 编程 Code Programing 阅读代码

架构实战营模块一作业

胡颖

架构实战营

数字货币钱包系统软件开发详情(源码)

RPAaaS是什么?为何能够推进RPA人人可用?

王吉伟频道

云计算 RPA SaaS 机器人流程自动化 RPAaaS

Spring Boot 两大核心原理

风翱

springboot 10月月更

Vue进阶(幺肆幺):Vue 计算属性 computed 方法内传参

No Silver Bullet

Vue 计算属性 10月月更

如何支撑企业快速构建数字孪生体

华为云开发者联盟

数据分析 IoT 工业物联网 数字孪生 华为云IoT数据分析

实用 | 利用 aardio 配合 Python 快速开发桌面应用

星安果

Python 软件 工具 aardio 桌面开发

【高热FAQ】关于智慧康养物联网加速器 ,你想知道的都在这

华为云开发者联盟

物联网 硬件开发 智慧康养 华为云物联网平台 SaaS应用

AI 在视频领域运用—弹幕穿人

百度Geek说

AI 后端 弹幕 视频

在线最小公倍数计算器

入门小站

工具

docker 系列:基础入门

yuexin_tech

Docker

中科柏诚本地生活,助力银行完成数字金融转型

联营汇聚

数字货币钱包软件系统开发简介(案例)

16个实用JavaScript代码片段:DOM、Cookie、数组、对象

devpoint

JavaScript DOM Cookie Object 10月月更

谈 C++17 里的 Factory 模式之二

hedzr

设计模式 工厂模式 Design Patterns factory pattern c++17

微信业务架构图

孙志强

架构实战营

【Flutter 专题】25 图解关乎 SQL 数据库的二三事(一)

阿策小和尚

Flutter 小菜 0 基础学习 Flutter Android 小菜鸟 10月月更

数字资产钱包系统开发源码搭建

虚拟币钱包软件系统开发(搭建)

【LeetCode】最长公共前缀Java题解

Albert

算法 LeetCode 10月月更

想要面试大数据工作的50道必看题

华为云开发者联盟

大数据 hadoop hdfs 数据分析 关系型数据库

官方线索|2021长沙·中国1024程序员节

liuzhen007

1024我在现场

新思科技网络安全研究中心发现Nagios XI存在漏洞

InfoQ_434670063458

从Flash到MP4,爱奇艺奇秀直播礼物特效精进之路_架构_爱奇艺技术产品团队_InfoQ精选文章