本文首发个人博客 blog.eastpiger.com

例行废话##

1024那天,应wph的邀(guai)约(pian)带着小伙伴们一行七人到杭州参加SegmentFault Hackathon。这是我第一次参加这种活动,估计他们六个也是。幸好半路抓来了一个同校研究僧学长垫背。学长是参加过类似比赛的,好歹能带带我们。当时是这么想的——最后事情也就是这么发展的。

Hackathon的主题是“科技改变生活”,经过我们的讨论,我们一致认为,这个题目并没有什么卵用。当然也不是完全没有用处,好歹指导我们把脑洞开向了一个词“吃喝玩(piao)乐(du)”。

所以,OneMoreFace项目就这么诞生了。

Describe##

我们官方提交的项目说明是这样的:

基于面部识别和 WebRTC 的多人同步匿名娱乐聊天服务。提供多人同时在线,文本发送,视频识别覆盖个性化数字面具等功能。本项目使用了 clmtrackr 项目和实时猫 WebRTC 大厅服务。

其实他是这样的

本项目的目的在于在现有的匿名交(yue)友(pao)平台之上,添加一种既能保证安全性和隐私性,又能像面对面沟通一样可以准确传达表情和情感的技术手段。也就是说,数字换脸,顺带同步真实表情的效果。

技术关键词##

两个实现关键点:

  • 在线视频通讯
  • 图像处理

对应了两个我们最终选择的技术手段:

  • WebRTC
  • 开源项目clmtrackr

前者是Google提出的在线流媒体传输的框架,这个技术目前应该还是Draft状态,不过基本功能Webkit等一干内核应该都支持得可以(于是我们就被坑了……)

后者是学长推荐给我们的一个人脸定点识别的开源框架,这个框架实际上已经做好了很大一部分人脸识别以及三维建模的工作,甚至已经提供了换脸这个基本demo的样式,对于时间要求比较紧的我们来说确实很有用处。

实现流程##

面部处理交给scientist和makeapp做去了,表示并不知道他们做了什么……

我主要是做两者的结合工作,一来是先调通WebRTC流通讯,二来是接入我们面部的处理工作,最后争取让整个项目看起来还像是那么回事。

调WebRTC其实蛮简单,我们直接调用了实时猫的技术就实现了双人对通的效果。由于后面的一些状况,我实际上在现场把实时猫的代码反混淆之后差不多重新读了一遍了,整体感觉他的前端API差不多就是WebRTC上封装了简单地一层,实际上的这种封装和直接调用WebRTC进行通讯没多大差别。当然我们看中他的原因也是有的,比如期望直接拿他的Demo代码修改修改就可以运行,虽然事后证明我们想多了……不过使用实时猫也为我们提供了一些方便,不用单独去部署后端服务,Session和Token的机制实时猫都已经做好了,这在当时那种【时间短】【网络不稳定】【我懒】的特殊情况下还是非常有用的。

实时猫官方给的Demo还是0.1版本的,非常不稳定和不准确,他给的多用户连接甚至是手工创建两个页面手工写入Token来实现的。而图像的Stream则直接来自于MediaDevices.getUserMedia()函数,并简单粗暴的输出到LocalVideo标签。clmtrackr那边也并不顺利,他的Demo代码兼容性实际上可以认为就是没有……对多图同步处理毫无办法,也与WebRTC很难接入。

基于上述的问题,我继承了在中科院无线中心实习的时候练就的一项粗暴的思路,劳资重构一个数据类型干掉他╭(′▽`)╯

构造一个数据类型Clmtrackr,内部仿照Clmtrackr的面部模拟Demo封装了面部替换的构建逻辑,坚定地向着松耦合的方向迈步,也就为了最终能够实现多视频独立处理提供了先决条件了。

之后便是在实时猫的Demo代码之上做修改,先是用Clmtrackr类替代了localStream.play("localMediaContainer");这句本地播放的语句,其次基本重新修改了“stream-subscribed”的event函数。

接下来就画画前端咯,加一下msgstream的功能咯,然后就哈哈哈哈得做完咯……

然后我们就如愿以偿的挂了……

主要的难点有几个,首先,是根据我们的想法,肯定是要做好私密性为上,那么最基本的想法就是客户端将自己的视频数据识别处理之后再广播出去。这样我们就需要HTMLCanvasElement.captureStream()这个函数帮助我们将canvas转换到tream之后发给广播。然而……特么这个函数居然都是Not supported……

最终的解决方案实际上是我们特别特别不爽的,也就是实际发送的是每个人的摄像头获取的原始图像,广播出去后接受方在本地进行匹配和识别。这导致了严重的性能问题、无法承担过多人数同时在线、疯狂的内存泄露.

第一个问题导致我们卡了两个多小时,甚至一度准备更换方向。然而后面这个更是一个大坑,简单来说,就是实时猫的“stream-message-received”事件收不到数据,一开始我以为是发送函数有问题,又怀疑是网络问题,还怀疑是不是必须单独去开messagestream来传输数据,全部无效。也就促成我直接去撸实时猫的前端SDK源代码去了~>_<~

看到了“_message”这个内部事件……

打算调试一下这个事件看看有啥……

于是我收到了“session-message-received”事件……

……

┏ (゜ω゜)=☞你不走、我走!

本宝宝不开心了!

然而并没有什么卵用……抱怨完了继续滚去码代码……

TimeStone##

  • 1024 下午10时 初步定下开发方向
  • 1024 下午11时 服务器配置以及逻辑跑路
  • 1024 下午100时 github提交-实现了WebCRT基本视频直播
  • 1024 下午110时 github提交-实现WebCRT与Clmtrackr的识别处理联动
  • 1025 早10时 github提交-Clmtrackr封装完成,WebCRT大厅完成
  • 1025 早101时 github提交-基本完成前端
  • 1025 早1010时 github合并mask数据

Information##