資料介紹
AVPlayer:可以理解為播放器對(duì)象,靈活性好,可以高度化的自定義UI,但它本身不能顯示視頻,顯示需要另一個(gè)類AVPlayerLayer來顯示,繼承于CALayer,下面是摘自官方的一段介紹:
AVPlayer works equally well with local and remote media files.
You can display the visual content of items played by an instance of AVPlayer in a CoreAnimation layer of class AVPlayerLayer.
You can observe the status of a player using key-value observing.
主要是說它支持本地/網(wǎng)絡(luò)媒體播放,需要CoreAnimation下的AVPlayerLayer來顯示視頻,我們可以通過KVO監(jiān)聽player的播放狀態(tài)。
AVPlayerItem:存有相關(guān)媒體信息的類,一個(gè)視頻資源對(duì)應(yīng)一個(gè)AVPlayerItem對(duì)象,當(dāng)你需要循環(huán)播放多個(gè)視頻資源時(shí)也需創(chuàng)建多個(gè)AVPlayerItem對(duì)象。建議大家可以多看看官方的英文文檔解釋(題外話)。
An AVPlayerItem represents the presentation state of an asset that’s played by an AVPlayer object, and lets you observe that state.
AVAsset:主要用于獲取多媒體信息,可以理解為一個(gè)抽象類,不能直接使用,操作針對(duì)它的子類AVURLAsset,根據(jù)你視頻的url創(chuàng)建一個(gè)包含視頻媒體信息的AVURLAsset對(duì)象。
CMTime:還會(huì)用到這個(gè)媒體時(shí)間相關(guān)的類,如有不明白可以看之前一個(gè)帖子的解釋。
層級(jí)關(guān)系:
基于以上幾個(gè)類就能實(shí)現(xiàn)視頻的基本功能了,例如暫停、播放,快進(jìn)、后退、顯示播放/緩沖進(jìn)度。然后UI層面,層級(jí)很簡單,XLVideoPlayer繼承于UIView,上面我們說到顯示視頻需要AVPlayerLayer,我們將AVPlayerLayer加到view的layer上。

