赞
踩
AVPlayer是AVFoundation框架中的一个类,它比较接近于底层,可以利用该类进行自定义样式的视频播放。AVPlayer本身并不能显示视频,如果AVPlayer要显示视频,则它必须要创建一个播放器层AVPlayerLayer来用于展示视频,播放器层继承了CALayer,我们只需要把AVPlayerLayer添加到控制器view的layer中即可。我们在了解AVPlayer之前,首先需要了解以下几个常用类:
AVAsset : 用于获取多媒体信息,是一个抽象类。
AVURLAsset : 媒体资源管理类,管理视频的一些基本信息和状态,一个AVPlayerItem对应着一个视频资源。
eg:一个视频播放的例子
//
// ViewController.m
// AVPlayerDemo
//
#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>
@interface ViewController ()
@property (nonatomic,strong) AVPlayer *player; // 播放器对象
@property (nonatomic,strong) AVPlayerLayer *playerLayer;
@property (weak, nonatomic) IBOutlet UIView *container;
@property (weak, nonatomic) IBOutlet UIButton *playOrPause;
@property (weak, nonatomic) IBOutlet UIProgressView *progress;
@end
@implementation ViewController
- (AVPlayer *)player
{
if (!_player) {
AVPlayerItem *playerItem = [self getPlayItem:1];
_player = [AVPlayer playerWithPlayerItem:playerItem];
[self addProgressObserver];
[self addobserToPlayerItem:playerItem];
[self addNotification];
}
return _player;
}
- (AVPlayerLayer *)playerLayer
{
if (!_playerLayer) {
_playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
_playerLayer.frame = self.container.bounds;
}
return _playerLayer;
}
- (void)setupUI
{
AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
playerLayer.frame = self.container.bounds;
[self.container.layer addSublayer:playerLayer];
[self.playOrPause setTitle:@"Pause" forState:UIControlStateNormal];
}
- (void)viewDidLoad {
[super viewDidLoad];
// 创建播放器层
[self setupUI];
[self.player play];
}
#pragma mark -UI事件
- (IBAction)playClick:(UIButton *)btn {
if (self.player.rate == 0) // 如果当前是暂停状态
{
[btn setTitle:@"Pause" forState:UIControlStateNormal];
[self.player seekToTime:CMTimeMake(playCurrent, 1.0)];
[self.player play];
}
if (self.player.rate == 1) // 如果当前是正在播放状态
{
[self.player pause];
[btn setTitle:@"Play" forState:UIControlStateNormal];
}
}
- (IBAction)navigationButtonClick:(UIButton *)sender {
[self removeNotification];
[self removeObserverFromPlayerItem:self.player.currentItem];
AVPlayerItem *playerItem = [self getPlayItem:(int)sender.tag];
[self addobserToPlayerItem:playerItem];
// 切换视频
[self.player replaceCurrentItemWithPlayerItem:playerItem];
[self initUI];
[self addNotification];
}
- (void)initUI
{
[self.progress setProgress:0.0];
[self.playOrPause setTitle:@"Pause" forState:UIControlStateNormal];
[self.player seekToTime:CMTimeMake(0, 1)];
}
- (AVPlayerItem *)getPlayItem:(int)videoIndex
{
NSURL *url = [[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%i",videoIndex] ofType:@"mp4"]];
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:url];
return playerItem;
}
- (void)playbackFinished:(NSNotification *)notification
{
[self.player seekToTime:CMTimeMake(0, 1)]; // 视频播放完成以后,从新设置到起点
NSLog(@"视频播放完成");
[self removeNotification];
}
- (void)addNotification
{
//给AVPlayerItem添加播放完成通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackFinished:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.player.currentItem];
}
-(void)removeNotification{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
static float playCurrent = 0;
- (void)addProgressObserver
{
AVPlayerItem *playerItem = self.player.currentItem;
UIProgressView *progress = self.progress;
// 设置每秒执行一次
[self.player addPeriodicTimeObserverForInterval:CMTimeMake(1.0, 1.0) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
float current = CMTimeGetSeconds(time);
playCurrent = current;
float total = CMTimeGetSeconds([playerItem duration]);
NSLog(@"当前已经播放了%.2fs",current);
if (current) {
[progress setProgress:(current/total) animated:YES];
}
}];
}
// 为AVPlayerItem添加监控
- (void)addobserToPlayerItem:(AVPlayerItem *)playerItem
{
//监控状态属性,注意AVPlayer也有一个status属性,通过监控它的status也可以获得播放状态
[playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
// 监控网络加载情况
[playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];
}
-(void)removeObserverFromPlayerItem:(AVPlayerItem *)playerItem{
[playerItem removeObserver:self forKeyPath:@"status"];
[playerItem removeObserver:self forKeyPath:@"loadedTimeRanges"];
}
/**
* 通过KVO监控播放器的状态
*
* @param keyPath 监控属性
* @param object 监控器
* @param change 状态改变
* @param context 上下文
*/
- (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) {
NSLog(@"正在播放...视频总长度:%.2f",CMTimeGetSeconds(playerItem.duration));
}
}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; // 缓冲总长度
NSLog(@"共缓冲:%.2f",totalBuffer);
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。