帶你用AVPlayer實現音頻和視頻播放


項目概述

  • 以下項目是基於AVPlayer的實際運用,實現音頻播放、橫豎屏視頻切換播放、類似抖音的豎屏全屏播放效果。
    項目地址:AVPlayerAudioVideo
    如果文章和項目對你有幫助,還請給個Star⭐️,你的Star⭐️是我持續輸出的動力,謝謝啦😘

1.音頻播放器效果:

2.豎屏和橫屏的切換效果:

3.類似抖音豎屏全屏的效果:

豎屏全屏用UICollectionView實現,只創建了三個UICollectionViewCell視圖實例。無論有多少視頻需要播放,都是復用這三個UICollectionViewCell視圖實例,有效控制內存大小,避免內存加載過大、內存爆滿的情況。
UICollectionViewCell復用時有一個難點,就是記錄視頻當前已播放的位置,一開始用CMTime來保存發現不行,然后用CMTimeValue和CMTimeScale分別記錄也是存在各種問題,后來使用AVPlayerItem來保存已播放位置才徹底解決。

遇到的問題

  • 播放時,揚聲器沒有聲音,插上耳機才有聲音。
    原因是app揚聲器默認跟隨系統聲音模式,而手機調了靜音模式,因此揚聲器跟隨靜音模式,沒有聲音。
    解決方式:設置Category,讓揚聲器不跟隨系統聲音模式。
    //必須設置,否則揚聲器默認跟隨系統聲音模式
    //AVAudioSessionCategoryPlayAndRecord模式能播放能錄音,該模式下聲音默認出口是聽筒(戴耳機才有聲音),切換到揚聲器通過以下方式
    AVAudioSession *session = [AVAudioSession sharedInstance];
    [session setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:nil];
  • 當反復快速移動滑塊時,滑塊會出現跳躍的現象。
    這是由於移動滑塊時,會調用seekToTime:,該方法用於搜索並播放指定視頻幀,執行時需要一點時間,不會立馬搜索並播放到指定視頻幀,此時addPeriodicTimeObserverForInterval:queue:usingBlock:回調會設置滑塊的位置,出現手指已讓滑塊移動到某一位置,突然有一瞬間滑塊回到之前的位置,然后立馬又回到手指停留的位置。
    解決方式:用seekToTime:toleranceBefore:toleranceAfter:completionHandler:代替seekToTime:,搜索並播放到指定視頻幀會有completionHandler的回調,獲得該回調后再設置滑塊的位置。具體處理細節詳見項目。

什么是AVPlayer

  • AVPlayer存在於AVFoundation框架中,它是一個視頻播放器,用來播放視頻,但也可以用來播放音樂,播放音樂時不需要實現界面。換句話說,只要掌握了視頻播放,音頻播放自然就掌握了。
  • AVPlayerItem:和媒體資源存在對應關系,管理媒體資源的信息和狀態。它的初始化需要URL或AVAsset。
  • AVPlayer:播放器,控制資源的播放和暫停,AVPlayerItem是它的屬性,它的初始化需要URL或AVPlayerItem。
+ (instancetype)playerWithURL:(NSURL *)URL;
+ (instancetype)playerWithPlayerItem:(nullable AVPlayerItem *)item;
  • AVPlayerLayer:播放器圖層,用於展示視頻內容,AVPlayer是它的屬性,它的初始化需要AVPlayer。如果是播放音頻,則不需要創建AVPlayerLayer。
+ (AVPlayerLayer *)playerLayerWithPlayer:(nullable AVPlayer *)player
  • AVPlayerItem、AVPlayer、AVPlayerLayer三者關系,做個類比:
    AVPlayerItem是光盤,AVPlayer是dvd影碟機,AVPlayerLayer是電視機屏幕。

視頻播放功能實現

1.通過網絡鏈接播放視頻資源

//url有中文時需要URL編碼
NSURL *url = [NSURL URLWithString:[self.str stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]];
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:url];
AVPlayer *player = [AVPlayer playerWithPlayerItem:playerItem];
AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];
    
playerLayer.frame = CGRectMake(0, 50, self.view.frame.size.width, 200);
[self.view.layer addSublayer:playerLayer];

2.常用操作

  • 播放和暫停
[player play];
[player pause];
  • 替換播放資源
[player replaceCurrentItemWithPlayerItem:videoItem];

3.監聽播放進度

  • 使用addPeriodicTimeObserverForInterval:queue:usingBlock:監聽播放器的進度,常用於指示播放進度,獲取播放時長等信息。
    1)Interval參數表示回調的間隔時間,block是每到一個間隔時間執行一次。
    例如Interval傳CMTimeMake(1,10),1表示當前有1幀,10表示每秒10幀,1/10=0.1,即player在播放中時每0.1秒執行一次block,包括開始播放、暫停播放也會回調。
    2)方法返回一個觀察者對象,當不再播放時,要移除該觀察者。
    添加觀察者
    self.timeObserve = [self.player addPeriodicTimeObserverForInterval:CMTimeMake(1, 10) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
        float current = CMTimeGetSeconds(time);
        float total = CMTimeGetSeconds(weakSelf.player.currentItem.duration);
        weakSelf.playTime = [NSString stringWithFormat:@"%.f",current];
        weakSelf.playDuration = [NSString stringWithFormat:@"%.2f",total];
        if (weakSelf.slider.isTracking == NO) {
            weakSelf.slider.value = current / total;
        }
    }];

移除觀察者

    if (self.timeObserve) {
        [self.player removeTimeObserver:self.timeObserve];
    }

4.移動滑塊播放指定時刻的視頻幀

  • 使用seekToTime:seekToTime:completionHandler:seekToTime:toleranceBefore:toleranceAfter:completionHandler:播放指定時刻的視頻內容。
    精確搜索某一時刻的視頻幀可能會導致額外的解碼延遲,seekToTime:默認不是精確搜索,而是有一個小范圍的誤差。
    seekToTime:toleranceBefore:toleranceAfter:completionHandler:的搜索的范圍是[time-toleranceBefore, time+toleranceAfter],當toleranceBefore和toleranceAfter設置為kCMTimePositiveInfinity時,執行效果等同於seekToTime:completionHandler:
    [self.player seekToTime:goalTime toleranceBefore:kCMTimePositiveInfinity toleranceAfter:kCMTimePositiveInfinity completionHandler:^(BOOL finished) {
    }];


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM