日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

iOS AVPlayer的那些坑

發布時間:2023/12/31 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 iOS AVPlayer的那些坑 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

這次主要是總結和記錄下視頻播放遇到的坑,視頻播放采用的是AVPlayer這個控件,語法大致如下:

NSURL * url = [NSURL fileURLWithPath:@"視頻地址"];AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:url];self.player = [AVPlayer playerWithPlayerItem:playerItem];[playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];self.player.actionAtItemEnd = AVPlayerActionAtItemEndNone;self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];self.playerLayer.videoGravity = AVLayerVideoGravityResizeAspect;self.playerLayer.frame = self.view.bounds;[self.view.layer addSublayer:self.playerLayer]; 復制代碼

一般說來,這里要監聽AVPlayerItem的status屬性:

**AVPlayerItem的三種狀態*AVPlayerItemStatusUnknown,*AVPlayerItemStatusReadyToPlay,*AVPlayerItemStatusFailed*/ 復制代碼

如果是AVPlayerStatusFailed說明視頻加載失敗,這時可以通過self.player.error.description屬性來找出具體的原因。 問題一:當status變為AVPlayerStatusReadyToPlay后,我們調用play方法真的就能保證視頻正常播放嗎?

眾所周知,AVPlayer支持的視頻、音頻格式非常廣泛,拋開那些無法正常編解碼的情況,在某些情況下其可能就是無法正常播放。AVPlayer在進行播放時,會預先解碼一些內容,而此時如果我們的App使用CPU過多,I/O讀寫過多時,有可能導致視頻播放聲/畫不同步,這點尤其在iPhone4上面表現更為明顯,用戶反饋iOS9.3.2的系統上也很明顯。而如果是發生在AVPlayer初始化解碼視頻的時候,有可能導致視頻直接無法播放,這時,我們再調用play或者seekToTime:方法都無法正常播放。建議不要在CPU或者I/O很頻繁的情況下使用AVPlayer,例如剛登錄App加載各種數據的情況下,可以等App預熱以后再使用。

問題二:當rate屬性的值大于0后,真的就在播放視頻了嗎?

當然不是。當發生上面所講的情況時,我打印了當前的rate情況,是大于0的,但是頁面上顯示的情況卻還是什么也沒有。有時候我們如果想要在視頻一播放的時候去做一些事情,例如設置一下播放器的背景色,如果我們僅僅是監聽這個rate可能無法100%保證有效,而如果我們真的要監聽這種情況的話,有一個取巧的方法:

id _timerObserver = [self.player addBoundaryTimeObserverForTimes:@[[NSValue valueWithCMTime:CMTimeMake(1, 30)]] queue:dispatch_get_main_queue()usingBlock:^{//do something}]; 復制代碼

另外如果不需要監聽播放進度的時候可以調下面的方法:

[self.player removeTimeObserver:_timerObserver]; 復制代碼

問題三:AVPlayer前后臺播放

當我們切換到后臺后,這時AVPlayer通常會自動暫停,當然如果設置了后臺播放音頻的話,是可以在后臺繼續播放聲音的,正如蘋果自己的WWDC這個App一樣。這個功能在我的另一篇文章iOS AVPlayer之后臺連續播放視頻中解決了這個問題。

問題四:音頻通道的搶占引起的無法播放視頻問題

這個問題下周我會另開一篇博客專門講述,今兒就此略過。

問題五:其它App播放聲音打斷

如果用戶當時在后臺聽音樂,如QQ音樂,或者喜馬拉雅這些App,這個時候播放視頻后,其會被我們打斷,當我們不再播放視頻的時候,自然需要繼續這些后臺聲音的播放。

首先,我們需要先向設備注冊激活聲音打斷AudioSessionSetActive(YES);,當然我們也可以通過 [AVAudioSession sharedInstance].otherAudioPlaying;這個方法來判斷還有沒有其它業務的聲音在播放。 當我們播放完視頻后,需要恢復其它業務或App的聲音,這時我們可以在退到后臺的事件中調用如下方法:

- (void)applicationDidEnterBackground:(UIApplication *)application {NSError *error =nil;AVAudioSession *session = [AVAudioSession sharedInstance];// [session setCategory:AVAudioSessionCategoryPlayback error:nil];BOOL isSuccess = [session setActive:NO withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:&error];if (!isSuccess) {NSLog(@"__%@",error);}else{NSLog(@"成功了");}} 復制代碼

問題六:在用戶插入和拔出耳機時,導致視頻暫停,解決方法如下

//耳機插入和拔掉通知[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioRouteChangeListenerCallback:) name:AVAudioSessionRouteChangeNotification object:[AVAudioSession sharedInstance]];//耳機插入、拔出事件 - (void)audioRouteChangeListenerCallback:(NSNotification*)notification {NSDictionary *interuptionDict = notification.userInfo;NSInteger routeChangeReason = [[interuptionDict valueForKey:AVAudioSessionRouteChangeReasonKey] integerValue];switch (routeChangeReason) {case AVAudioSessionRouteChangeReasonNewDeviceAvailable:break;case AVAudioSessionRouteChangeReasonOldDeviceUnavailable:{//判斷為耳機接口AVAudioSessionRouteDescription *previousRoute =interuptionDict[AVAudioSessionRouteChangePreviousRouteKey];AVAudioSessionPortDescription *previousOutput =previousRoute.outputs[0];NSString *portType =previousOutput.portType;if ([portType isEqualToString:AVAudioSessionPortHeadphones]) {// 拔掉耳機繼續播放if (self.playing) {[self.player play];}}}break;case AVAudioSessionRouteChangeReasonCategoryChange:// called at start - also when other audio wants to playbreak;} }復制代碼

問題七:打電話等中斷事件

//中斷的通知[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleInterruption:) name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]];//中斷事件 - (void)handleInterruption:(NSNotification *)notification{NSDictionary *info = notification.userInfo;//一個中斷狀態類型AVAudioSessionInterruptionType type =[info[AVAudioSessionInterruptionTypeKey] integerValue];//判斷開始中斷還是中斷已經結束if (type == AVAudioSessionInterruptionTypeBegan) {//停止播放[self.player pause];}else {//如果中斷結束會附帶一個KEY值,表明是否應該恢復音頻AVAudioSessionInterruptionOptions options =[info[AVAudioSessionInterruptionOptionKey] integerValue];if (options == AVAudioSessionInterruptionOptionShouldResume) {//恢復播放[self.player play];}}}復制代碼

小提示:如果不起作用,請檢查退到后臺事件中有什么其它的操作沒。因為電話來時,會調用退到后臺的事件。

問題七:內存泄露問題 當我們釋放一個正在播放的視頻時,需要先調用pause方法,如果由于某些原因,例如切前后臺時,導致又調用了play方法,那么有可能會hold不住內存空間而導致內存泄漏。其實更靠譜的方法是,還要移除player加載的資源。

總的來說,AVPlayer能滿足一般的需求,雖然坑不少。最后,再來推銷一下我自己封裝的LYAVPlayer,簡單方便,支持cocoa pods,只需幾行代碼即可完成播放:

LYAVPlayerView *playerView =[LYAVPlayerView alloc]init]; playerView.frame =CGRectMake(0, 64, ScreenWidth,200);playerView.delegate =self;//設置代理[self.view addSubview:playerView];[playerView setURL:[NSURL URLWithString:VideoURL]];//設置播放的URL[playerView play];//開始播放 復制代碼

工程中pod 'LYAVPlayer','~> 1.0.1'即可使用。有什么問題請Issues我。

總結

以上是生活随笔為你收集整理的iOS AVPlayer的那些坑的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。