2025上半年,最新 AI实践都在这!20+ 应用案例,任听一场议题就值回票价 了解详情
写点什么

从 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:002766

评论

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

初级工程师职场生存要点

javaadu

程序员 职场成长 开发日志

《TED TALKS演讲的力量》阅读笔记

Jesse Xing

读书笔记 演讲 TED

面试前不陪女朋友也要看完这套spring源码面试题(附答案)

小Q

Java 学习 编程 架构 面试

jdk 源码系列之ReentrantLock

sinsy

源码 jdk ReentrantLock 公平锁 非公平锁

JMeter100个线程竟然只模拟出1个并发

dongfanger

软件测试 Jmeter 性能测试 压力测试 测试工具

金融科技的未来

CECBC

金融

从一场“众盟科技云滇之播”,我们发现了美食直播的商业与公益价值

脑极体

从智慧计算的点、线、面,读懂浪潮AI的进化轨迹

脑极体

《乌合之众——群体心理研究》读书笔记

Jesse Xing

读书笔记 心理学 乌合之众 群体心理学

Java垃圾回收GC概览

Java JVM GC

数字货币OTC交易所开发,交易所搭建方案

13530558032

USDT承兑支付平台技术开发,承兑商币支付交易平台搭建

13530558032

从接口异常说说线上问题排查流程

QiLab

线上排障 指标监控 链路监控 日志监控 排障流程

接口测试的时候如何生成随机数据进行测试

测试人生路

接口测试

音像协呼吁保护音乐版权:短视频平台成为侵权重灾区

石头IT视角

害怕重构?都怪我太晚和你介绍该如何重构,现在我来了

小Q

Java 学习 程序员 面试 重构

《精进:如何成为一个很厉害的人》阅读心得

Jesse Xing

读书笔记 个人成长 精进

算法有多重要,看字节腾讯等公司面试多重视就行了

小Q

Java 学习 架构 面试 算法

一不小心画了 24 张图剖析计网应用层协议!

苹果看辽宁体育

计算机网络 计算机 协议

一款区块链钱包开发需要多少钱?数字资产钱包开发搭建

13530558032

做个别人家的网页

MySQL从删库到跑路

html/css 网页设计

不会这些mysql得面试题,那可能说明你要回炉了

小Q

Java MySQL 数据库 学习 面试

搭建一套ASP.NET Core+Nacos+Spring Cloud Gateway项目

yi念之间

Android网络性能监控方案

移动研发平台EMAS

android 性能 监控 移动开发 应用

爆料!前华为微服务专家纯手打500页落地架构实战笔记,已开源

996小迁

架构 面试 分布式 微服务 程序人生

如何稳扎稳打推进数字货币进程

CECBC

数字货币

架构师训练营 - 第七周 - 作业一

行者

魏际刚:精准谋划我国供应链发展新方位

CECBC

供应链 物流

神经网络之dropout总述

Dreamer

学习

CDN是什么?

德胜网络-阳

18张图,揭开阿里巴巴开发手册强制使用SLF4J作为门面担当的秘密

沉默王二

Java slf4j 日志系统

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