資料介紹
AVPlayer:可以理解為播放器對(duì)象,靈活性好,可以高度化的自定義UI,但它本身不能顯示視頻,顯示需要另一個(gè)類AVPlayerLayer來(lái)顯示,繼承于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.
主要是說(shuō)它支持本地/網(wǎng)絡(luò)媒體播放,需要CoreAnimation下的AVPlayerLayer來(lái)顯示視頻,我們可以通過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í)很簡(jiǎn)單,XLVideoPlayer繼承于UIView,上面我們說(shuō)到顯示視頻需要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];
[self 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
[self.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;
[weakSelf showOrHidenBar];
CMTime currentCMTime = CMTimeMake(0, 1);
[weakSelf.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í)長(zhǎng))
#pragma mark - PlayerItem (status,loadedTimeRanges)
-(void)addObserverToPlayerItem:(AVPlayerItem *)playerItem{
//監(jiān)控狀態(tài)屬性,注意AVPlayer也有一個(gè)status屬性,通過監(jiān)控它的status也可以獲得播放狀態(tài)
[playerItem addObserver:self forKeyPath:@“status” options:NSKeyValueObservingOptionNew context:nil];
//network loading progress
[playerItem addObserver:self forKeyPath:@“l(fā)oadedTimeRanges” options:NSKeyValueObservingOptionNew context:nil];
}
在這獲取視頻的總時(shí)長(zhǎng),網(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;//緩沖總長(zhǎng)度
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;
[self addSubview:self.activityIndicatorView];
[self.activityIndicatorView startAnimating];
}else {
[self.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);
[self.player seekToTime:currentCMTime completionHandler:^(BOOL finished) {
[self.player play];
self.playOrPauseBtn.selected = YES;
}];
}
- labview超快自定義控件制作和普通自定義控件制作 11次下載
- labview自定義控件 16次下載
- 自定義視圖組件教程案例 14次下載
- Labview自定義右鍵快捷菜單功能實(shí)用小技巧 26次下載
- 精美的TF自定義控件源文件合集 31次下載
- 串口屏LUA教程10-自定義串口指令
- Xilinx基本自定義OpenRISC系統(tǒng)硬件教程 93次下載
- 如何在LabVIEW中實(shí)現(xiàn)自定義控件 48次下載
- LCD1602自定義顯示字符及漢字 85次下載
- 自定義fifo接口控制器 1次下載
- 1602自定義字符 1次下載
- 自定義函數(shù)測(cè)試學(xué)習(xí)工程
- 基于SOPC的MPEG-4視頻播放器
- matlab自定義函數(shù)調(diào)用的方法
- CSF文件播放器
- TSMaster 自定義 LIN 調(diào)度表編程指導(dǎo) 389次閱讀
- 基于YOLOv8實(shí)現(xiàn)自定義姿態(tài)評(píng)估模型訓(xùn)練 2397次閱讀
- 博途用戶自定義庫(kù)的使用 634次閱讀
- 添加自定義屬性控制fridaserver啟動(dòng)和停止 1350次閱讀
- 什么是自定義序列 1028次閱讀
- 自定義特性能做什么? 700次閱讀
- FreeRTOS|自定義裁剪 1193次閱讀
- 基于AWTK和AWPLC開發(fā)自定義功能塊 818次閱讀
- 如何自定義函數(shù)或局部腳本 1305次閱讀
- 如何在Vivado中更改自定義的Interface 2658次閱讀
- 三種自定義彈窗UI組件封裝的實(shí)現(xiàn) 2887次閱讀
- 如何給EOS賬號(hào)設(shè)置自定義權(quán)限 1414次閱讀
- erlang如何自定義_ERLANG環(huán)境搭建 1467次閱讀
- springmvc 自定義攔截器實(shí)現(xiàn)未登錄用戶的攔截 2481次閱讀
- LCD1602自定義點(diǎn)陣字符詳解 1.3w次閱讀
下載排行
本周
- 1電子電路原理第七版PDF電子教材免費(fèi)下載
- 0.00 MB | 1490次下載 | 免費(fèi)
- 2單片機(jī)典型實(shí)例介紹
- 18.19 MB | 93次下載 | 1 積分
- 3S7-200PLC編程實(shí)例詳細(xì)資料
- 1.17 MB | 27次下載 | 1 積分
- 4筆記本電腦主板的元件識(shí)別和講解說(shuō)明
- 4.28 MB | 18次下載 | 4 積分
- 5開關(guān)電源原理及各功能電路詳解
- 0.38 MB | 10次下載 | 免費(fèi)
- 6基于AT89C2051/4051單片機(jī)編程器的實(shí)驗(yàn)
- 0.11 MB | 4次下載 | 免費(fèi)
- 7基于單片機(jī)和 SG3525的程控開關(guān)電源設(shè)計(jì)
- 0.23 MB | 3次下載 | 免費(fèi)
- 8基于單片機(jī)的紅外風(fēng)扇遙控
- 0.23 MB | 3次下載 | 免費(fèi)
本月
- 1OrCAD10.5下載OrCAD10.5中文版軟件
- 0.00 MB | 234313次下載 | 免費(fèi)
- 2PADS 9.0 2009最新版 -下載
- 0.00 MB | 66304次下載 | 免費(fèi)
- 3protel99下載protel99軟件下載(中文版)
- 0.00 MB | 51209次下載 | 免費(fèi)
- 4LabView 8.0 專業(yè)版下載 (3CD完整版)
- 0.00 MB | 51043次下載 | 免費(fèi)
- 5555集成電路應(yīng)用800例(新編版)
- 0.00 MB | 33562次下載 | 免費(fèi)
- 6接口電路圖大全
- 未知 | 30320次下載 | 免費(fèi)
- 7Multisim 10下載Multisim 10 中文版
- 0.00 MB | 28588次下載 | 免費(fèi)
- 8開關(guān)電源設(shè)計(jì)實(shí)例指南
- 未知 | 21539次下載 | 免費(fèi)
總榜
- 1matlab軟件下載入口
- 未知 | 935053次下載 | 免費(fèi)
- 2protel99se軟件下載(可英文版轉(zhuǎn)中文版)
- 78.1 MB | 537791次下載 | 免費(fèi)
- 3MATLAB 7.1 下載 (含軟件介紹)
- 未知 | 420026次下載 | 免費(fèi)
- 4OrCAD10.5下載OrCAD10.5中文版軟件
- 0.00 MB | 234313次下載 | 免費(fèi)
- 5Altium DXP2002下載入口
- 未知 | 233046次下載 | 免費(fèi)
- 6電路仿真軟件multisim 10.0免費(fèi)下載
- 340992 | 191183次下載 | 免費(fèi)
- 7十天學(xué)會(huì)AVR單片機(jī)與C語(yǔ)言視頻教程 下載
- 158M | 183277次下載 | 免費(fèi)
- 8proe5.0野火版下載(中文版免費(fèi)下載)
- 未知 | 138039次下載 | 免費(fèi)
評(píng)論
查看更多