亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > iOS > 正文

詳解iOS視頻播放方式

2019-10-21 18:43:07
字體:
來源:轉載
供稿:網友

多媒體這整個系列的文章自己也準備好開始整理了,先從視頻音頻最簡單也是最常用的播放出發慢慢的往下深究,探索到底層的編碼解碼等等,這篇文章就從視頻的播放這個最簡單的說起。

iOS的視頻播放方式有幾種?其實要是只是簡單的想播放一段視頻并且對UI沒什么要求的話的確比較簡單,很容易搞定,但我相信這種情況除了你的Demo一般是不會出現的,對播放UI的定義以及可能有各種不同的需求對應著你是不能隨便寫個播放器就沒事了的。

最原始的播放

要不是剛接觸iOS開發的同學應該是知道MediaPlayer這個框架的,要是想簡單的使用它播放視頻,可能幾行代碼就能搞定了,它里面有一個MPMoviePlayerViewController,利用起來簡單的不要不要的。

不過遺憾的是自從iOS 9.0開始,它是被Apple遺棄了的,9.0之后的項目建議用的我們下面再說,你要是有維護9.0之前的項目,可能它你也有必要了解一下,我們也介紹一個它的基本的使用,以及它里面的整個播放的代碼邏輯。

工程師以前寫過一個三方,KRVideoPlayer 

這個播放器就是基于MediaPlayer框架寫的,里面就兩個文件,代碼也是相當的簡單,你直接把它源碼下載下來之后我們當一個了解MediaPlayer的Demo簡單的說一下。下滿是它git上面展示的gif Demo圖片:

iOS,視頻播放方式

你在看看它源碼里面的文件:只有 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;}

 

關于MediaPlayer還有下面的需要你留意一下:

1、關于播放或者暫停等的方法都是在MPMediaPlayback協議里面的

2、MPMoviePlayerController就是遵守了上面說的MPMediaPlayback協議,下面的MPMoviePlayerController源碼:

iOS,視頻播放方式

3、在給MPMoviePlayerController寫的類別MPMovieProperties、MPMoviePlayerThumbnailGeneration、MPMoviePlayerTimedMetadataAdditions包含了這個播放器幾乎所有的功能,淡然這部分的方法代代碼都是在MPMoviePlayerController.h中,有興趣或者需要的可以command進去了解。

4、上面介紹的三方提供給大家的不僅僅是一份代碼,希望我們都能理解一個思路,就是自定義的播放器我們該怎么去理解去動手做。這點后面我還會再提。

關于MediaPlayer的暫時就提這么多,有問題歡迎交流。

該升級一下了

 嗯,該升級一下了,說到這里就的說我們前面說到的9.0系統之后的播放器,這說這個之前順便提一個自己的見解,以前我們開發應用的時候我記得最開始適配的最低版本是7.0以上的,到前兩年發展到8.0以上,按照我自己的理解,在11系統發布后我們要是做新應用或者舊的項目項目維護的時候應該要慢慢的舍棄7.0以及8.0的了,也就是最低版本按照9.0開始,因為不管是7.0還是8.0,用戶所占的比例真的是很小很下了,并且一些新鮮的功能在我們的低版本是不支持的, 維護的成本也會慢慢的變得越來越大,當然這些也都不是空穴來風,可以上網去搜一下8.0之前版本系統占得比例,以及8.0、7.0給整個維護帶來的成本,我在最近逛一些論壇的時候也有同行在說這個問題了。好了回到正題!

說我們的正題:9.0之后Apple建議用的: AVKit框架,首先AVKit框架是8.0之后出現的,它是建立在我們熟悉的AVFoundation框架之上的.

利用AVKit進行視頻播放時我們整理一下我們需要的大致都在這幾個類或者協議當中:

1、AVPlayerItem                          (視頻要播放的元素)

2、AVPlayerLayer                        (播放顯示視頻的圖層界面)

3、AVPlayer                                (用于播放音視頻)

4、AVPlayerViewController            (控制器)

5、AVPlayerViewControllerDelegate(協議)

要是想要徹底的了解AVFoundation這個框架是不容易的,這個框架的確很龐大,有一本書叫做 《AV Foundation 開發秘籍》有興趣的可以去購買看看,自己也在學習當中,后續的文章全都會整理在這個系列當中。

這篇文章就等于是給這個系列開一個頭,這個框架的學習之路應該是漫長的,也希望自己能堅持完吧這個系列文章全都總結出來。下面把上面說的各個類分別說一下:

