玩大了! 阿里工程师的年会竟然这样搞?

简介:

不用邀请函、不用签字板,“笑容”才是唯一的入场凭证。年会还有这样的操作?

最近在阿里巴巴内部就掀起这样一阵“笑容签到”风潮。在年会开场,大家是这样排队刷脸的:

0c1e5a6cc142ccc6233f13789b565c6f3bcd5c57

而刷脸成功后,入场人员的花名、头像以及“笑容指数”会实时同步显示在会场大屏幕上,并汇聚成一个“笑脸星球”。

9fd5b1b5e7cbc0193a85e9d8d936bd1f7ab60a52

这是阿里巴巴信息平台一群90后工程师,用两周时间开发的一套年会开场秀系统:

观众在经过人脸识别后,系统会根据人脸表情特征,识别出观众的花名(名字)与微笑指数,同时吐出一句“评语”。当笑容越灿烂,评价就会越高。同时通过技术手段,这些信息还会上屏展示与互动。

afbb098f7966eaa7e8bae52d61d62535d66688e4

工程师们在现场调试

不仅是部门年会,在内部一些大型比赛、重要颁奖典礼等活动开场,也逐步用起了这一套科技感满满的开场秀。同时根据活动不同主题,还可以进行个性化定制呈现。

a23c46304584da30144cbcb54842468046dd21e2

阿里内部一些重要大会陆续使用这套系统开场

究竟这套年会开场秀系统如何实现的?今天,阿里妹邀请到该项目团队中的开发小哥哥探源,来聊聊背后的实现原理与技术方案。

背景

传统大会通常采用的暖场方式是,在大屏幕上循环播放宣传视频,等观众差不多到齐时,一个321的倒计时宣告开始,既老套又缺乏互动。更是白白错过一次向观众展示公司技术与公司人才的机会。

那有没有一种可以将科技感与互动感结合的开场秀呢?恰逢新一财年信息平台部门大会在即,我们想以此为切入点,给大家玩一些不一样的开场。

解决方案

任何一个“靠谱”的前端工程师,肯定会下意识想用H5动画来替代视频。我们的方案是:使用酷炫的H5动画,并且结合智慧园区团队的人脸识别技术实现人员扫脸签到+大屏展示的技术方案。既能运用及展示内部的技术,又能起到不错的暖场效果。

2254301e2e400163adb3898cab5ca39058281a12

根据方案构想,很快就形成了初版需求demo。梳理一下,可以拆分出下面几点功能:

d47e62d2b349aca45e42305ed6714efbe5ed61d9 初始状态下,是默认做自转运动的星球,周围有围绕的卫星
d47e62d2b349aca45e42305ed6714efbe5ed61d9 当人员进场时,人脸识别成功后,在屏幕上展示
d47e62d2b349aca45e42305ed6714efbe5ed61d9 展示完之后,照片要飞回到自转的球面上,跟着球一起做自转运动
d47e62d2b349aca45e42305ed6714efbe5ed61d9 会议开始前,人工控制照片做粒子效果,over

技术方案

当功能拆解后,便是研究怎么实现方案了。出于对效果考虑,准备选择3维动画来创作,并最终采用了Three.js作为3D引擎库,结合tween.js作为配套的动画库,以及基于webpack的脚手架nowa链接作为技术支持。

whyThree.js?

目前市面上比较成熟的3D库有Three.js和Babylon.js,但对比两者后可发现:

d47e62d2b349aca45e42305ed6714efbe5ed61d9 Babylon.js常用于制作3d游戏引擎,倾向于游戏开发;而Three.js是纯渲染引擎。
d47e62d2b349aca45e42305ed6714efbe5ed61d9 Babylon.js诞生不久(13年),社区活跃;而Three.js相对久一些(比webgl还久),且比较流行,代码易读,团队成员有相关的开发经验。
d47e62d2b349aca45e42305ed6714efbe5ed61d9 Babylon.js已经支持了webgl2的多数特性,并且能够平滑降级;而Three.js还是处于提需求阶段,并没有支持。

所以最后选择的是Three.js,想尝试下webgl2.0的小伙伴可以试下Babylon.js。

