iOS視頻播放總結(jié):記一篇AVPlayer

iOS已經(jīng)提供了一些視頻播放的API,封裝性很強,使用上也比較方便,但是自定制UI比較困難,自由度比較低:

  • MPMoviePlayerController
  • AVPictureInPictureController

所以我們自己用AVPlayer實現(xiàn)一些視頻播放的定制開發(fā)。AVPlayer屬于AVFoundation框架,可以播放視頻、音頻,支持本地、網(wǎng)絡視頻源,相對來說更加接近底層。

實現(xiàn)視頻播放

AVFoundtion 框架中主要使用 AVAsset 類來展示媒體信息,了解幾個常用類:
1、AVAsset:AVAsset類專門用于獲取多媒體的相關信息,包括獲取多媒體的畫面、聲音等信息,屬于一個抽象類,不能直接使用。
2、AVURLAsset:AVAsset的子類,可以根據(jù)一個URL路徑創(chuàng)建一個包含媒體信息的AVURLAsset對象。
3、AVPlayerItem:一個媒體資源管理對象,管理者視頻的一些基本信息和狀態(tài),一個AVPlayerItem對應著一個視頻資源。

在AVPlayer實現(xiàn)視頻播放的開發(fā)中,AVPlayerLayer 顯示視頻,AVPlayerItem 提供視頻信息, AVPlayer 管理和調(diào)控.

AVPlayer 本身并不能顯示視頻, 顯示視頻的是 AVPlayerLayer。 AVPlayerLayer 繼承自 CALayer。
初始化操作:
AVPlayer初始化

- (AVPlayer *)avPlayer
{
    if (_avPlayer == nil) {
        _avPlayer = [[AVPlayer alloc] init];
        // 設置默認音量
        _avPlayer.volume = 0.5;
    }
    return _avPlayer;
}
- (instancetype)init
{
    if (self = [super init]) {
        // 讓view的layerClass為AVPlayerLayer類,那么self.layer就為AVPlayerLayer的實例
        self.playerLayer = (AVPlayerLayer *)self.layer;
        self.playerLayer.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6].CGColor;
        // 初始化playerLayer的player
        self.playerLayer.player = self.avPlayer;
    }
    return self;
}

設置媒體資源

- (void)settingPlayerItem:(AVPlayerItem *)playerItem
{
    _playerItem = playerItem;
    [self.avPlayer pause];
    /*
     replaceCurrentItemWithPlayerItem: 用于切換視頻
     */
    // 設置當前playerItem
    [self.avPlayer replaceCurrentItemWithPlayerItem:playerItem];
    [self.avPlayer play];
}

視頻播放

- (void)viewDidLoad {
   [super viewDidLoad];
   
   CGFloat palyerW = [UIScreen mainScreen].bounds.size.width;
   NKAVPlayerView *playerView = [[NKAVPlayerView alloc] init];
   playerView.frame = CGRectMake(0, 0, palyerW, palyerW / 7 * 4);
   
   [self.view addSubview:playerView];
   NSString *moviePath = [[NSBundle mainBundle] pathForResource:@"movie" ofType:@"mp4"];
   [playerView settingPlayerItemWithUrl:[NSURL fileURLWithPath:moviePath]];
}

這樣視頻播放就完成,附上運行效果:


視頻播放

視頻播放的控制

  • 監(jiān)控播放狀態(tài)
// 監(jiān)控它的status也可以獲得播放狀態(tài)
[self.avPlayer.currentItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];
  • 監(jiān)控緩沖加載
//監(jiān)控緩沖加載
[self.avPlayer.currentItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];
  • 監(jiān)控播放完成
//監(jiān)控播放完成
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playFinished:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.avPlayer.currentItem];
  • 監(jiān)控時間進度
//監(jiān)控時間進度(根據(jù)API提示,如果要監(jiān)控時間進度,這個對象引用計數(shù)器要+1,retain)
__weak typeof(self) weakSelf = self;
self.timeObserver = [self.avPlayer addPeriodicTimeObserverForInterval:CMTimeMake(1, 1) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
        // 獲取 item 當前播放秒
        float currentPlayTime = (double)weakSelf.avPlayer.currentItem.currentTime.value/ weakSelf.avPlayer.currentItem.currentTime.timescale;
        [weakSelf updateVideoSlider:currentPlayTime];
}];
  • 橫豎屏切換
// 添加通知
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(orientationHandler)
                                                 name:UIDeviceOrientationDidChangeNotification
                                               object:nil
     ];
// 切換到大屏
- (void)fullScreenButtonClick {
    [self forceChangeOrientation:UIInterfaceOrientationLandscapeRight];
    self.controlView.fullScreenButton.hidden = YES;
    self.controlView.shrinkScreenButton.hidden = NO;
    self.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
}
// 切換到小屏
- (void)shrinkScreenButtonClick {
    
    [self forceChangeOrientation:UIInterfaceOrientationPortrait];
    self.controlView.fullScreenButton.hidden = NO;
    self.controlView.shrinkScreenButton.hidden = YES;
    self.frame = _shrinkRect;
}

/**
 *    強制橫屏
 *
 *    @param orientation 橫屏方向
 */
- (void)forceChangeOrientation:(UIInterfaceOrientation)orientation
{
    int val = orientation;
    if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {
        SEL selector = NSSelectorFromString(@"setOrientation:");
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDevice instanceMethodSignatureForSelector:selector]];
        [invocation setSelector:selector];
        [invocation setTarget:[UIDevice currentDevice]];
        [invocation setArgument:&val atIndex:2];
        [invocation invoke];
    }
}

AVQueuePlayer

AVQueuePlayer集成于AVPlayer,主要實現(xiàn)添加多個AVPlayerItem,然后順序播放。

總結(jié)一下播放視頻的步驟

首先,得到視頻的URL

根據(jù)URL創(chuàng)建AVPlayerItem

把AVPlayerItem 提供給 AVPlayer

AVPlayerLayer 顯示視頻。

AVPlayer 控制視頻, 播放, 暫停, 跳轉(zhuǎn) 等等。

播放過程中獲取緩沖進度,獲取播放進度。

視頻播放完成后做些什么,是暫停還是循環(huán)播放,還是獲取最后一幀圖像。

后續(xù)繼續(xù)更新一些小問題,進度條、彈出動畫等等


??附上demo,如果幫到你了請給個小星星??
GitHub

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容