NVIDIA 初创加速计划,免费加速您的创业启动 了解详情
写点什么

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

评论

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

架构师系列 14 PageRank算法

桃花原记

简化业务代码开发:看Lambda表达式如何将代码封装为数据

华为云开发者联盟

函数式接口 数据 代码 函数 lambad

redis持久化怎么选?成年人从来不做选择...

moon聊技术

《我想进大厂》之分布式事务篇

艾小仙

Java 面试 后端

是找茬?还是装B?阿里面试每轮必问的“Spring Boot”意义何在?

比伯

Java 编程 架构 面试 计算机

阿里巴巴2021年最新开源十亿级Java高并发系统设计手册

Java架构追梦

Java 阿里巴巴 架构 并发 系统架构设计手册

Elastic search 单节点、两节点、三节点环境

escray

elasticsearch elastic 28天写作 死磕Elasticsearch 60天通过Elastic认证考试

IM即时通讯实现的原理

v16629866266

惊喜来袭!253页全彩免费电子书《Python 编程参考》正式上线发布

穿甲兵

Python redis 程序设计 Go 语言

作业1

瑾瑾呀

2020中国ToB独角兽:估值逆势起飞,寡头效应加剧

ToB行业头条

iTerm2 实现 ssh 自动登录,并使用 Zmodem 实现快速传输文件

米开朗基杨

iterm2

合约跟单交易软件系统开发|合约跟单交易APP开发

系统开发

SpringCloud 从入门到精通 11---Nacos负载均衡

Felix

Java 程序经验小结:返回零长度的数组或集合,而不是null

后台技术汇

28天写作

我所认为的产品经理能力模型

day day up

热情空前,家长纷纷变身“寒假规划师”,如何抓住这波热潮?

ZEGO即构

AI 在线教育 在线课堂

COCO聊天挖矿系统开发|COCO聊天挖矿软件APP开发

系统开发

【有奖调研】中国人工智能开发者调研

百度大脑

阿里架构师深入讲解Android开发!教你一种更清晰的Android架构!BAT大厂面试总结

欢喜学安卓

android 程序员 面试 移动开发

架构师 3 期 3 班 -week8- 作业

zbest

作业 week8

iOS音视频--视频合集

程序员 音视频 OpenGL ES GPUImage Metal

盘点2020 | 百度AI的2020

百度大脑

盘点2020

地下钱庄简单介绍

IT方案内参

大数据 地下钱庄 技战法

使用Apollo升级一下yml文件管理和发布

Sky彬

springboo

WebRTC 的现状和未来:专访 W3C WebRTC Chair Bernard Aboba

阿里云视频云

阿里云 WebRTC 视频云

《2020年微信视频号研究报告》 | 视频号 28 天 (11)

赵新龙

28天写作

TarsBenchmark | 服务性能压测利器

TARS基金会

微服务 压力测试 TARS

QA为什么转换角色

BY林子

软件测试 QA 职业发展

Soul网关源码阅读番外篇(一) HTTP参数请求错误

Java 源码阅读 网关

阿里架构师经验分享!Android面试知识点总结宝典助你通关!顺利通过阿里Android岗面试

欢喜学安卓

android 程序员 面试 移动开发

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