- 效果图:
问题:利用AVPlayer做网络视频播放时,若此时网络出现问题,AVPlayer会自动将其暂停,而若几分钟网络好时它并不会自动播放,你必须手动调用AVPlayer的播放方法play才会继续播放。
解决:所以现在的问题,就是,何时进行AVPlayer的手动让其播放。我们可以AVPlayer提供给我们的属性currentItem的属性值loadedTimeRanges进行监听 视频 缓存大小,当视频缓存大小 > 当前播放时长 ,就 调用AVPlayer的play方法进行播放.
-
实现代码如下:
- 解析:点击控制器view进行播放网络视频,当开始播放后,你可以模拟 关掉网络,然后会发现 视频播放到缓存时间后,会自动暂停,当你网络打开,AVPlayer默认会继续缓存时,当缓存值 > 当前播放时间,又开始继续播放了。
#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>
@interface ViewController ()
/** 播放器 */
@property (nonatomic, strong) AVPlayer *player;
@property (nonatomic, strong) NSString *status_playType; // 正在播放, 等待播放
@property (nonatomic, strong) UILabel *currentTimeLable; // 显示 当前播放时长
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.currentTimeLable = [[UILabel alloc ] initWithFrame:CGRectMake(0, 240, self.view.frame.size.width, 400)];
self.currentTimeLable.backgroundColor = [UIColor greenColor];
[self.view addSubview:self.currentTimeLable];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"status"]) {
AVPlayerItemStatus status = [[change objectForKey:NSKeyValueChangeNewKey] integerValue];
// NSLog(@"%d", status);
if (AVPlayerItemStatusReadyToPlay == status) {
} else {
}
}else if ([keyPath isEqualToString:@"loadedTimeRanges"]){
NSTimeInterval timeInterval = [self availableDuration];// 计算缓冲进度
NSLog(@"已缓存时长 : %f",timeInterval);
self.currentTimeLable.text = [NSString stringWithFormat:@"当前播放时长: %f \\n 已缓存: %f", self.getCurrentPlayingTime, timeInterval];
if (timeInterval > self.getCurrentPlayingTime+5){ // 缓存 大于 播放 当前时长+5
if ([self.status_playType isEqual: @"等待播放"]) { // 接着之前 播放时长 继续播放
[self.player play];
self.status_playType = @"正在播放";
}
}else{
self.status_playType = @"等待播放"; // 出现问题,等待播放
NSLog(@"等待播放,网络出现问题");
}
}
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[self.player play];
self.status_playType = @"正在播放";
[[self.player.currentItem valueForKey:@"_playerItem"] addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
[self.player.currentItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];// 监听loadedTimeRanges属性
}
#pragma mark - 懒加载代码
- (AVPlayer *)player
{
if (_player == nil) {
// 1.创建URL
NSURL *url = [NSURL URLWithString:@"http://v1.mukewang.com/19954d8f-e2c2-4c0a-b8c1-a4c826b5ca8b/L.mp4"];
// NSURL *url = [[NSBundle mainBundle] URLForResource:@"01-知识回顾.mp4" withExtension:nil];
// 2.创建AVPlayer对象
AVPlayerItem *_playerItem = [[AVPlayerItem alloc] initWithURL:url];
_player = [[AVPlayer alloc] initWithPlayerItem:_playerItem];
// 3.创建播放layer
AVPlayerLayer *layer = [AVPlayerLayer playerLayerWithPlayer:_player];
layer.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.width * 9 / 16);
[self.view.layer addSublayer:layer];
}
return _player;
}
/**
* 返回 当前 视频 播放时长
*/
- (double)getCurrentPlayingTime{
return self.player.currentTime.value/self.player.currentTime.timescale;
}
/**
* 返回 当前 视频 缓存时长
*/
- (NSTimeInterval)availableDuration{
NSArray *loadedTimeRanges = [[self.player currentItem] loadedTimeRanges];
CMTimeRange timeRange = [loadedTimeRanges.firstObject CMTimeRangeValue];// 获取缓冲区域
float startSeconds = CMTimeGetSeconds(timeRange.start);
float durationSeconds = CMTimeGetSeconds(timeRange.duration);
NSTimeInterval result = startSeconds + durationSeconds;// 计算缓冲总进度
return result;
}
@end
- HTTPS处理,相关提示错误:
App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.**
- 注意:HTTPS处理,在Info.plist文件中加入下面代码
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>