微信里的小视频功能(有些移动端IM里也叫“短视频”)是微信6.0版亮点功能之一,微信技术人员在开发此功能过程中遇到过不少问题,现将技术实现过程中遇到的问题及解决方案分享给大家,希望能对有类似需求的同行有所启发。

1录制需求

支持白平衡、对焦、缩放;

录制视频长度6秒,30帧/秒,尽量不丢帧;

能录制不同尺寸和码率的视频。

2播放需求

可以同时播放多个视频;

用户操作界面时视频可以继续播放;

播放时不能卡住界面,视频滑进界面内后要立即播放;

视频在列表内播放是静音播放,点击放大是有声播放。

技术实现:录制

对于需求1:“支持白平衡、对焦、缩放”,AVFoundation有API可以支持,这里不多说。这里重点说说需求2:“录制视频长度6秒,30帧/秒,尽量不丢帧”、需求3:“能录制不同尺寸和码率的视频”的实现方案。

前期录制方案如下:

创建AVCaptureSession,设置拍摄分辨率;

添加AVCaptureInput,如摄像头和麦克风;

添加AVCaptureOutput,如AVCaptureVideoDataOutput、AVCaptureAudioDataOutput:

这里AVCaptureAudioDataOutput建议在Session -startRunning后才添加,避免影响摄像头启动时间。

添加AVCaptureVideoPreviewLayer,为用户提供拍摄预览界面;

创建MMovieWriter,里面包含AVAssetWriter对象,用于写视频;

开始捕捉-startRunning;

AVCaptureVideoDataOutput和AVCaptureAudioDataOutput不停地往MMovieWriter传递VideoSampleBuffer和AudioSampleBuffer,MMovieWriter对VideoSampleBuffer做分辨率压缩,以及对AudioSampleBuffer做码率压缩;

结束捕捉-stopRunning,MMovieWriter停止写视频,把生成的视频文件抛给上层。

在4s以上的设备拍摄小视频挺流畅,帧率能达到要求。但是在iPhone4,录制的时候特别卡,录到的视频只有6~8帧/秒。尝试把录制视频时的界面动画去掉,稍微流畅些,帧率多了3~4帧/秒,还是不满足需求。通过Instrument检测,发现跟写音频时的压缩有关,写音频时阻塞了AVFoundation的线程,引起后续的丢帧。网上也有人反馈类似问题。把写音频去掉后,帧率果然上去了。但是系统相机的拍摄视频是非常流畅的。于是用AVCaptureMovieFileOutput(640*480)直接生成视频文件,拍视频很流畅。然而录制的6s视频大小有2M+,再用MMovieDecoder+MMovieWriter压缩至少要7~8s,影响聊天窗口发小视频的速度。即时通讯聊天软件app开发可以加蔚可云的v:weikeyun24咨询

综上所述,要想拍视频不卡,就要在录制过程中尽量不做CPU耗时操作,而且AVCaptureOutput传递数据给上层时不能卡住AV线程。最终想到个方案,加个Cache层,先把AVCaptureOutput传递的SampleBuffer缓存下来,不在AV的线程写视频;等CPU空闲时,再唤起movieWriter线程写视频。

通过这样处理,拍视频流畅度跟系统相机接近了,只是刚拍的前1s帧数只有18帧,后面稳定到30帧/秒左右了。而且用户松手拍完后,最多等1s就能把视频写完文件了;也优化了之前的视频截图生成接口,减少200ms。不过拍摄稳定性不够好,经常出现下面的写失败错误,频率大概是6次/100次:

通过google搜索,网上说这错误原因是同一个FrameTime写入了两帧。但是FrameTime是从SampleBuffer里取的,理论上不会时间重合(我没打log验证);而且老方案没出现这种错误,新方案延后处理才会出现的。经过多次试验,把Buffer

Cache设置上限,当Buffer数达到一定数量后强制让MovieWriter写入文件,同时把下面这行代码注释,错误不再出现了:

技术实现:播放

1MPMoviePlayerController方案