技术实现

介绍完技术引擎后,接下来将结合整体的功能流程,为大家解析下如何通过技术实现。

447856a53c4bcc6dac889e20dea4228b939efc79

step1:让球体运动起来

d2fbf0bfbdb15764a82031d5d0715fb9b4d548fa

这是动画展示效果的第一步。通过Three.js的基本方法,很容易实现在场景中添加对象的功能。如上图所示,在场景中添加了一个球体,并让它做顺时针的转动,而让球表面的图做逆时针的转动,并向场景中添加了不断向z轴负方向运动的星星,和做一定角度的公转运动的卫星。

bea541cbbdd43b3b8483b84757a3713582a6c307

三维坐标系中的点坐标x,y,z可以转换成了(上图)中的极坐标r,θφ(半径r和两个角度θ 和φ),同样可以用来表示点的位置(反过来也能推导)。

球面上的方片也是由对象构成。人员签到成功之后,方片上会变成照片,这里需要事先计算出方片相对于球面的位置以便生成方片。根据前期配置的到场人数n,从而让球面生成均匀分布的n个点,得到每个点的极坐标系位置,再转换成点坐标位置,这些位置就是方片位置。

step2:加入“微笑”展示效果

09db1230ff836eda5716b322397ef19f7c334e0f

前端通过轮询定时请求后端接口,来拉取人脸识别数据,展示之后告诉后端已经展示过了。由于现场人脸识别后的“微笑”需要实时展示在主屏上,每场年会活动到场人数不等(约500-1500人),在这一状况下,如何保证在规定时间内完成人员入场与展示。我们的方案是:展示时间可以动态调节,人流量大时识别成功之后大屏就展示快一些,反之则展示慢一些

因此,需要在前端维护了一个队列,用于存储识别成功但还未展示人员,轮询拉取的数据会进入到队列中,展示过的数据则会从队列中移除,一个展示动画的时长会根据队列的长度动态调节,取值范围2.5-5s不等。

step3:让“微笑”随球体一起运动

“微笑”展示后,还有个照片飞回球面并跟着球体一起运动的效果。因为牵涉到坐标系的相对运动球面的位置是相对于父元素来实现的),这一效果较难实现。

通过step1,可以计算出方片的位置position(position是个三维向量:xyz),因为位置是相对球体的,所以从球体看来方片的位置永远是xyz,而在全局看来,方片的位置是永远在变化的,而这个位置坐标怎么获取是一个问题。

当时,小伙伴们想到了两种方案:

第一种:让照片相对球体运动,这样就不用去考虑方片位置了,因为这个位置是不变的。但这样的弊端是,因为球体在运动,照片也需要一直运动。如果要达到视觉上看“照片不动”的效果,就需要照片永远对着摄像头。

第二种:让照片相对全局运动,在每一帧的时候去获取方片相对于全局的坐标。然后在这一帧内慢慢趋近于这个坐标,最后实现位置的重叠。

经过讨论,决定采用第二种方案。因为核心是要解决坐标系相对转换的问题,但第一种方案并没有解决,只是把问题方式转移了。还好,Three.js提供了现成的方法:getWorldPosition用于返回表示对象在世界空间中的位置向量。

这样,就可以得到方片的全局坐标。

现在知道了照片的位置和最后需要到达的位置。但如果直接从初始位置向最后位置运动,还会有个问题:照片可能直接穿过球体而达到最后的位置(不符合运动规律),所以这里需要尽可能做曲线运动,而不是让照片穿过球体。

我们还是用到了上面的坐标系转极坐标系的公式,通过初始的极坐标位置(sourceR,sourcePhi,sourceTheta)和目标位置的(targetR,targetPhi,targetTheta)。根据线性差值公式计算出在每一帧中的中间位置(currentR,currentPhi,currentTheta),再转换成点坐标系下的位置,即为每一帧时照片的位置,从轨迹上来看是一个曲线运动,且不会穿过球体。 

step4:粒子动画开场

c3385372d331f1e3e51227916bdcf0022dc291c0

