用WebRTC打造一个Animoji + Facetime 的视频聊天应用
1, Animoji
Animoji是在iPhone X上的动画表情。是iPhone在十周年特别版iPhone X发布的新功能。其使用面部识别传感器来检测用户面部表情变化, 并最终生成可爱的3D动画表情符号, 目前只能在iMessage中使用. 但有人破解了Animoji, 并提取相应的头文件供大家在产品中使用.
2, Factime
FaceTime 是苹果公司iOS和Mac OS X内置的一款视频通话软件,通过Wi-Fi或者蜂窝数据接入互联网,在两个装有FaceTime 的设备之间实现视频通话. 用通俗的话讲就是视频电话.
之前在试用Animoji的时候觉得很神奇, 在想如果和实时的视频聊天配合起来应该很有意思, 大概花了半天的时间, 写出了这个小玩具.
首先Animoji:
在网上找到有人封装好的Animoji 头文件 github.com/efremidze/A…, 研究了之后发现并没有可以获得Animoji 一帧的接口, 我继续把这个库完善了一下, 暴漏出了可以获得每一帧数据的接口. 我fork 了一份代码在这里 github.com/notedit/Ani…, 修改之后的代码也已经PR到原来的项目中.
帧数据处理:
后面在做视频传输的时候需要CVPixelBuffer, 而我们这里从Animoji里只能获得CIImage, 另外我们需要对取得的数据做一次缩放处理, 避免图片过大. 这里主要使用了CoreImage 和 CVPixelBuffer的一些处理, 直接上代码:
-(CVPixelBufferRef)processCIImage:(CIImage*)image { @autoreleasepool { [filter setValue:image forKey:kCIInputImageKey]; CIImage *outimage = [filter outputImage];NSLog(@"outimage widthxheight %dx%d", (int)outimage.extent.size.width,(int)outimage.extent.size.height); CVPixelBufferRef outPixelBuffer = NULL; CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault,(int)outimage.extent.size.width,(int)outimage.extent.size.height,kCVPixelFormatType_420YpCbCr8BiPlanarFullRange ,(__bridge CFDictionaryRef) @{(__bridge NSString *) kCVPixelBufferIOSurfacePropertiesKey: @{}},&outPixelBuffer);if (status != 0) { NSLog(@"CVPixelBufferCreate error %d", (int)status); CFRelease(outPixelBuffer); return nil; } [ciContext render:outimage toCVPixelBuffer:outPixelBuffer bounds:outimage.extent colorSpace:nil]; return outPixelBuffer; }
}复制代码 到这里你已经可以很happy的拿到Animoji的帧数据了.
视频通话:
为了快速完成这一部分我直接使用了我们的音视频通话SDK — dotEngine , 支持自定义的YUV 数据输入, 然后我们就可以很愉快的把上一步拿到的数据喂给这个SDK.
大概的流程如下
dotEngine = DotEngine.sharedInstance(with:self)
localStream = DotStream(audio: true, video: true, videoProfile: DotEngineVideoProfile.DotEngine_VideoProfile_360P, delegate: self)videoCapturer = DotVideoCapturer()localStream.videoCaptuer = videoCapturer// some other codelet image = self.animoji.snapshot(with:self.animoji.frame.size)let ciimage = CIImage(image: image!)let pixelBuffer = self.convert.processCIImage(ciimage)
if pixelBuffer != nil { self.videoCapturer?.send(pixelBuffer!.takeUnretainedValue(), rotation: VideoRotation.roation_0) pixelBuffer?.release()
}复制代码 运行效果如下图:
完整的代码在 github.com/dotEngine/a…
我们的音视频通讯SDK dotEngine github.com/dotEngine
转载于:https://juejin.im/post/5aaa086d6fb9a028b77a887c
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
