.h 文件 #import <UIKit/UIKit.h> @interface TTVAVPlayerView : UIView @end .m 文件 #import "TTVAVPlayerView.h" #import <AVFoundation/AVFoundation.h> @implementation TTVAVPlayerView + (Class)layerClass { return [AVPlayerLayer class]; } @end
#import <AVFoundation/AVFoundation.h> #import<MediaPlayer/MediaPlayer.h> #import<CoreMedia/CoreMedia.h>
- (NSDictionary*)setupPlayer:(NSString*)url{ //防盜鏈headers NSMutableDictionary * headers = [NSMutableDictionary dictionary]; [headers setObject:@"http://*.itouchtv.cn" forKey:@"Referer"]; NSURL*liveURL = [NSURL URLWithString:url]; AVAsset*liveAsset = [AVURLAsset URLAssetWithURL:liveURL options:@{@"AVURLAssetHTTPHeaderFieldsKey" : headers} ]; AVPlayerItem* playerItem = [AVPlayerItem playerItemWithAsset:liveAsset]; if (iOS9_OR_LATER) { playerItem.canUseNetworkResourcesForLiveStreamingWhilePaused = true; } if (iOS10_OR_LATER) { playerItem.preferredForwardBufferDuration = kPreferredForwardBufferDuration; } //播放器 AVPlayer*player = [AVPlayer playerWithPlayerItem:playerItem]; //渲染對象 TTVAVPlayerView* avPlayerView = [[TTVAVPlayerView alloc ]init]; AVPlayerLayer* playerLayer = (AVPlayerLayer *)avPlayerView.layer; [playerLayer setPlayer:player]; return @{@"AVAsset":player,@"TTVAVPlayerView":avPlayerView}; }
static NSString* const kStatusKeyName = @"status"; static NSString* const kLoadedTimeRangesKeyName = @"loadedTimeRanges"; static NSString* const kPlaybackBufferEmptyKeyName = @"playbackBufferEmpty"; static NSString* const kPlaybackLikelyToKeepUpKeyName = @"playbackLikelyToKeepUp"; - (void)addKVO:(AVPlayerItem*)playerItem{ if (playerItem == nil) return; [playerItem addObserver:self forKeyPath:kStatusKeyName options:NSKeyValueObservingOptionNew context:nil]; [playerItem addObserver:self forKeyPath:kLoadedTimeRangesKeyName options:NSKeyValueObservingOptionNew context:nil]; [playerItem addObserver:self forKeyPath:kPlaybackBufferEmptyKeyName options:NSKeyValueObservingOptionNew context:nil]; [playerItem addObserver:self forKeyPath:kPlaybackLikelyToKeepUpKeyName options:NSKeyValueObservingOptionNew context:nil]; } - (void)delKVO:(AVPlayerItem*)playerItem{ @try { [playerItem removeObserver:self forKeyPath:kStatusKeyName context:nil]; [playerItem removeObserver:self forKeyPath:kLoadedTimeRangesKeyName context:nil]; [playerItem removeObserver:self forKeyPath:kPlaybackBufferEmptyKeyName context:nil]; [playerItem removeObserver:self forKeyPath:kPlaybackLikelyToKeepUpKeyName context:nil]; } @catch (NSException *exception) { DLog(@"屢次刪除了"); } } //監聽得到消息 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context { { AVPlayerItem *playerItem = (AVPlayerItem *)object; if ([keyPath isEqualToString:@"status"]) { if ([playerItem status] == AVPlayerStatusReadyToPlay) { self.playerStatus = TTVPlayerStatusReady; //status 點進去看 有三種狀態 CGFloat duration = playerItem.duration.value / playerItem.duration.timescale; //視頻總時間 DLog(@"準備好播放了,總時間:%.2f", duration);//還能夠得到播放的進度,這裏能夠給播放進度條賦值了 } else if ([playerItem status] == AVPlayerStatusFailed || [playerItem status] == AVPlayerStatusUnknown) { [_player pause]; } } else if ([keyPath isEqualToString:@"loadedTimeRanges"]) { //監聽播放器的下載進度 NSArray *loadedTimeRanges = [playerItem loadedTimeRanges]; CMTimeRange timeRange = [loadedTimeRanges.firstObject CMTimeRangeValue];// 獲取緩衝區域 float startSeconds = CMTimeGetSeconds(timeRange.start); float durationSeconds = CMTimeGetSeconds(timeRange.duration); NSTimeInterval timeInterval = startSeconds + durationSeconds;// 計算緩衝總進度 CMTime duration = playerItem.duration; CGFloat totalDuration = CMTimeGetSeconds(duration); CGFloat bufferdDuration = round(timeInterval); DLog(@"下載進度:%.2f 當前下載時長:%.2f 總時長:%.2f", timeInterval / totalDuration,self.bufferedTime,totalDuration); } else if ([keyPath isEqualToString:@"playbackBufferEmpty"]) { //監聽播放器在緩衝數據的狀態 DLog(@"緩衝不足暫停了"); } else if ([keyPath isEqualToString:@"playbackLikelyToKeepUp"]) { DLog(@"緩衝達到可播放程度了"); //因爲 AVPlayer 緩存不足就會自動暫停,因此緩存充足了須要手動播放,才能繼續播放 [_player play]; } } }
- (void)addNotification{ [[NSNotificationCenter defaultCenter] removeObserver:self]; [[NSNotificationCenter defaultCenter] removeObserver:self.player]; @weakify(self) [[NSNotificationCenter defaultCenter] addObserverForName:AVPlayerItemDidPlayToEndTimeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) { @strongify(self) DLog(@"播放完成"); }]; [[NSNotificationCenter defaultCenter] addObserverForName:AVPlayerItemFailedToPlayToEndTimeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) { @strongify(self) DLog(@"播放出錯"); }]; }
@property (nonatomic, strong) AVPlayer *player; - (BOOL)playing { if (self.playerItem.isPlaybackLikelyToKeepUp && self.player.rate == 1) { return true; } return false; } - (NSUInteger)currentPlayingTime { CMTime time = self.player.currentTime; return CMTimeGetSeconds(time); } - (NSUInteger)totalPlayingTime { CMTime time = self.player.currentItem.duration; Float64 seconds = CMTimeGetSeconds(time); return seconds; } - (void)seekTo:(NSUInteger)sec{ CMTime time = CMTimeMakeWithSeconds(sec, 1); [self.player seekToTime:time]; } - (void)play{ [self.player play]; } - (void)resume{ [self seekTo:self.currentPlayingTime]; [self.player play]; } - (void)pause{ [self.player pause]; } - (void)stop{ [self.player pause]; self.player.muted = true; self.player.rate = 0.0; }
原文:http://raychow.linkfun.top/2017/12/28/archives/1_ios/AVPlayer/index/ios