终于进入最后的环节了。在活动正式开场前,“笑脸星球“会散开成粒子状态,通过粒子运动拼成本场活动的主题文案。这里运用到粒子动画效果,需要事先知道每个粒子最后运动的位置。我们参考了canvas粒子动画的效果(具体可以自行查一下),简化如下:

  1. newImage加载图片
  2. context.drawImage把图片画到一张canvas画布上
  3. 通过context.getImageData就可以获取画布上指定区域的像素数据
  4. 比较每个点的像素值就可以记录下需要像素点的位置信息,转换成3D的坐标
  5. 这边会涉及坐标系的转换,需要特别注意一下,平面canvas的坐标系和THREE.js的坐标系是不一样的)。
  6. 创造粒子,让粒子做飞散状运动起来,最后到达指定位置即可
  7. 事先准备两张图片,一张白底透明,一张彩色透明,粒子运动完成之后白底渐渐显示
  8. 然后白底渐隐,彩色的渐渐显示

性能优化

客观因素如:大屏分辨率、设备显卡等不考虑,但需要更多从可控条件来解决部分性能问题。一般衡量动画是否卡顿用fps衡量,如果在30-60帧之内肉眼基本无感知,再往下,会感受到很明显的卡顿。第一版开发完成之后,在mac上的帧率只有20+到40。肯定达不到标准,所以从以下几个方面开始优化。

1.尽量重用MaterialGeometry,或者缓存模型;

BufferGeometry 会缓存网格模型,性能要高效点。网格模型生成原理。

d47e62d2b349aca45e42305ed6714efbe5ed61d9 Geometry 生成的模型是这样的 (代码)-> (CUP 进行数据处理,转化成虚拟3D数据) -> (GPU 进行数据组装,转化成像素点,准备渲染) -> 显示器第二次操作时重复走这些流程。
d47e62d2b349aca45e42305ed6714efbe5ed61d9 BufferGeometry 生成模型流程 (代码) -> (CUP 进行数据处理,转化成虚拟3D数据) -> (GPU 进行数据组装,转化成像素点,准备渲染) -> (丢入缓存区) -> 显示器第二次修改时,通过API直接修改缓存区数据,流程就变成了这样(代码) -> (CUP 进行数据处理,转化成虚拟3D数据) -> (修改缓存区数据) -> 显示器。

2.减少渲染的对象,或者渲染的时候让对象不可见:渲染过不再需要的对象可以设置visible = false,或者直接从scene中remove,两者的区别可以参考Three.js scene.remove vs. visible=false;

3.谨慎地在render()中操作:一般FPS为60也就意味着一秒会执行60次如果render()中有有实例化或是赋值操作很容易会崩溃;

4.选择合适的对象:粒子我就是用Sprite代替Mesh实现的;

5.考虑光源的影响:会影响场景中对象的渲染;

6.渲染的对象时side属性尽量用FrontSide,DoubleSide会导致更多的渲染,也是减少渲染的方法;

7.可以用着色器来渲染,用更底层的glsl来实现。

优化完之后的状态:在mac上基本上都是60fps。保证了最终效果的实现:

8c64196593c2ae32f5fc59b0b9a804c5ca75181f

未来规划

万万没想到,一套专为部门年会做的方案,正逐步演变成一个成熟产品。并且通过可视化、定制化的配置,结合人脸识别技术已经支持集团多个部门的年会与活动。

随着使用场景的不断丰富,未来我们还将针对活动主题,在活动过程中增加互动。比如根据入场时的人脸识别,支持抽奖等现场互动,实现年会大屏、观众手机、人脸闸机等多屏互动。此外,在面向参会观众,还将生成现场图片等素材,方便收藏。

信息平台事业部是阿里巴巴经济体服务的基础平台,为阿里巴巴提供生态化、国际化、数据化、移动化以及安全稳定的企业信息服务。我们希望能有更多同学加入,通过技术创新,挑战自己的不可能,同时为阿里巴巴更多可能性的发生贡献力量。


原文发布时间为:2018-06-21

本文作者:阿里妹

本文来自云栖社区合作伙伴“阿里技术”,了解相关信息可以关注“阿里技术”。