1、AVPlayerItem

在我們使用AVPlayer播放視頻的時候,提供視頻信息的就是AVPlayerItem,一個AVPlayerItem對應著你提供的一個視頻Url資源,這個理解它的時候可以把它比作一個Model, 你初始化了AVPlayerItem之后,并不是馬上就可以使用它了,因為凡是和Url網絡扯上關系的,都需要時間,等AVPlayerItem加載好之后就可以使用它了,那這一步我們怎么處理呢?

1> : 答案是利用KVO觀察statues屬性為 AVPlayerStatusReadyToPlay,看看這個屬性的定義:

 @property (nonatomic, readonly) AVPlayerStatus status  它是一個只讀屬性,這點也需要注意,其實也就理解利用KVO的原因。

2>: 順便總結要是你要顯示當前視屏的緩存進度,你需要監測它的loadedTimeRanges屬性。

2、AVPlayerLayer

它主要負責的就是視頻的顯示,繼承自CALayer,其實你可以把它理解成我們的View。我們自定義的那些播放時候的控件就是添加在它上面的,比如我們能看到的播放按鈕,停止按鈕,或者播放進度條等等。

3、 AVPlayer  

它主要負責的是管理視頻播放,暫停等等,相當于一個視頻管理器,要是類比的話他就是一個ViewController(當然不是真正的ViewController),這三者就基本含括了一個基本的視頻播,基于著三者我們總結一下播放一個視頻的基本的過程:

首先,得到視頻的URL 根據URL創建AVPlayerItem 把AVPlayerItem 提供給 AVPlayer AVPlayerLayer 顯示視頻。 AVPlayer 控制視頻, 播放, 暫停, 跳轉 等等。播放過程中獲取緩沖進度,獲取播放進度。視頻播放完成后做些什么,是暫停還是循環播放,還是獲取最后一幀圖像。

4、AVPlayerViewController

它是Apple 幫我們封裝好的可以一個視頻播放控制器,它就有一個  @property (nonatomic, strong, nullable) AVPlayer *player 的屬性,前面的AVPlayer也就像相應的需要賦值給它,它里面還有一些我們需要理解一下的屬性,我們也把它寫出來,具體代碼我們下面再看:

player:                                    設置播放器 showsPlaybackControls:           設置是否顯示媒體播放組件,默認YES videoGravity:                           設置視頻拉伸模式 allowsPictureInPicturePlayback: 設置是否允許畫中畫回放,默認YES delegate:                                設置代理

5、AVPlayerViewControllerDelegate

這個代理就是前面說的AVPlayerViewController的協議,它主要的是為畫中畫的設置的代理,前面介紹 AVPlayerViewController 的時候有看到過一個是否允許畫中畫的屬性,具體什么是畫中畫相信大家都了解,看過直接的朋友應該都看到了這個技術點的具體應用。我們看看它里面的飯法規主要都干了些什么?

// 1、即將開始畫中畫- (void)playerViewControllerWillStartPictureInPicture:(AVPlayerViewController *)playerViewController;// 2、開始畫中畫- (void)playerViewControllerDidStartPictureInPicture:(AVPlayerViewController *)playerViewController;// 3、畫中畫失敗- (void)playerViewController:(AVPlayerViewController *)playerViewController failedToStartPictureInPictureWithError:(NSError *)error;// 4、即將結束畫中畫- (void)playerViewControllerWillStopPictureInPicture:(AVPlayerViewController *)playerViewController;// 5、結束畫中畫- (void)playerViewControllerDidStopPictureInPicture:(AVPlayerViewController *)playerViewController; 

 

我們看一個簡單的Demo 

我們先不說關于AVFoundation復雜的東西,因為自己也是在學習這個 AVFoundation當中,我們先看一些很簡單的Demo,就簡單的利用一下AVFoundation 播放一下視頻:

iOS,視頻播放方式

我們在簡單的看一下我們寫的這部分的代碼,簡單的先使用了一下我們說的上面的一些知識點:

