那些年,追逐过的小视频
2017-01-17 00:00
183 查看
最近公司快不行了,又有空闲的时间了😳,对之前做的一些功能做一些总结,微信小视频,曾经热火朝天的功能,许多社交类app都想着模仿。下面就来解析下小视频功能特点。
1.小视频没有声音
2.小视频在cell中无限循环播放
3.性能要求,滑动需要顺畅(线程设计)。
最早接触iOS,我只知道播放视频通常有两种方式,一种是 AVPlayer,另一种是MPMoviePlayerController 。现在 ios9之后苹果已推荐播放视频使用 AVPlayer。
下面介绍下简单的说下 AVPlayer 视频播放器使用时的相关知识,具体的参见官方文档
AVPlayer功能很强大,音视频都可以播放,但像小视频功能我们只需要他的视频功能, 音频功能不需要,如果小视频功能用AVPlayer来实现,系统开销可能就有点浪费了,因为AVPlayer实现了Video+Audio ,而且AVPlayer的音频对AudioSession也有影响,如果app其他地方有使用到声音的,需要注意它的使用了。
后来追求性能,发现了AVAssetReader类
AVAssetReader用于从AVAsset资源中读取媒体样本,可以读取出视频和音频
小视频功能可以通过AVPlayer和AVAssetReader 两种途径实现,
我写了个简单的demo,但里面还是有很多学问的。下面简述下demo中的3中实现方式:
实现方式1:用过AVPlayer的 可能都遇到过这么一个现象:黑屏。黑屏的原因是app最多支持16个AVPlayerLayer同时存在,等到17个的时候就会出现黑屏,解决这个问题需要及时释放AVPlayer相关资源。 如果一屏需要展示的播放个数大于16,那么AVPlayer就不适合用来实现小视频,当然实际过程中1屏幕就最多6,7个人视频同时播放了。
实现方式2:利用AVAssetReader 中的获取到的CGImageRef
将每一帧都放到layer.contents中展示
实现方式3:实际开发中 gif图 你可以是服务器下载下来的,也可以是通过AVAssetReader 获取到所需要的UIImages,制作成gif,然后保存展示。
以上3中方式,1的性能较差。2,3各有优点。
这3种方式都有一个最大的特点,cell滑动过程中不做视频的加载,这样做为了滑动更流畅,结束的时候再加载当前屏幕中的cell视频。对于gif和customPlayerLayer如果想要修改成滑动时播放,需要修改timer的runloop的model。
demo
总结:demo中cell元素比较简单,但也能比较不同方式的性能差异,视频播放其实并不难实现,主要是注意性能,利用线程的特性,处理好视频播放。视频播放肯定还有其他实现方式。
1.小视频没有声音
2.小视频在cell中无限循环播放
3.性能要求,滑动需要顺畅(线程设计)。
最早接触iOS,我只知道播放视频通常有两种方式,一种是 AVPlayer,另一种是MPMoviePlayerController 。现在 ios9之后苹果已推荐播放视频使用 AVPlayer。
下面介绍下简单的说下 AVPlayer 视频播放器使用时的相关知识,具体的参见官方文档
//创建一个AVPlayer播放类 @property(nonatomic,strong) AVPlayer *player; //AVPlayerItem(多媒体资源) @property(nonatomic,strong) AVPlayerItem *playerItem; //AVAsset(音视频当中单个资源,例如声道,影片) @property (nonatomic, strong) AVAsset
AVPlayer功能很强大,音视频都可以播放,但像小视频功能我们只需要他的视频功能, 音频功能不需要,如果小视频功能用AVPlayer来实现,系统开销可能就有点浪费了,因为AVPlayer实现了Video+Audio ,而且AVPlayer的音频对AudioSession也有影响,如果app其他地方有使用到声音的,需要注意它的使用了。
后来追求性能,发现了AVAssetReader类
AVAssetReader用于从AVAsset资源中读取媒体样本,可以读取出视频和音频
//从媒体中得到声音轨道 AVMediaTypeVideo 视频 AVAssetTrack *track = [[asset tracksWithMediaType:AVMediaTypeAudio] firstObject];
AVAssetReaderOutput输出资源并通过copyNextSampleBuffer方法将我们需要的数据给弄一份出来。注意读取的过程是分帧(音频是分块)读取,并不是一次性将将所有数据读取去完毕。结束时,AVAssetReader的
status属性 会变成
AVAssetReaderStatusCompleted,通过此属性来判断是否读取完毕。
//从媒体中得到视频轨道 AVMediaTypeAudio 音频 AVAssetTrack *track = [[self.asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; //读取配置 NSDictionary *setting = @{ (id)kCVPixelBufferPixelFormatTypeKey:@(kCVPixelFormatType_32BGRA), (id)kCVPixelBufferWidthKey:@(self.size.width), (id)kCVPixelBufferHeightKey:@(self.size.height), }; //读取输出,在相应的轨道和输出对应格式的数据 self.assetReaderOutput = [[AVAssetReaderTrackOutput alloc] initWithTrack:track outputSettings:setting]; //赋给读取并开启读取 if ([self.assetReader canAddOutput:self.assetReaderOutput]) { [self.assetReader addOutput:self.assetReaderOutput]; } [self.assetReader startReading];//开始读取
小视频功能可以通过AVPlayer和AVAssetReader 两种途径实现,
我写了个简单的demo,但里面还是有很多学问的。下面简述下demo中的3中实现方式:
实现方式1:用过AVPlayer的 可能都遇到过这么一个现象:黑屏。黑屏的原因是app最多支持16个AVPlayerLayer同时存在,等到17个的时候就会出现黑屏,解决这个问题需要及时释放AVPlayer相关资源。 如果一屏需要展示的播放个数大于16,那么AVPlayer就不适合用来实现小视频,当然实际过程中1屏幕就最多6,7个人视频同时播放了。
实现方式2:利用AVAssetReader 中的获取到的CGImageRef
将每一帧都放到layer.contents中展示
self.videoImageView.layer.contents = (__bridge id)(imageRef);
实现方式3:实际开发中 gif图 你可以是服务器下载下来的,也可以是通过AVAssetReader 获取到所需要的UIImages,制作成gif,然后保存展示。
以上3中方式,1的性能较差。2,3各有优点。
这3种方式都有一个最大的特点,cell滑动过程中不做视频的加载,这样做为了滑动更流畅,结束的时候再加载当前屏幕中的cell视频。对于gif和customPlayerLayer如果想要修改成滑动时播放,需要修改timer的runloop的model。
//cell 不在可视区域内 可以暂停播放 释放资源 - (BOOL)currentCellIsNotShowedInScreen { UITableView *table; for (UIView* next = [self superview]; next; next = next.superview) { UIResponder* nextResponder = [next nextResponder]; if ([nextResponder isKindOfClass:[UITableView class]]) { table = (UITableView *)nextResponder; break; } } if (table) { CGRect cellR = [table rectForRowAtIndexPath:self.currentIndexPath]; if ((table.contentOffset.y + table.frame.size.height) < CGRectGetMinY(cellR) || table.contentOffset.y > CGRectGetMaxY(cellR)) { return true; } } return false; }
demo
总结:demo中cell元素比较简单,但也能比较不同方式的性能差异,视频播放其实并不难实现,主要是注意性能,利用线程的特性,处理好视频播放。视频播放肯定还有其他实现方式。
相关文章推荐
- 第二十三节: EF性能篇(三)之基于开源组件 Z.EntityFrameWork.Plus.EF6解决EF性能问题 第四节:一些指令总结 定时调度系列之Quartz.Net详解 第十七节:易混淆的概念(静态和非静态、拆箱和装箱) 那些年我们一起追逐的多线程(Thread、ThreadPool、委托异步调用、Task/TaskFactory、Parallerl、async和await)
- 谈谈嵌入式开发的那些年【附录:独家原创视频教程】
- 那些年写过的视频解析
- 那些年我们一起追逐过的安全工具
- 【我的学生】李怀宾-OCM之路有感 《那些年我们一起追逐过的OCM》系列有感
- 那些年从项目中走过——从完结的基于视频的车辆识别系统写起
- 【我的学生】祝志伟-我眼中的OCM 《那些年我们一起追逐过的OCM》系列有感
- dataguru北京线下沙龙-第一部 《那些年我们一起追逐过的沙龙》
- 那些年我们一起追逐的多线程(Thread、ThreadPool、委托异步调用、Task/TaskFactory、Parallerl、async和await)
- 世界杯与视频压缩(1)
- fedora11下的音频视频解码
- 实时视频在网页直播--windows下编译librtmp、rtmpdump
- 腾讯QQ群视频功能“视频秀”即将上线
- Android开发视频教学第一季(17-34集)视频源码下载
- 人人都喊大数据的时代,不看这些视频你就out啦!
- 我的视频网站开通,第一个 ArcGIS文本文件,excel文件生成点操作发布,希望大家支持
- 视频会议的行业应用
- android 视频录制 混淆打包 之native层 异常的解决
- vr四棱锥视频文件通过opengl在手机端播放全景视频
- 玩转Android之在线视频播放控件Vitamio的使用