相关文章
|
4月前
|
缓存 运维 容灾
入行5年,谈谈我在阿里做测试开发的经验
作者在阿里一直从事测试开发相关工作,这几年学习很多、收获很多,作者希望给还在该方向摸爬滚打的同学一些启发和方向。
|
消息中间件 设计模式 Kubernetes
【面经分享】-一年工作经验阿里三面
【面经分享】-一年工作经验阿里三面
【面经分享】-一年工作经验阿里三面
|
网络性能优化 双11
这位三个月就想辞职的阿里工程师,现在,真香!
他前段时间和剑桥大学教授 Frank Kelly 合作,设计了新一代高速网络拥塞控制协议 HPCC。
450 0
这位三个月就想辞职的阿里工程师,现在,真香!
|
缓存 移动开发 前端开发
我在阿里招前端,我该怎么帮你?
良心解读:JD 分析图谱 我面试过的同学,在结束的时候,我都会指出问题,并给出学习建议。大部分同学不是不够努力,不是不够聪明,而是没有找对方法,没有切中要害。我总结了一下之前所有的面试经历,以及常见的问题,写下这篇文章,希望能够给前端的同学,不论是否来面试阿里的职位,有一个参考。同时,也是写下我自己总结的方法,希望能帮助到其他技术相关的同学
14315 0
我在阿里招前端,我该怎么帮你?
|
程序员 Java 开发工具
阿里工程师谈,什么是好的代码?
我们每天都与代码打交道,但当被问道什么是好的代码时,很多人可能会先愣一下,然后给出的回答要么比较空泛,要么比较散,没办法简单明了地概括出来。显然,这个问题并没有唯一的标准答案,谁都可以谈论自己的理解,今天谈谈我对于好代码的理解。
7972 0
阿里工程师谈,什么是好的代码?
|
前端开发
真香!阿里工程师的一段代码让我看饿了
阿里妹导读:打开盒马app,相信你跟阿里妹一样,很难抵抗各种美味的诱惑。颜值即正义,盒马的图片视频技术逼真地还原了食物细节,并在短短数秒内呈现出食物的最佳效果。今天,我们请来阿里高级无线开发工程师莱宁,解密盒马app里那些“美味”视频是如何生产的。
7012 0
|
Android开发 Java
【面小易-面经10】阿里巴巴Android客户端开发实习生面试经验
又到了“金九银十”的招聘季,各位小伙伴们是不是也在忙着准备面试呢找工作呢?在接下来的一段时间里,面小易会为大家分享各种面试经验哦!请持续关注我。今天要和大家分享的是一位投递阿里巴巴Android开发实习生同学的面试经验,虽然他最终止步于二面,但是他的面试经验还是值得我们学习的,就让我们一起来看看吧。
4931 0
|
Java Spring 数据库
【面小易-面经02】蚂蚁金服Java开发工程师面试总结
又到了“金九银十”的招聘季,各位小伙伴们是不是也在忙着准备面试呢找工作呢?在接下来的一段时间里,面小易会为大家分享各种面试经验哦!请持续关注我。本文中,又是一位投递蚂蚁金服Java研发工程师的小伙伴总结的面试经验哦,一场面试中究竟问到了哪些内容呢?一起来看看吧!
8094 0
|
Java 算法 消息中间件
【面小易-面经01】阿里巴巴Java开发工程师面试总结
7月9日 19:00-21:30 阿里云开发者社区首场“Offer 5000”直播开启!15位团队技术大牛在线招人,更有《阿里云技术面试红宝书》助你拿下Offer!马上投递简历:https://developer.aliyun.com/special/offerday01
17978 0
|
C++ 算法
【面小易-面经03】阿里巴巴C++研发实习生面试经验总结
又到了“金九银十”的招聘季,各位小伙伴们是不是也在忙着准备面试呢找工作呢?在接下来的一段时间里,面小易会为大家分享各种面试经验哦!请持续关注我。本文为大家分享了一位拿到阿里巴巴C++研发实习生Offer的同学总结的面试经验,赶快搬起自己的小板凳来围观吧。
4823 0

热门文章

最新文章