下面貼出主要的代碼,初始化AVPlayer對(duì)象
- (AVPlayerLayer *)playerLayer {
if (!_playerLayer) {
_playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
_playerLayer.backgroundColor = kPlayerBackgroundColor;
_playerLayer.videoGravity = AVLayerVideoGravityResizeAspect;//視頻填充模式
}
return _playerLayer;
}
- (AVPlayer *)player{
if (!_player) {
AVPlayerItem *playerItem = [self getAVPlayItem];
self.playerItem = playerItem;
_player = [AVPlayer playerWithPlayerItem:playerItem];
[self addProgressObserver];
?。踫elf addObserverToPlayerItem:playerItem];
}
return _player;
}
//initialize AVPlayerItem
- (AVPlayerItem *)getAVPlayItem{
NSAssert(self.videoUrl != nil, @“必須先傳入視頻url?。?!”);
if ([self.videoUrl rangeOfString:@“http”].location != NSNotFound) {
AVPlayerItem *playerItem=[AVPlayerItem playerItemWithURL:[NSURL URLWithString:[self.videoUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
return playerItem;
}else{
AVAsset *movieAsset = [[AVURLAsset alloc]initWithURL:[NSURL fileURLWithPath:self.videoUrl] options:nil];
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:movieAsset];
return playerItem;
}
}
同時(shí)我們注冊(cè)KVO,監(jiān)控視頻播放過程,這可以獲取視頻的播放進(jìn)度。AVPlayer有一個(gè)屬性currentItem是AVPlayerItem類型,表示當(dāng)前播放的視頻對(duì)象。
#pragma mark - monitor video playing course
-(void)addProgressObserver{
//get current playerItem object
AVPlayerItem *playerItem = self.player.currentItem;
__weak typeof(self) weakSelf = self;
//Set once per second
?。踫elf.player addPeriodicTimeObserverForInterval:CMTimeMake(1.0, 1.0) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
float current = CMTimeGetSeconds(time);
float total = CMTimeGetSeconds([playerItem duration]);
weakSelf.progressLabel.text = [weakSelf timeFormatted:current];
if (current) {
// NSLog(@“%f”, current / total);
weakSelf.slider.value = current / total;
if (weakSelf.slider.value == 1) { //complete block
if (weakSelf.completedPlayingBlock) {
weakSelf.completedPlayingBlock(weakSelf);
}else { //finish and loop playback
weakSelf.playOrPauseBtn.selected = NO;
?。踳eakSelf showOrHidenBar];
CMTime currentCMTime = CMTimeMake(0, 1);
?。踳eakSelf.player seekToTime:currentCMTime completionHandler:^(BOOL finished) {
weakSelf.slider.value = 0.0f;
}];
}
}
}
}];
}
以及監(jiān)聽AVPlayerItem對(duì)象的status/loadedTimeRanges屬性變化,status對(duì)應(yīng)播放狀態(tài),loadedTimeRanges網(wǎng)絡(luò)緩沖狀態(tài),當(dāng)loadedTimeRanges的改變時(shí),每緩沖一部分?jǐn)?shù)據(jù)就會(huì)更新此屬性,可以獲得本次緩沖加載的視頻范圍(包含起始時(shí)間、本次網(wǎng)絡(luò)加載時(shí)長)
#pragma mark - PlayerItem (status,loadedTimeRanges)
-(void)addObserverToPlayerItem:(AVPlayerItem *)playerItem{
//監(jiān)控狀態(tài)屬性,注意AVPlayer也有一個(gè)status屬性,通過監(jiān)控它的status也可以獲得播放狀態(tài)
?。踦layerItem addObserver:self forKeyPath:@“status” options:NSKeyValueObservingOptionNew context:nil];
//network loading progress
[playerItem addObserver:self forKeyPath:@“l(fā)oadedTimeRanges” options:NSKeyValueObservingOptionNew context:nil];
}
在這獲取視頻的總時(shí)長,網(wǎng)絡(luò)的視頻緩沖進(jìn)度,做相應(yīng)的顯示。
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
AVPlayerItem *playerItem = object;
if ([keyPath isEqualToString:@“status”]) {
AVPlayerStatus status = [[change objectForKey:@“new”] intValue];
if(status == AVPlayerStatusReadyToPlay){
self.totalDuration = CMTimeGetSeconds(playerItem.duration);
self.totalDurationLabel.text = [self timeFormatted:self.totalDuration];
}
}else if([keyPath isEqualToString:@“l(fā)oadedTimeRanges”]){
NSArray *array = playerItem.loadedTimeRanges;
CMTimeRange timeRange = [array.firstObject CMTimeRangeValue];//本次緩沖時(shí)間范圍
float startSeconds = CMTimeGetSeconds(timeRange.start);
float durationSeconds = CMTimeGetSeconds(timeRange.duration);
NSTimeInterval totalBuffer = startSeconds + durationSeconds;//緩沖總長度
self.slider.middleValue = totalBuffer / CMTimeGetSeconds(playerItem.duration);
// NSLog(@“totalBuffer:%.2f”,totalBuffer);
//remove loading animation
if (self.slider.middleValue 《= self.slider.value) {
self.activityIndicatorView.center = self.center;
?。踫elf addSubview:self.activityIndicatorView];
[self.activityIndicatorView startAnimating];
}else {
?。踫elf.activityIndicatorView removeFromSuperview];
}
}
}
下面這部分是定位視頻的某個(gè)位置播放,也就是快進(jìn)后退。
這里需要注意的是在用戶拖拽slider的過程中需要先暫停,否則手動(dòng)改變進(jìn)度和播放的進(jìn)度會(huì)有沖突,用戶拖拽完畢再去播放視頻。
- (void)finishChange {
_inOperation = NO;
[self hiden];
CMTime currentCMTime = CMTimeMake(self.slider.value * self.totalDuration, 1);
?。踫elf.player seekToTime:currentCMTime completionHandler:^(BOOL finished) {
[self.player play];
self.playOrPauseBtn.selected = YES;
}];
}
- labview超快自定義控件制作和普通自定義控件制作 14次下載
- labview自定義控件 22次下載
- 自定義視圖組件教程案例 15次下載
- Labview自定義右鍵快捷菜單功能實(shí)用小技巧 27次下載
- 精美的TF自定義控件源文件合集 32次下載
- 串口屏LUA教程10-自定義串口指令
- Xilinx基本自定義OpenRISC系統(tǒng)硬件教程 93次下載
- LCD1602自定義顯示字符及漢字 85次下載
- JAVA教程之自定義光標(biāo) 7次下載
- 自定義fifo接口控制器 1次下載
- 1602自定義字符 1次下載
- 自定義函數(shù)測試學(xué)習(xí)工程
- 基于SOPC的MPEG-4視頻播放器
- matlab自定義函數(shù)調(diào)用的方法
- CSF文件播放器
- 如何使用SDK進(jìn)行自定義音頻播放功能 3.1k次閱讀
- HarmonyOS應(yīng)用自定義鍵盤解決方案 2.1k次閱讀
- 如何添加自定義單板 1.2k次閱讀
- 如何快速創(chuàng)建用戶自定義Board和App工程 1.1k次閱讀
- TSMaster 自定義 LIN 調(diào)度表編程指導(dǎo) 2k次閱讀
- 添加自定義屬性控制fridaserver啟動(dòng)和停止 2.8k次閱讀
- 什么是自定義序列 2k次閱讀
- 自定義特性能做什么? 1.5k次閱讀
- 如何自定義函數(shù)或局部腳本 2.3k次閱讀
- 如何在Vivado中更改自定義的Interface 3.9k次閱讀
- 三種自定義彈窗UI組件封裝的實(shí)現(xiàn) 4.4k次閱讀
- 如何給EOS賬號(hào)設(shè)置自定義權(quán)限 1.9k次閱讀
- erlang如何自定義_ERLANG環(huán)境搭建 1.8k次閱讀
- springmvc 自定義攔截器實(shí)現(xiàn)未登錄用戶的攔截 3.5k次閱讀
- LCD1602自定義點(diǎn)陣字符詳解 1.4w次閱讀
下載排行
本周
- 1MDD品牌三極管MMBT3906數(shù)據(jù)手冊(cè)
- 2.33 MB | 次下載 | 免費(fèi)
- 2MDD品牌三極管S9012數(shù)據(jù)手冊(cè)
- 2.62 MB | 次下載 | 免費(fèi)
- 3聯(lián)想flex2-14D/15D說明書
- 4.92 MB | 次下載 | 免費(fèi)
- 4收音環(huán)繞擴(kuò)音機(jī) AVR-1507手冊(cè)
- 2.50 MB | 次下載 | 免費(fèi)
- 524Pin Type-C連接器設(shè)計(jì)報(bào)告
- 1.06 MB | 次下載 | 免費(fèi)
- 6新一代網(wǎng)絡(luò)可視化(NPB 2.0)
- 3.40 MB | 次下載 | 免費(fèi)
- 7MS1000TA 超聲波測量模擬前端芯片技術(shù)手冊(cè)
- 0.60 MB | 次下載 | 免費(fèi)
- 8MS1022高精度時(shí)間測量(TDC)電路數(shù)據(jù)手冊(cè)
- 1.81 MB | 次下載 | 免費(fèi)
本月
- 1愛華AIWA HS-J202維修手冊(cè)
- 3.34 MB | 37次下載 | 免費(fèi)
- 2PC5502負(fù)載均流控制電路數(shù)據(jù)手冊(cè)
- 1.63 MB | 23次下載 | 免費(fèi)
- 3NB-IoT芯片廠商的資料說明
- 0.31 MB | 22次下載 | 1 積分
- 4H110主板CPU PWM芯片ISL95858HRZ-T核心供電電路圖資料
- 0.63 MB | 6次下載 | 1 積分
- 5UWB653Pro USB口測距通信定位模塊規(guī)格書
- 838.47 KB | 5次下載 | 免費(fèi)
- 6技嘉H110主板IT8628E_BX IO電路圖資料
- 2.61 MB | 4次下載 | 1 積分
- 7蘇泊爾DCL6907(即CHK-S007)單芯片電磁爐原理圖資料
- 0.04 MB | 4次下載 | 1 積分
- 8100W準(zhǔn)諧振反激式恒流電源電路圖資料
- 0.09 MB | 2次下載 | 1 積分
總榜
- 1matlab軟件下載入口
- 未知 | 935137次下載 | 10 積分
- 2開源硬件-PMP21529.1-4 開關(guān)降壓/升壓雙向直流/直流轉(zhuǎn)換器 PCB layout 設(shè)計(jì)
- 1.48MB | 420064次下載 | 10 積分
- 3Altium DXP2002下載入口
- 未知 | 233089次下載 | 10 積分
- 4電路仿真軟件multisim 10.0免費(fèi)下載
- 340992 | 191439次下載 | 10 積分
- 5十天學(xué)會(huì)AVR單片機(jī)與C語言視頻教程 下載
- 158M | 183353次下載 | 10 積分
- 6labview8.5下載
- 未知 | 81602次下載 | 10 積分
- 7Keil工具M(jìn)DK-Arm免費(fèi)下載
- 0.02 MB | 73822次下載 | 10 積分
- 8LabVIEW 8.6下載
- 未知 | 65991次下載 | 10 積分
電子發(fā)燒友App





創(chuàng)作
發(fā)文章
發(fā)帖
提問
發(fā)資料
發(fā)視頻
上傳資料賺積分
評(píng)論