這篇文章給大家分享的是有關(guān)iOS視頻播放方式有哪些的內(nèi)容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
創(chuàng)新互聯(lián)公司專業(yè)為企業(yè)提供余姚網(wǎng)站建設(shè)、余姚做網(wǎng)站、余姚網(wǎng)站設(shè)計、余姚網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計與制作、余姚企業(yè)網(wǎng)站模板建站服務(wù),10年余姚做網(wǎng)站經(jīng)驗,不只是建網(wǎng)站,更提供有價值的思路和整體網(wǎng)絡(luò)服務(wù)。
iOS的視頻播放方式有幾種?其實要是只是簡單的想播放一段視頻并且對UI沒什么要求的話的確比較簡單,很容易搞定,但我相信這種情況除了你的Demo一般是不會出現(xiàn)的,對播放UI的定義以及可能有各種不同的需求對應(yīng)著你是不能隨便寫個播放器就沒事了的。
最原始的播放
要不是剛接觸iOS開發(fā)的同學(xué)應(yīng)該是知道MediaPlayer這個框架的,要是想簡單的使用它播放視頻,可能幾行代碼就能搞定了,它里面有一個MPMoviePlayerViewController,利用起來簡單的不要不要的。
不過遺憾的是自從iOS 9.0開始,它是被Apple遺棄了的,9.0之后的項目建議用的我們下面再說,你要是有維護9.0之前的項目,可能它你也有必要了解一下,我們也介紹一個它的基本的使用,以及它里面的整個播放的代碼邏輯。
工程師以前寫過一個三方,KRVideoPlayer
這個播放器就是基于MediaPlayer框架寫的,里面就兩個文件,代碼也是相當(dāng)?shù)暮唵?,你直接把它源碼下載下來之后我們當(dāng)一個了解MediaPlayer的Demo簡單的說一下。下滿是它git上面展示的gif Demo圖片:
你在看看它源碼里面的文件:只有 KRVideoPlayerControlView 和 KRVideoPlayerController 兩個,簡單分析它們:
1、KRVideoPlayerControlView 繼承自 UIView
說白了這個文件寫的就是播放器的UI,包括一些播放按鈕,進度條,以及全屏切換等等
2、KRVideoPlayerController 集成自 MPMoviePlayerController
繼承之后直接使用MPMoviePlayerController來播放視頻,是在它初始化的時候在self.view 上添加 KRVideoPlayerControlView 這個自定義的UI,你可以看到下面的代碼:
// 初始化KRVideoPlayerController - (instancetype)initWithFrame:(CGRect)frame { self = [super init]; if (self) { self.view.frame = frame; self.view.backgroundColor = [UIColor blackColor]; self.controlStyle = MPMovieControlStyleNone; [self.view addSubview:self.videoControl]; self.videoControl.frame = self.view.bounds; [self configObserver]; [self configControlAction]; } return self; } // 懶加載KRVideoPlayerControlView - (KRVideoPlayerControlView *)videoControl { if (!_videoControl) { _videoControl = [[KRVideoPlayerControlView alloc] init]; } return _videoControl; }
關(guān)于MediaPlayer還有下面的需要你留意一下:
1、關(guān)于播放或者暫停等的方法都是在MPMediaPlayback協(xié)議里面的
2、MPMoviePlayerController就是遵守了上面說的MPMediaPlayback協(xié)議,下面的MPMoviePlayerController源碼:
3、在給MPMoviePlayerController寫的類別MPMovieProperties、MPMoviePlayerThumbnailGeneration、MPMoviePlayerTimedMetadataAdditions包含了這個播放器幾乎所有的功能,淡然這部分的方法代代碼都是在MPMoviePlayerController.h中,有興趣或者需要的可以command進去了解。
4、上面介紹的三方提供給大家的不僅僅是一份代碼,希望我們都能理解一個思路,就是自定義的播放器我們該怎么去理解去動手做。這點后面我還會再提。
關(guān)于MediaPlayer的暫時就提這么多,有問題歡迎交流。
該升級一下了
嗯,該升級一下了,說到這里就的說我們前面說到的9.0系統(tǒng)之后的播放器,這說這個之前順便提一個自己的見解,以前我們開發(fā)應(yīng)用的時候我記得最開始適配的最低版本是7.0以上的,到前兩年發(fā)展到8.0以上,按照我自己的理解,在11系統(tǒng)發(fā)布后我們要是做新應(yīng)用或者舊的項目項目維護的時候應(yīng)該要慢慢的舍棄7.0以及8.0的了,也就是最低版本按照9.0開始,因為不管是7.0還是8.0,用戶所占的比例真的是很小很下了,并且一些新鮮的功能在我們的低版本是不支持的, 維護的成本也會慢慢的變得越來越大,當(dāng)然這些也都不是空穴來風(fēng),可以上網(wǎng)去搜一下8.0之前版本系統(tǒng)占得比例,以及8.0、7.0給整個維護帶來的成本,我在最近逛一些論壇的時候也有同行在說這個問題了。好了回到正題!
說我們的正題:9.0之后Apple建議用的: AVKit框架,首先AVKit框架是8.0之后出現(xiàn)的,它是建立在我們熟悉的AVFoundation框架之上的.
利用AVKit進行視頻播放時我們整理一下我們需要的大致都在這幾個類或者協(xié)議當(dāng)中:
1、AVPlayerItem (視頻要播放的元素)
2、AVPlayerLayer (播放顯示視頻的圖層界面)
3、AVPlayer (用于播放音視頻)
4、AVPlayerViewController (控制器)
5、AVPlayerViewControllerDelegate(協(xié)議)
要是想要徹底的了解AVFoundation這個框架是不容易的,這個框架的確很龐大,有一本書叫做 《AV Foundation 開發(fā)秘籍》有興趣的可以去購買看看,自己也在學(xué)習(xí)當(dāng)中,后續(xù)的文章全都會整理在這個系列當(dāng)中。
這篇文章就等于是給這個系列開一個頭,這個框架的學(xué)習(xí)之路應(yīng)該是漫長的,也希望自己能堅持完吧這個系列文章全都總結(jié)出來。下面把上面說的各個類分別說一下:
1、AVPlayerItem
在我們使用AVPlayer播放視頻的時候,提供視頻信息的就是AVPlayerItem,一個AVPlayerItem對應(yīng)著你提供的一個視頻Url資源,這個理解它的時候可以把它比作一個Model, 你初始化了AVPlayerItem之后,并不是馬上就可以使用它了,因為凡是和Url網(wǎng)絡(luò)扯上關(guān)系的,都需要時間,等AVPlayerItem加載好之后就可以使用它了,那這一步我們怎么處理呢?
1> : 答案是利用KVO觀察statues屬性為 AVPlayerStatusReadyToPlay,看看這個屬性的定義:
@property (nonatomic, readonly) AVPlayerStatus status 它是一個只讀屬性,這點也需要注意,其實也就理解利用KVO的原因。
2>: 順便總結(jié)要是你要顯示當(dāng)前視屏的緩存進度,你需要監(jiān)測它的loadedTimeRanges屬性。
2、AVPlayerLayer
它主要負責(zé)的就是視頻的顯示,繼承自CALayer,其實你可以把它理解成我們的View。我們自定義的那些播放時候的控件就是添加在它上面的,比如我們能看到的播放按鈕,停止按鈕,或者播放進度條等等。
3、 AVPlayer
它主要負責(zé)的是管理視頻播放,暫停等等,相當(dāng)于一個視頻管理器,要是類比的話他就是一個ViewController(當(dāng)然不是真正的ViewController),這三者就基本含括了一個基本的視頻播,基于著三者我們總結(jié)一下播放一個視頻的基本的過程:
首先,得到視頻的URL 根據(jù)URL創(chuàng)建AVPlayerItem 把AVPlayerItem 提供給 AVPlayer AVPlayerLayer 顯示視頻。 AVPlayer 控制視頻, 播放, 暫停, 跳轉(zhuǎn) 等等。播放過程中獲取緩沖進度,獲取播放進度。視頻播放完成后做些什么,是暫停還是循環(huán)播放,還是獲取最后一幀圖像。
4、AVPlayerViewController
它是Apple 幫我們封裝好的可以一個視頻播放控制器,它就有一個 @property (nonatomic, strong, nullable) AVPlayer *player 的屬性,前面的AVPlayer也就像相應(yīng)的需要賦值給它,它里面還有一些我們需要理解一下的屬性,我們也把它寫出來,具體代碼我們下面再看:
player: 設(shè)置播放器 showsPlaybackControls: 設(shè)置是否顯示媒體播放組件,默認YES videoGravity: 設(shè)置視頻拉伸模式 allowsPictureInPicturePlayback: 設(shè)置是否允許畫中畫回放,默認YES delegate: 設(shè)置代理
5、AVPlayerViewControllerDelegate
這個代理就是前面說的AVPlayerViewController的協(xié)議,它主要的是為畫中畫的設(shè)置的代理,前面介紹 AVPlayerViewController 的時候有看到過一個是否允許畫中畫的屬性,具體什么是畫中畫相信大家都了解,看過直接的朋友應(yīng)該都看到了這個技術(shù)點的具體應(yīng)用。我們看看它里面的飯法規(guī)主要都干了些什么?
// 1、即將開始畫中畫 - (void)playerViewControllerWillStartPictureInPicture:(AVPlayerViewController *)playerViewController; // 2、開始畫中畫 - (void)playerViewControllerDidStartPictureInPicture:(AVPlayerViewController *)playerViewController; // 3、畫中畫失敗 - (void)playerViewController:(AVPlayerViewController *)playerViewController failedToStartPictureInPictureWithError:(NSError *)error; // 4、即將結(jié)束畫中畫 - (void)playerViewControllerWillStopPictureInPicture:(AVPlayerViewController *)playerViewController; // 5、結(jié)束畫中畫 - (void)playerViewControllerDidStopPictureInPicture:(AVPlayerViewController *)playerViewController;
我們看一個簡單的Demo
我們先不說關(guān)于AVFoundation復(fù)雜的東西,因為自己也是在學(xué)習(xí)這個 AVFoundation當(dāng)中,我們先看一些很簡單的Demo,就簡單的利用一下AVFoundation 播放一下視頻:
我們在簡單的看一下我們寫的這部分的代碼,簡單的先使用了一下我們說的上面的一些知識點:
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.view.backgroundColor = [UIColor whiteColor]; self.avPlayerItem = [AVPlayerItem playerItemWithURL:[NSURL URLWithString:MovieURL]]; self.avPlayer = [[AVPlayer alloc]initWithPlayerItem:self.avPlayerItem]; self.avPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:self.avPlayer]; self.avPlayerLayer.frame = CGRectMake(10, 100, 355, 200); [self.view.layer addSublayer:self.avPlayerLayer]; // 添加觀察者 [self addObserverWithAVPlayerItem]; } #pragma mark -- #pragma mark -- KVO -(void)addObserverWithAVPlayerItem{ //狀態(tài)添加觀察者 [self.avPlayerItem addObserver:self forKeyPath:@"status" options:(NSKeyValueObservingOptionNew) context:nil]; // 緩存進度添加觀察者 [self.avPlayerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil]; } -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{ AVPlayerItem * avplayeritem = (AVPlayerItem *)object; if ([keyPath isEqualToString:@"status"]) { AVPlayerStatus status = [[change objectForKey:@"new"] intValue]; if (status == AVPlayerStatusReadyToPlay) { NSLog(@"準備好播放"); CMTime duration = avplayeritem.duration; NSLog(@"視頻總時長:%.2f",CMTimeGetSeconds(duration)); // 播放 [self.avPlayer play]; }else if (status == AVPlayerStatusFailed){ NSLog(@"視頻準備發(fā)生錯誤"); }else{ NSLog(@"位置錯誤"); } }else if ([keyPath isEqualToString:@"loadedTimeRanges"]){ // 可以自定義緩存進度 NSTimeInterval timeInterval = [self alreadyCacheVideoProgress]; NSLog(@"視頻已經(jīng)緩存的時長:%.2f",timeInterval); } } #pragma mark -- #pragma mark -- alreadyCacheVideoProgress -(NSTimeInterval)alreadyCacheVideoProgress{ // 先獲取到它的緩存的進度 NSArray * cacheVideoTime = [self.avPlayerItem loadedTimeRanges]; // CMTimeRange 結(jié)構(gòu)體 start duration 表示起始位置 和 持續(xù)時間 // 獲取緩沖區(qū)域 CMTimeRange timeRange = [cacheVideoTime.firstObject CMTimeRangeValue]; float startSeconds = CMTimeGetSeconds(timeRange.start); float durationSeconds = CMTimeGetSeconds(timeRange.duration); // 計算總緩沖時間 = start + duration NSTimeInterval result = startSeconds + durationSeconds; return result; }
這些點我們有必要注意一下
1、CMTime 一個專門用于標(biāo)識視頻時間的結(jié)構(gòu)體
/*! @typedef CMTime @abstract Rational time value represented as int64/int32. */ typedef struct { CMTimeValue value; /*! @field value The value of the CMTime. value/timescale = seconds. 幀數(shù) */ CMTimeScale timescale; /*! @field timescale The timescale of the CMTime. value/timescale = seconds.幀率(影片每秒有幾幀)*/ CMTimeFlags flags; /*! @field flags The flags, eg. kCMTimeFlags_Valid, kCMTimeFlags_PositiveInfinity, etc. */ CMTimeEpoch epoch; /*! @field epoch Differentiates between equal timestamps that are actually different because of looping, multi-item sequencing, etc. Will be used during comparison: greater epochs happen after lesser ones. Additions/subtraction is only possible within a single epoch, however, since epoch length may be unknown/variable. */} CMTime;
前面的代碼中我們看到有一個獲取視頻總長度的方法:
CMTime duration = avplayeritem.duration; NSLog(@"視頻總時長:%.2f",CMTimeGetSeconds(duration));
可以看到CMTimeGetSeconds這個函數(shù)把一個CMTime類型轉(zhuǎn)化成一個浮點型,如果一個影片為60幀/每秒, 當(dāng)前想要跳轉(zhuǎn)到120幀的位置,也就是兩秒的位置,那么就可以創(chuàng)建一個 CMTime 類型數(shù)據(jù)。它通??梢杂孟旅鎯蓚€函數(shù)來創(chuàng)建.
1>: CMTimeMake(int64_t value, int32_t scale) Eg: CMTime time1 = CMTimeMake(120, 60);
2>:CMTimeMakeWithSeconds(Flout64 seconds, int32_t scale) Eg: CMTime time2 = CMTimeWithSeconds(120, 60);
CMTimeMakeWithSeconds 和 CMTimeMake 區(qū)別在于,第一個函數(shù)的第一個參數(shù)可以是float,其他一樣。
- (id)addPeriodicTimeObserverForInterval:(CMTime)interval queue:(nullable dispatch_queue_t)queue usingBlock:(void (^)(CMTime time))block;
比如說:我們把時間間隔設(shè)置為, 1/ 10 秒,然后 block 里面更新 UI。就是一秒鐘更新10次UI,我們驗證一下:
[self.avPlayer addPeriodicTimeObserverForInterval:CMTimeMake(1, 10) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) { // CMTime的timescale的定義幫助理解下面代碼 // @field timescale The timescale of the CMTime. value/timescale = seconds. float currentPlayTime = (double)self.avPlayerItem.currentTime.value/ self.avPlayerItem.currentTime.timescale; NSLog(@"當(dāng)前播放進度:%f",currentPlayTime); }];
我們隨便截取出一段打印的日志,看一下結(jié)果就可以驗證:
2、AVPlayerItem 視頻播放結(jié)束通知
/* Note that NSNotifications posted by AVPlayerItem may be posted on a different thread from the one on which the observer was registered. */ // notifications description AVF_EXPORT NSString *const AVPlayerItemTimeJumpedNotification NS_AVAILABLE(10_7, 5_0); // the item's current time has changed discontinuously AVF_EXPORT NSString *const AVPlayerItemDidPlayToEndTimeNotification NS_AVAILABLE(10_7, 4_0); // item has played to its end time AVF_EXPORT NSString *const AVPlayerItemFailedToPlayToEndTimeNotification NS_AVAILABLE(10_7, 4_3); // item has failed to play to its end time AVF_EXPORT NSString *const AVPlayerItemPlaybackStalledNotification NS_AVAILABLE(10_9, 6_0); // media did not arrive in time to continue playback AVF_EXPORT NSString *const AVPlayerItemNewAccessLogEntryNotification NS_AVAILABLE(10_9, 6_0); // a new access log entry has been added AVF_EXPORT NSString *const AVPlayerItemNewErrorLogEntryNotification NS_AVAILABLE(10_9, 6_0); // a new error log entry has been added // notification userInfo key type AVF_EXPORT NSString *const AVPlayerItemFailedToPlayToEndTimeErrorKey NS_AVAILABLE(10_7, 4_3); // NSError
3、這些個三方框架
(1): VKVideoPlayer
(2): ALMoviePlayerController
(3): PBJVideoPlayer
(4): 還有這個比較厲害的MobileVLCKit
感謝各位的閱讀!關(guān)于“iOS視頻播放方式有哪些”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
本文名稱:iOS視頻播放方式有哪些
文章轉(zhuǎn)載:http://www.rwnh.cn/article10/gspggo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站收錄、建站公司、網(wǎng)站內(nèi)鏈、網(wǎng)頁設(shè)計公司、App開發(fā)、移動網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)