- (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{ //狀態添加觀察者 [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(@"視頻準備發生錯誤"); }else{  NSLog(@"位置錯誤"); } }else if ([keyPath isEqualToString:@"loadedTimeRanges"]){  // 可以自定義緩存進度  NSTimeInterval timeInterval = [self alreadyCacheVideoProgress];  NSLog(@"視頻已經緩存的時長:%.2f",timeInterval); }}#pragma mark --#pragma mark -- alreadyCacheVideoProgress-(NSTimeInterval)alreadyCacheVideoProgress{  // 先獲取到它的緩存的進度 NSArray * cacheVideoTime = [self.avPlayerItem loadedTimeRanges]; // CMTimeRange 結構體 start duration 表示起始位置 和 持續時間 // 獲取緩沖區域 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  一個專門用于標識視頻時間的結構體

/*!	@typedef	CMTime	@abstract	Rational time value represented as int64/int32.*/typedef struct{	CMTimeValue	value;		/*! @field value The value of the CMTime. value/timescale = seconds. 幀數 */	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這個函數把一個CMTime類型轉化成一個浮點型,如果一個影片為60幀/每秒, 當前想要跳轉到120幀的位置,也就是兩秒的位置,那么就可以創建一個 CMTime 類型數據。它通常可以用下面兩個函數來創建.

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 區別在于,第一個函數的第一個參數可以是float,其他一樣。

- (id)addPeriodicTimeObserverForInterval:(CMTime)interval queue:(nullable dispatch_queue_t)queue usingBlock:(void (^)(CMTime time))block;

 

比如說:我們把時間間隔設置為, 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(@"當前播放進度:%f",currentPlayTime); }];

 

我們隨便截取出一段打印的日志,看一下結果就可以驗證:

iOS,視頻播放方式

2、AVPlayerItem  視頻播放結束通知

/* Note that NSNotifications posted by AVPlayerItem may be posted on a different thread from the one on which the observer was registered. */// notifications          descriptionAVF_EXPORT NSString *const AVPlayerItemTimeJumpedNotification			 NS_AVAILABLE(10_7, 5_0);	// the item's current time has changed discontinuouslyAVF_EXPORT NSString *const AVPlayerItemDidPlayToEndTimeNotification NS_AVAILABLE(10_7, 4_0); // item has played to its end timeAVF_EXPORT NSString *const AVPlayerItemFailedToPlayToEndTimeNotification NS_AVAILABLE(10_7, 4_3); // item has failed to play to its end timeAVF_EXPORT NSString *const AVPlayerItemPlaybackStalledNotification NS_AVAILABLE(10_9, 6_0); // media did not arrive in time to continue playbackAVF_EXPORT NSString *const AVPlayerItemNewAccessLogEntryNotification	 NS_AVAILABLE(10_9, 6_0);	// a new access log entry has been addedAVF_EXPORT NSString *const AVPlayerItemNewErrorLogEntryNotification		 NS_AVAILABLE(10_9, 6_0);	// a new error log entry has been added// notification userInfo key         typeAVF_EXPORT NSString *const AVPlayerItemFailedToPlayToEndTimeErrorKey NS_AVAILABLE(10_7, 4_3); // NSError

 

3、這些個三方框架

(1): VKVideoPlayer

(2): ALMoviePlayerController

(3): PBJVideoPlayer

(4): 還有這個比較厲害的MobileVLCKit

關于上面上的這些三方都給出了連接,最后一個給的是一篇幫助我們集成的文章,這些三方在后面這個系列文章的總結中會一點點慢慢的全都說一下,在這里只提一下有這些框架在,有興趣可以先了解,后面我在總結。


注:相關教程知識閱讀請移步到IOS開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
精品久久久国产| 欧美激情va永久在线播放| 成人黄色在线观看| 欧美激情视频一区| 2020国产精品视频| 欧美激情精品久久久久久| 中文在线资源观看视频网站免费不卡| 成人黄色av网站| 91国内免费在线视频| 一区二区三区国产视频| 国产亚洲精品美女久久久久| 日本aⅴ大伊香蕉精品视频| 一区二区在线视频播放| 久久久精品中文字幕| 超薄丝袜一区二区| 欧美在线免费看| 日韩视频免费观看| 国产精品成人一区二区三区吃奶| 精品国偷自产在线视频| 欧美日韩国产成人在线观看| 久久国产精品偷| 日韩欧美在线中文字幕| 亚洲激情电影中文字幕| 91亚洲国产精品| 亚洲男人的天堂在线| 欧美性精品220| 九九久久精品一区| 日本中文字幕久久看| 国产日韩在线看| www.精品av.com| 国语自产精品视频在线看抢先版图片| 欧美一区二粉嫩精品国产一线天| 久久亚洲精品国产亚洲老地址| 欧美一级大胆视频| 日韩精品在线私人| www.久久色.com| 亚洲a一级视频| 国产亚洲精品一区二区| 91色视频在线导航| 久久色免费在线视频| 九九久久久久99精品| 国内成人精品视频| 中文字幕免费国产精品| 久久夜色撩人精品| 亚洲第一精品电影| 欧美影院成年免费版| 在线视频欧美日韩| 精品毛片网大全| 国产精品久久久久久久9999| 午夜精品福利电影| 久久久久国产精品免费| 成人免费大片黄在线播放| 91高清视频在线免费观看| 色先锋久久影院av| 国产精品极品美女在线观看免费| 不卡在线观看电视剧完整版| 成人伊人精品色xxxx视频| 92看片淫黄大片看国产片| 欧美老妇交乱视频| 亚洲四色影视在线观看| 亚洲精品国产品国语在线| 亚洲国产天堂久久综合| 亚洲国产欧美日韩精品| 欧美亚洲视频在线看网址| 中文字幕九色91在线| 精品国内产的精品视频在线观看| 91欧美激情另类亚洲| 亚洲精品国产suv| 91精品国产自产在线观看永久| 日本乱人伦a精品| 日韩精品视频在线观看网址| 欧美性视频网站| 一区二区三区视频免费在线观看| 日韩精品免费观看| 国产一区二区三区欧美| 中文字幕亚洲专区| 欧美一区二区色| 久久久在线视频| 国产精品一区二区三区在线播放| 久久亚洲影音av资源网| 亚洲性线免费观看视频成熟| 亚洲人成电影在线观看天堂色| 影音先锋欧美在线资源| 日韩av中文字幕在线免费观看| 亚洲精品国产精品国自产观看浪潮| 成人免费视频网址| 欧美人在线观看| 91精品久久久久久久久久| 亚洲精品一区久久久久久| 色综合男人天堂| 亚洲国产精品成人精品| 久久精品中文字幕电影| 性色av一区二区三区红粉影视| 日韩中文在线视频| 精品国模在线视频| 日本在线精品视频| 91黑丝高跟在线| 国产精品国模在线| 亚洲成人免费网站| 亚洲国产精品视频在线观看| 国产精品日韩电影| 欧美日韩免费网站| 51视频国产精品一区二区| www欧美日韩| 播播国产欧美激情| 亚洲人成网站免费播放| 日韩国产欧美区| 国产九九精品视频| 97超碰蝌蚪网人人做人人爽| 欧美日韩在线看| 国内精品久久久久影院优| 欧美激情精品久久久久久蜜臀| 欧美激情第6页| 91久久久国产精品| 国产亚洲综合久久| 中文字幕亚洲一区在线观看| 久久九九精品99国产精品| 精品久久久久久| 亚洲欧美成人精品| www高清在线视频日韩欧美| 欧美日韩国产一区在线| 亚洲男女自偷自拍图片另类| 国内精品久久影院| 中文字幕精品一区二区精品| 精品中文字幕在线观看| 国产一区私人高清影院| 国产精品入口夜色视频大尺度| 久久久久久久久久久人体| 国产精品一区二区女厕厕| 日韩av在线播放资源| 韩日欧美一区二区| 亚洲欧美中文日韩在线v日本| 国产精自产拍久久久久久蜜| 国产精品揄拍一区二区| 亚洲欧美制服另类日韩| 欧美孕妇毛茸茸xxxx| 久久在线免费视频| 久久久精品中文字幕| 日本久久久久久久| 亚洲国产中文字幕在线观看| 久久久久久91| 国产亚洲精品久久久久久| 国产午夜精品理论片a级探花| 亚洲国产精品成人一区二区| 日韩精品视频在线观看网址| 91网站在线免费观看| 成人精品在线观看| 国内精品模特av私拍在线观看| www欧美xxxx| 亚洲色图国产精品| 国产精品国模在线| 国产精品444| 欧美国产视频日韩| 91免费在线视频网站| 欧美性猛交xxxx乱大交蜜桃| 欧美人与性动交| 成人精品一区二区三区| 国产精品免费看久久久香蕉| 69av视频在线播放| 欧美大片在线看免费观看| 国产欧美精品xxxx另类| 欧美激情免费观看| 中文字幕亚洲一区二区三区五十路| 91免费精品国偷自产在线|