- 效果圖:
效果圖.png
問題:利用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>