MPMoviePlayerController是一个简单易用的视频播放控件,可以播放本地文件和网络流媒体,支持mov、mp4、mpv、3gp等H.264和MPEG-4视频编码格式,支持拖动进度条、快进、后退、暂停、全屏等操作,并为开发者提供了一系列播放状态事件通知。使用时先设置URL,然后把它的view add到某个parent view里,再调用play即可。

但这方案的缺点是,同一时间只能有一个MPMoviePlayerController对象播放,不满足同时多个播放的需求;而且也不支持静音播放。MPMoviePlayerController适合于全屏播放视频的场景。

2AVPlayer方案

VPlayer是AVFoundation.Framework提供的偏向于底层的视频播放控件,用起来复杂,但功能强大。单独使用AVPlayer是无法显示视频的,要把它添加到AVPlayerLayer里才行。另外它需要配合AVPlayerItem使用,AVPlayerItem类似于MVC里的Model层,负责资源加载、视频播放设置及播放状态管理(通过KVO方式来观察状态)。

AVPlayerItem的status属性有三种状态:AVPlayerStatusUnknown、AVPlayerStatusReadyToPlay及AVPlayerStatusFailed。当status=AVPlayerStatusReadyToPlay时,就代表视频能播放了,此时调用AVPlayer的play方法就能播放视频了。

相比MPMoviePlayerController,AVPlayer有最多可以同时播放16个视频。另外AVPlayer在使用时会占用AudioSession,这个会影响用到AudioSession的地方,如聊天窗口开启小视频功能。还有AVPlayer释放时最好先把AVPlayerItem置空,否则会有解码线程残留着。最后是性能问题,如果聊天窗口连续播放几个小视频,列表滑动时会非常卡。通过Instrument测试性能,看不出哪里耗时,怀疑是视频播放互相抢锁引起的。

3AVAssetReader+AVAssetReaderTrackOutput方案

既然AVPlayer在播放视频时会有性能问题,我们不如做自己的播放器。AVAssetReader可以从原始数据里获取解码后的音视频数据。结合AVAssetReaderTrackOutput,能读取一帧帧的CMSampleBufferRef。CMSampleBufferRef可以转化成CGImageRef。为此,我们可以写个MMovieDecoder的类,负责视频解码,每读出一个SampleBuffer就往上层回调:

另一个是MVideoPlayerView,负责视频的显示,它接收MMovieDecoder回调的CMSampleBufferRef后,把它转为CGImageRef,然后设置layer.contents为这个CGImageRef对象。创建CGImageRef不会做图片数据的内存拷贝,它只会当Core Animation执行Transaction::commit()触发layer -display时,才把图片数据拷贝到layer buffer里。

AVAssetReader也能decode音频的SampleBuffer,不过本人还没想到如何播放CMSampleBufferRef的音频,目前只能静音播放。

4以上方案测试对比

* 对方案2、3做了滑动性能对比和耗电对比,测试条件分别是:

滑动:在iPhone4的聊天窗口,有30个小视频,来回做4次列表滑动;

耗电:在iPhone5s,屏幕亮度调到最大,禁止自动锁屏,开启飞行模式,聊天窗口同时播放着3个小视频,10分钟。

