資料介紹
AVPlayer:可以理解為播放器對象,靈活性好,可以高度化的自定義UI,但它本身不能顯示視頻,顯示需要另一個類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.
主要是說它支持本地/網絡媒體播放,需要CoreAnimation下的AVPlayerLayer來顯示視頻,我們可以通過KVO監聽player的播放狀態。
AVPlayerItem:存有相關媒體信息的類,一個視頻資源對應一個AVPlayerItem對象,當你需要循環播放多個視頻資源時也需創建多個AVPlayerItem對象。建議大家可以多看看官方的英文文檔解釋(題外話)。
An AVPlayerItem represents the presentation state of an asset that’s played by an AVPlayer object, and lets you observe that state.
AVAsset:主要用于獲取多媒體信息,可以理解為一個抽象類,不能直接使用,操作針對它的子類AVURLAsset,根據你視頻的url創建一個包含視頻媒體信息的AVURLAsset對象。
CMTime:還會用到這個媒體時間相關的類,如有不明白可以看之前一個帖子的解釋。
層級關系:
基于以上幾個類就能實現視頻的基本功能了,例如暫停、播放,快進、后退、顯示播放/緩沖進度。然后UI層面,層級很簡單,XLVideoPlayer繼承于UIView,上面我們說到顯示視頻需要AVPlayerLayer,我們將AVPlayerLayer加到view的layer上。
下面貼出主要的代碼,初始化AVPlayer對象
- (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;
}
}
同時我們注冊KVO,監控視頻播放過程,這可以獲取視頻的播放進度。AVPlayer有一個屬性currentItem是AVPlayerItem類型,表示當前播放的視頻對象。
#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;
}];
}
}
}
}];
}
以及監聽AVPlayerItem對象的status/loadedTimeRanges屬性變化,status對應播放狀態,loadedTimeRanges網絡緩沖狀態,當loadedTimeRanges的改變時,每緩沖一部分數據就會更新此屬性,可以獲得本次緩沖加載的視頻范圍(包含起始時間、本次網絡加載時長)
#pragma mark - PlayerItem (status,loadedTimeRanges)
-(void)addObserverToPlayerItem:(AVPlayerItem *)playerItem{
//監控狀態屬性,注意AVPlayer也有一個status屬性,通過監控它的status也可以獲得播放狀態
[playerItem addObserver:self forKeyPath:@“status” options:NSKeyValueObservingOptionNew context:nil];
//network loading progress
[playerItem addObserver:self forKeyPath:@“loadedTimeRanges” options:NSKeyValueObservingOptionNew context:nil];
}
在這獲取視頻的總時長,網絡的視頻緩沖進度,做相應的顯示。
- (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:@“loadedTimeRanges”]){
NSArray *array = playerItem.loadedTimeRanges;
CMTimeRange timeRange = [array.firstObject CMTimeRangeValue];//本次緩沖時間范圍
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;
[self addSubview:self.activityIndicatorView];
[self.activityIndicatorView startAnimating];
}else {
[self.activityIndicatorView removeFromSuperview];
}
}
}
下面這部分是定位視頻的某個位置播放,也就是快進后退。
這里需要注意的是在用戶拖拽slider的過程中需要先暫停,否則手動改變進度和播放的進度會有沖突,用戶拖拽完畢再去播放視頻。
- (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超快自定义控件制作和普通自定义控件制作14次下载
- labview自定义控件19次下载
- 自定义视图组件教程案例15次下载
- Labview自定义右键快捷菜单功能实用小技巧27次下载
- 精美的TF自定义控件源文件合集32次下载
- 串口屏LUA教程10-自定义串口指令16次下载
- Xilinx基本自定义OpenRISC系统硬件教程93次下载
- 如何在LabVIEW中实现自定义控件49次下载
- LCD1602自定义显示字符及汉字85次下载
- 自定义fifo接口控制器1次下载
- 1602自定义字符1次下载
- 自定义函数测试学习工程5次下载
- 基于SOPC的MPEG-4视频播放器34次下载
- matlab自定义函数调用的方法88次下载
- CSF文件播放器469次下载
- HarmonyOS应用自定义键盘解决方案633次阅读
- 如何添加自定义单板570次阅读
- 如何快速创建用户自定义Board和App工程514次阅读
- TSMaster 自定义 LIN 调度表编程指导1166次阅读
- 博途用户自定义库的使用1654次阅读
- 添加自定义属性控制fridaserver启动和停止2251次阅读
- 什么是自定义序列1574次阅读
- 自定义特性能做什么?1093次阅读
- 如何自定义函数或局部脚本1787次阅读
- 如何在Vivado中更改自定义的Interface3430次阅读
- 三种自定义弹窗UI组件封装的实现3604次阅读
- 如何给EOS账号设置自定义权限1687次阅读
- erlang如何自定义_ERLANG环境搭建1629次阅读
- springmvc 自定义拦截器实现未登录用户的拦截2601次阅读
- LCD1602自定义点阵字符详解13854次阅读
下載排行
本周
- 1三相逆變主電路的原理圖和PCB資料合集免費下載
- 27.35 MB | 107次下載 | 1 積分
- 2蘋果iphone 11電路原理圖
- 4.98 MB | 10次下載 | 5 積分
- 3匯編語言教學中文資料
- 1.43 MB | 3次下載 | 免費
- 4HPS27W高精度氣壓與溫度傳感器:特性、應用及接口設計
- 0.99 MB | 1次下載 | 免費
- 5AU3116 2×60W模擬輸入雙通道Class-D 音頻功率放大器數據手冊
- 1.19 MB | 1次下載 | 免費
- 6KP14622必易微PF>0.9 的高精度、調光型 LED 恒流驅動控制芯片
- 637.86 KB | 次下載 | 免費
- 7PC102A 用于USB Type-C PD3.2140W 線材的eMarker芯片數據手冊
- 0.41 MB | 次下載 | 免費
- 8 BH系列高壓干簧繼電器-測試測量與水銀繼電器替代的理想選擇!
- 2.31 MB | 次下載 | 免費
本月
- 1三相逆變主電路的原理圖和PCB資料合集免費下載
- 27.35 MB | 107次下載 | 1 積分
- 2PCB的EMC設計指南
- 2.47 MB | 16次下載 | 1 積分
- 3蘋果iphone 11電路原理圖
- 4.98 MB | 10次下載 | 5 積分
- 4TL494工業用開關電源原理圖資料
- 0.22 MB | 9次下載 | 1 積分
- 5運算放大器基本電路中文資料
- 1.30 MB | 9次下載 | 免費
- 6常用電子元器件介紹
- 3.21 MB | 7次下載 | 免費
- 7AIWA J36 維修手冊
- 4.34 MB | 4次下載 | 10 積分
- 8QW2893應急燈專用檢測芯片
- 590.40 KB | 4次下載 | 免費
總榜
- 1matlab軟件下載入口
- 未知 | 935130次下載 | 10 積分
- 2開源硬件-PMP21529.1-4 開關降壓/升壓雙向直流/直流轉換器 PCB layout 設計
- 1.48MB | 420064次下載 | 10 積分
- 3Altium DXP2002下載入口
- 未知 | 233089次下載 | 10 積分
- 4電路仿真軟件multisim 10.0免費下載
- 340992 | 191390次下載 | 10 積分
- 5十天學會AVR單片機與C語言視頻教程 下載
- 158M | 183344次下載 | 10 積分
- 6labview8.5下載
- 未知 | 81591次下載 | 10 積分
- 7Keil工具MDK-Arm免費下載
- 0.02 MB | 73815次下載 | 10 積分
- 8LabVIEW 8.6下載
- 未知 | 65989次下載 | 10 積分
評論