录制完视频后,我们想在录制视频的预览层上无限循环播放我们的小视频,是不是很炫酷,这时候我们就有三中选择了:
1.MPMoviePlayerController
2.AVPlayer
3.AVAssetReader+AVAssetReaderTrackOutput

但是我们这个预览层是自定义的喔,所以MPMoviePlayerController只能马上给筛选掉了,所以用,那么我们就要用到 AVPlayer 了,虽然上 AVPlayer 最多只能创建16个,性能上不及用 AVAssetReader+AVAssetReaderTrackOutput 方法好,但是对于这么个视频小播放也是足够的了。(PS:接下来博主会写一篇关于如何用AVAssetReader+AVAssetReaderTrackOutput来实现播放视频)

AVPlayer

AVPlayer本身并不能显示视频,而且它也不像MPMoviePlayerController有一个view属性。如果AVPlayer要显示必须创建一个播放器层AVPlayerLayer用于展示,播放器层继承于CALayer,
有了AVPlayerLayer之添加到控制器视图的layer中即可。要使用AVPlayer首先了解一下几个常用的类: AVAsset:主要用于获取多媒体信息,是一个抽象类,不能直接使用。
AVURLAsset:AVAsset的子类,可以根据一个URL路径创建一个包含媒体信息的AVURLAsset对象。
AVPlayerItem:一个媒体资源管理对象,管理者视频的一些基本信息和状态,一个AVPlayerItem对应着一个视频资源。

我们先来熟悉一下 AVPlayer 的这些类
那么运用AVPlayer播放视频的步骤如下:
1.创建 AVPlayerItem ,用来实例化AVPlayer并监控视频的状态

- (AVPlayer *)player
{
if (!_player ) {
AVPlayerItem *playerItem = [self getPlayItem];
_player = [[AVPlayer alloc]initWithPlayerItem:playerItem];
// 可以利用 AVPlayerItem 对这个视频的状态进行监控 }
return _player;
} - (AVPlayerItem *)getPlayItem
{
NSString *cachePath=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *savePath=[cachePath stringByAppendingPathComponent:MOVIEPATH];
NSURL *saveUrl=[NSURL fileURLWithPath:savePath]; // 通过文件 URL 来实例化 AVPlayerItem
AVPlayerItem *playerItem = [[AVPlayerItem alloc] initWithURL:saveUrl]; return playerItem;
}

2.通过AVPlayer 创建预览层(AVPlayerLayer)并添加到可视的图层上播放

 AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
playerLayer.frame = _viewContrain.bounds;
playerLayer.videoGravity=AVLayerVideoGravityResizeAspectFill;//视频填充模式
[_viewContrain.layer addSublayer:playerLayer];
[self.player play];

3.通过 KVO 来监听视频的属性,查看是否播放完成,播放长度为多小,缓冲了多少等等

/** * 给播放器添加进度更新 */
-(void)addProgressObserver{
AVPlayerItem *playerItem=self.player.currentItem;
UIProgressView *progress=self.progress; //这里设置每秒执行一次
[self.player addPeriodicTimeObserverForInterval:CMTimeMake(1.0, 1.0) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
float current=CMTimeGetSeconds(time);
float total=CMTimeGetSeconds([playerItem duration]);
NSLog(@"当前已经播放%.2fs.",current);
if (current) {
[progress setProgress:(current/total) animated:YES];
}
}];
} #pragma mark - KVO
/** * 给AVPlayerItem添加监控 *
* @param playerItem AVPlayerItem对象 */
-(void)addObserverToPlayerItem:(AVPlayerItem *)playerItem{
//监控状态属性,注意AVPlayer也有一个status属性,通过监控它的status也可以获得播放状态
[playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
//监控网络加载情况属性
[playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];
} -(void)removeObserverFromPlayerItem:(AVPlayerItem *)playerItem{
[playerItem removeObserver:self forKeyPath:@"status"];
[playerItem removeObserver:self forKeyPath:@"loadedTimeRanges"];
} /** * 通过KVO监控播放器状态 *
* @param keyPath 监控属性
* @param object 监视器
* @param change 状态改变
* @param context 上下文 */
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
AVPlayerItem *playerItem=object;
if ([keyPath isEqualToString:@"status"]) {
AVPlayerStatus status= [[change objectForKey:@"new"] intValue];
if(status==AVPlayerStatusReadyToPlay){
NSLog(@"正在播放...,视频总长度:%.2f",CMTimeGetSeconds(playerItem.duration));
}
}
else if([keyPath isEqualToString:@"loadedTimeRanges"])
{
NSArray *array=playerItem.loadedTimeRanges;
CMTimeRange timeRange = [array.firstObject CMTimeRangeValue];//本次缓冲时间范围
float startSeconds = CMTimeGetSeconds(timeRange.start);
float durationSeconds = CMTimeGetSeconds(timeRange.duration);
NSTimeInterval totalBuffer = startSeconds + durationSeconds;//缓冲总长度
NSLog(@"共缓冲:%.2f",totalBuffer);
}
}

到此,我们就把 AVPlayer 视频播放的方法创建完毕了。

那么我们在视频录制完成的时候调用播放视频的方法了

- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error
{
NSLog(@"---- 录制结束 ----");
}
- (void)completeHandle
{
// 完成后不断播放
[_captureVideoPreviewLayer removeFromSuperlayer]; // 播放视频
// 1.创建播放层
// 这里为什么要调用延迟1.0秒呢,我们说过用 AVCaptureMovieFileOutput 来录制视频,是边录边写的,即使是录制完成了,真实的是视频还在写,大概时间是延迟1.2秒左右。
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// 在此方法调用创建 AVPlayer 播放视频的第二部
.通过AVPlayer 创建预览层(AVPlayerLayer)并添加到可视的图层上播放
[self addNotification];
});
}
添加视频播放完后的监控来循环播放视频
 /**
* 添加播放器通知
*/
-(void)addNotification{
//给AVPlayerItem添加播放完成通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackFinished:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.player.currentItem];
} -(void)removeNotification{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
/**
* 播放完成通知
*
* @param notification 通知对象
*/
-(void)playbackFinished:(NSNotification *)notification{
NSLog(@"视频播放完成."); // 播放完成后重复播放
// 跳到最新的时间点开始播放
[_player seekToTime:CMTimeMake(, )];
[_player play];
}

iOS - 视频循环播放的更多相关文章

  1. H5 多个视频 循环播放效果

    跟轮播效果差不多 页面HTML结构 <video id="myvideo" width="100%" height="auto" co ...

  2. 在wpf中如何让MediaElement的视频循环播放

    原文:在wpf中如何让MediaElement的视频循环播放 MediaElement原始的播放是只播放一遍:如何设置让MediaElement播放 的视频或者音频循环播放,解决如下: 修改Media ...

  3. 深入理解MVC C#+HtmlAgilityPack+Dapper走一波爬虫 StackExchange.Redis 二次封装 C# WPF 用MediaElement控件实现视频循环播放 net 异步与同步

    深入理解MVC   MVC无人不知,可很多程序员对MVC的概念的理解似乎有误,换言之他们一直在错用MVC,尽管即使如此软件也能被写出来,然而软件内部代码的组织方式却是不科学的,这会影响到软件的可维护性 ...

  4. ios 视频音乐播放

    IOS开发小技巧(视频和音乐播放).IOS视频播放代码(添加MediaPlayer.framework和#import) -(void)playMovie:(NSString *)fileName{ ...

  5. iOS scrollview循环播放加缩放

    前些日子一直在研究3d的框架没有时间写博客,不过最后需求改了,也没研究出个啥.这段时间出了新的需求,需要循环播放图片,并且滑动的时候中间的图片有缩放的效果.刚开始想在网上搜索,不过并没有找到合适的de ...

  6. C# WPF 用MediaElement控件实现视频循环播放

    在WPF里用MediaElement控件,实现一个循环播放单一视频的程序,同时可以控制视频的播放.暂停.停止. 一种方式,使用MediaElement.MediaEnded事件,在视频播放结束后,自动 ...

  7. video标签实现多个视频循环播放

    <head> <!-- If you'd like to support IE8 (for Video.js versions prior to v7) --> </he ...

  8. HTML5实现两个视频循环播放!

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. html5 css3 背景视频循环播放代码

    <div style ="position: absolute; z-index: -1; top: 0px; left: 0px; bottom: 0px; right: 0px; ...

随机推荐

  1. linux文件压缩与打包

    在linux中常见的压缩命令 首先,在linux中压缩文件的扩展名大多是 *.gz gzip程序压缩的文件 *.bz2 bzip2程序压缩的文件 *.tar tar程序打包的数据,并没有压缩过 *.t ...

  2. GPS 坐标距离计算

    CREATE FUNCTION [dbo].[Rad]( @d float ) RETURNS float BEGIN return @d * PI()/ 180.00; End CREATE FUN ...

  3. MSDE简介

    MSDE的全程是Microsoft SQL Server Desktop Engine,它是一个基于 SQL Server 核心技术构建的数据引擎.MSDE 2000 支持单处理器和双处理器,是面向小 ...

  4. Best Time to Buy and Sell Stock II

    Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...

  5. codeforces gym-101078

    题目链接: http://codeforces.com/gym/101078 A: #include <iostream> #include <cstdio> #include ...

  6. 两道相似KMP题

    1.POJ 3450 Coporate Identity 这两题的解法都是枚举子串,然后匹配,像这种题目以后可以不用KMP来做,直接字符串自带的strstr函数搞定,如果字符串未出现,该函数返回NUL ...

  7. ABP入门系列(6)——展现层实现增删改查

    这一章节将通过完善Controller.View.ViewModel,来实现展现层的增删改查.最终实现效果如下图: 一.定义Controller ABP对ASP.NET MVC Controllers ...

  8. http协议详解<一>

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://7826443.blog.51cto.com/7816443/1729227 写在 ...

  9. 工厂模式(Factory Patter)

    1.工厂模式简介 工厂模式属于创建型模式,是专门用来创建对象的模式,抽象了实例化的过程.工厂模式分为 : 工厂方法模式.抽象工厂模式. 在学习工厂方法模式.抽象工厂之前,首先先要了解一下简单工厂模式, ...

  10. [资料]PHP Yaf

    QConShanghai2013-惠新宸-微博LAMP性能优化之路 Yaf-一个PHP扩展实现的PHP框架 Baidu Yaf