IM即时通讯开发之iOS版微信小视频功能相关推荐

  1. IOS版微信小视频导出方法

    1.在电脑上连接手机,打开iTools 选择 应用-应用-文件共享. 2.依次打开/Library/WechatPrivate/6e2809aac61608de6a6cc55d9570d25b/Sig ...

  2. 即时通讯开发之MobileIMSDK-Web介绍

    MobileIMSDK-Web是一套纯JS编写的Web端即时通讯框架(含服务端): 1)超轻量级.极少依赖:     2)纯JS编写.高度提炼,简单易用:     3)基于流行的socket.io网络 ...

  3. 即时通讯开发之WebRTC服务器是如何联接通话的

    通过WebRTC的端到端通信通常被人们所误解.WebRTC并不是真正意味着你不需要服务器来协商和联接通话.它只意味着,在多数情况中,你可以直接地在浏览器之间进行通信. WebRTC,名称源自网页实时通 ...

  4. 浅析即时通讯开发之Android端加密算法

    即时通讯是互联网的重要应用形态之一,安全性一直是开发者需要优先考虑的基础问题,并不是使用了加密就绝对安全了,如果加密函数使用不正确,加密数据很容易受到逆向破解攻击.如何正确地理解和使用加密技术则显的尤 ...

  5. android asmack和xmpp的关系,Android即时通讯开发之XMPP (一)初识XMPP协议和asmack

    XMPP 消息格式 Jabber/XMPP 系统使用 XML 流在不同实体之间相互传输数据.在两个实体的连接期间,XML 流将从一个实体传送到另一个实体.在实体间,有三个顶层的 XML 元素: ,和. ...

  6. 微信团队分享:极致优化,iOS版微信编译速度3倍提升的实践总结

    1.引言 岁月真是个养猪场,这几年,人胖了,微信代码也翻了. 记得 14 年转岗来微信时,用自己笔记本编译微信工程才十来分钟.如今用公司配的 17 年款 27-inch iMac 编译要接近半小时:偶 ...

  7. 微信团队分享:iOS版微信的高性能通用key-value组件技术实践

    本文来自微信开发团队guoling的技术分享. 1.前言 本文要分享的是iOS版微信内部正在推广和使用的一个高性能通用key-value 组件的技术实践过程,该组件在微信内部被命名为MMKV(以下简称 ...

  8. 微信团队分享:iOS版微信是如何防止特殊字符导致的炸群、APP崩溃的?

    本文来自微信开发团队yanyang的技术分享. 1.引言 相信大家都遇到过一段特殊文本可以让iOS设备所有app闪退的经历.前段时间大年初一,又出现某个印度语字符引起iOS11系统奔溃,所幸iOS版微 ...

  9. 微信团队原创分享:iOS版微信的内存监控系统技术实践

    为什么80%的码农都做不了架构师?>>>    本文来自微信开发团队yangyang的技术分享. 一.前言 FOOM(Foreground Out Of Memory),是指App在 ...

  10. 仿微信H5聊天系统即时通讯社交完整优化版搭建,IM聊天APP聊天交友客服,带安卓苹果端APP源码+视频教程

    H5聊天系统即时通讯社交完整优化版,IM聊天APP聊天交友客服仿微信 带安卓苹果端APP源码+教程

最新文章

  1. oracle@命令_Oracle 常用运维命令整理
  2. 3D游戏编程入门(十五)索引缓存
  3. RS232详解(续)
  4. Flume监听文件夹中的文件变化,并把文件下沉到hdfs
  5. 图像滤镜艺术---微软自拍APP滤镜实现合集DEMO
  6. LaTeX中用BibTex管理参考文献
  7. 中兴网信“智慧旅游”亮相2016国际孔子文化节
  8. eclipse显示行号和Tab、空格、回车
  9. threeJs 入门
  10. 数字电子技术之逻辑门电路
  11. 天轰穿典型三层架构留言本9级视频教程
  12. windows10 计算机打不开怎么办,win10计算器打不开怎么解决|win10打开计算器的方法...
  13. 玩转基因组浏览器之使用IGV查看基因结构信息
  14. C语言程序设计勾股数,打印出100内的所有的勾股数(用C语言实现)
  15. 如何通过KRPano全景资源下载助手来批量下载720yun的全景图
  16. ffmpeg mp3转pcm指令
  17. Vue实现拖拽穿梭框功能四种方式
  18. 成语答题小程序怎么做
  19. [HNOI2017/AHOI2017]影魔
  20. 变电站应用监控系统6大优势,你知道几个?

热门文章

  1. Hexo+Github轻松搭建个人博客
  2. 用JAVA 创建自己的 A4 打印语言
  3. 手机总是显示服务器太忙,手机总提示服务器太忙请稍后重试
  4. 高德地图——步行导航
  5. 网站建设的基本步骤有哪些
  6. prometheus的remote write功能
  7. angular 易犯错误
  8. 医学图像处理常用的看图软件介绍及使用(RadiAnt DICOM Viewer、ITK-Snap和3D Slicer)
  9. Linux_常用的磁盘列阵(RAID)
  10. MacBook关闭系统更新