使用AVPlayer
来源:互联网 发布:网络教育好通过率 编辑:程序博客网 时间:2024/04/20 21:38
在iOS开发中,播放视频通常有两种方式,一种是使用MPMoviePlayerController(需要导入MediaPlayer.Framework),还有一种是使用AVPlayer。关于这两个类的区别可以参考http://stackoverflow.com/questions/8146942/avplayer-and-mpmovieplayercontroller-differences,简而言之就是MPMoviePlayerController使用更简单,功能不如AVPlayer强大,而AVPlayer使用稍微麻烦点,不过功能更加强大。这篇博客主要介绍下AVPlayer的基本使用,由于博主也是刚刚接触,所以有问题大家直接指出~
在开发中,单纯使用AVPlayer类是无法显示视频的,要将视频层添加至AVPlayerLayer中,这样才能将视频显示出来,所有我们先在@interface中添加以下属性
1.
@property
(nonatomic ,strong) AVPlayer *player;
2.
@property
(nonatomic ,strong) AVPlayerItem *playerItem;<BR>
@property
(nonatomic ,weak) IBOutletPlayerView *playerView;
其中playerView继承自UIView,不过重写了set和get方法,用于将player添加至playerView的AVPlayerLayer中,这样才能顺利将视频显示出来
@property (nonatomic ,strong) AVPlayer *player;
01.
+ (Class)layerClass {
02.
return
[AVPlayerLayer
class
];
03.
}
04.
05.
- (AVPlayer *)player {
06.
return
[(AVPlayerLayer *)[self layer] player];
07.
}
08.
09.
- (
void
)setPlayer:(AVPlayer *)player {
10.
[(AVPlayerLayer *)[self layer] setPlayer:player];
11.
}
在PlayerView.h中声明一个AVPlayer对象,由于默认的layer是CALayer,而AVPlayer只能添加至AVPlayerLayer中,所以我们改变一下layerClass,这样PlayerView的默认layer就变了,之后我们可以把在viewController中初始化的AVPlayer对象赋给AVPlayerLayer的player属性。
然后在viewDidLoad中执行初始化:
1.
NSURL *videoUrl = [NSURL URLWithString:@
"http://www.jxvdy.com/file/upload/201405/05/18-24-58-42-627.mp4"
];
2.
self.playerItem = [AVPlayerItem playerItemWithURL:videoUrl];
3.
[self.playerItem addObserver:self forKeyPath:@
"status"
options:NSKeyValueObservingOptionNew context:nil];
// 监听status属性
4.
[self.playerItem addObserver:self forKeyPath:@
"loadedTimeRanges"
options:NSKeyValueObservingOptionNew context:nil];
// 监听loadedTimeRanges属性
5.
self.player = [AVPlayer playerWithPlayerItem:self.playerItem];<BR>[[NSNotificationCenterdefaultCenter]addObserver:selfselector:
@selector
(moviePlayDidEnd:) name:AVPlayerItemDidPlayToEndTimeNotificationobject:self.playerItem];
先将在线视频链接存放在videoUrl中,然后初始化playerItem,playerItem是管理资源的对象(A player item manages the presentation state of an asset with which it is associated. A player item contains player item tracks—instances of
AVPlayerItemTrack
—that correspond to the tracks in the asset.)然后监听playerItem的status和loadedTimeRange属性,status有三种状态:
AVPlayerStatusUnknown,
AVPlayerStatusReadyToPlay,
AVPlayerStatusFailed
当status等于AVPlayerStatusReadyToPlay时代表视频已经可以播放了,我们就可以调用play方法播放了。
loadedTimeRange属性代表已经缓冲的进度,监听此属性可以在UI中更新缓冲进度,也是很有用的一个属性。
最后添加一个通知,用于监听视频是否已经播放完毕,然后实现KVO的方法:
01.
- (
void
)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(
void
*)context {
02.
AVPlayerItem *playerItem = (AVPlayerItem *)object;
03.
if
([keyPath isEqualToString:@
"status"
]) {
04.
if
([playerItem status] == AVPlayerStatusReadyToPlay) {
05.
NSLog(@
"AVPlayerStatusReadyToPlay"
);
06.
self.stateButton.enabled = YES;
07.
CMTime duration = self.playerItem.duration;
// 获取视频总长度
08.
CGFloat totalSecond = playerItem.duration.value / playerItem.duration.timescale;
// 转换成秒
09.
_totalTime = [self convertTime:totalSecond];
// 转换成播放时间
10.
[self customVideoSlider:duration];
// 自定义UISlider外观
11.
NSLog(@
"movie total duration:%f"
,CMTimeGetSeconds(duration));
12.
[self monitoringPlayback:self.playerItem];
// 监听播放状态
13.
}
else
if
([playerItem status] == AVPlayerStatusFailed) {
14.
NSLog(@
"AVPlayerStatusFailed"
);
15.
}
16.
}
else
if
([keyPath isEqualToString:@
"loadedTimeRanges"
]) {
17.
NSTimeInterval timeInterval = [self availableDuration];
// 计算缓冲进度
18.
NSLog(@
"Time Interval:%f"
,timeInterval);
19.
CMTime duration = self.playerItem.duration;
20.
CGFloat totalDuration = CMTimeGetSeconds(duration);
21.
[self.videoProgress setProgress:timeInterval / totalDuration animated:YES];
22.
}
23.
}
24.
25.
- (NSTimeInterval)availableDuration {
26.
NSArray *loadedTimeRanges = [[self.playerView.player currentItem] loadedTimeRanges];
27.
CMTimeRange timeRange = [loadedTimeRanges.firstObject CMTimeRangeValue];
// 获取缓冲区域
28.
float
startSeconds = CMTimeGetSeconds(timeRange.start);
29.
float
durationSeconds = CMTimeGetSeconds(timeRange.duration);
30.
NSTimeInterval result = startSeconds + durationSeconds;
// 计算缓冲总进度
31.
return
result;
32.
}
33.
34.
- (NSString *)convertTime:(CGFloat)second{
35.
NSDate *d = [NSDate dateWithTimeIntervalSince1970:second];
36.
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
37.
if
(second/
3600
>=
1
) {
38.
[formatter setDateFormat:@
"HH:mm:ss"
];
39.
}
else
{
40.
[formatter setDateFormat:@
"mm:ss"
];
41.
}
42.
NSString *showtimeNew = [formatter stringFromDate:d];
43.
return
showtimeNew;
44.
}
此方法主要对status和loadedTimeRanges属性做出响应,status状态变为AVPlayerStatusReadyToPlay时,说明视频已经可以播放了,这时我们可以获取一些视频的信息,包含视频长度等,把播放按钮设备enabled,点击就可以调用play方法播放视频了。在AVPlayerStatusReadyToPlay的底部还有个monitoringPlayback方法:
1.
- (
void
)monitoringPlayback:(AVPlayerItem *)playerItem {
2.
self.playbackTimeObserver = [self.playerView.player addPeriodicTimeObserverForInterval:CMTimeMake(
1
,
1
) queue:NULL usingBlock:^(CMTime time) {
3.
CGFloat currentSecond = playerItem.currentTime.value/playerItem.currentTime.timescale;
// 计算当前在第几秒
4.
[self updateVideoSlider:currentSecond];
5.
NSString *timeString = [self convertTime:currentSecond];
6.
self.timeLabel.text = [NSString stringWithFormat:@
"%@/%@"
,timeString,_totalTime];
7.
}];
8.
}
monitoringPlayback用于监听每秒的状态,- (id)addPeriodicTimeObserverForInterval:(CMTime)interval queue:(dispatch_queue_t)queue usingBlock:(void (^)(CMTime time))block;此方法就是关键,interval参数为响应的间隔时间,这里设为每秒都响应,queue是队列,传NULL代表在主线程执行。可以更新一个UI,比如进度条的当前时间等。
作为播放器,除了播放,暂停等功能外。还有一个必不可少的功能,那就是显示当前播放进度,还有缓冲的区域,我的思路是这样,用UIProgressView显示缓冲的可播放区域,用UISlider显示当前正在播放的进度,当然这里要对UISlider做一些自定义,代码如下:
01.
- (
void
)customVideoSlider:(CMTime)duration {
02.
self.videoSlider.maximumValue = CMTimeGetSeconds(duration);
03.
UIGraphicsBeginImageContextWithOptions((CGSize){
1
,
1
}, NO,
0
.0f);
04.
UIImage *transparentImage = UIGraphicsGetImageFromCurrentImageContext();
05.
UIGraphicsEndImageContext();
06.
07.
[self.videoSlider setMinimumTrackImage:transparentImage forState:UIControlStateNormal];
08.
[self.videoSlider setMaximumTrackImage:transparentImage forState:UIControlStateNormal];
09.
}
这样UISlider就只有中间的ThumbImage了,而ThumbImage左右的颜色都变成透明的了,仅仅是用于显示当前的播放时间。UIProgressView则用于显示当前缓冲的区域,不做任何自定义的修改,在StoryBoard看起来是这样的:
把UISlider添加至UIProgressView上面,运行起来的效果就变成了这样:
这样基本的缓冲功能就做好了,当然还有一些功能没做,比如音量大小,滑动屏幕快进快退等,大家有时间可以自己做着玩儿下~ 最后的效果如下:
延伸阅读:
- 使用AVPlayer
- AVPlayer使用学习
- AVPlayer的使用
- AVAudioPlayer,AVPlayer 使用
- AVPlayer的基本使用
- AVPlayer的基本使用
- AVPlayer的基本使用
- 使用AVPlayer播放视频
- AVPlayer的使用
- iOS AVPlayer 使用详解
- AVPlayer的基本使用
- AVplayer的使用教程
- AVPlayer的基本使用
- AVPlayer的使用
- avplayer
- AVplayer
- AVPlayer
- AVPlayer
- Dialog对话框参考文章
- 使用py2exe将python 脚本生成exe可执行文件
- LeetCode_41---First Missing Positive
- 07-排序1. 排序(25)
- Linux read系统调用
- 使用AVPlayer
- HTML 头部代码
- 代码片段
- Xamarin 导入 Jar包
- Android设计模式(十四)--适配器模式
- LeetCode 201. Bitwise AND of Numbers Range
- iOS的影片播放 MediaPlayer 和 AVPlayer
- mac版andriod studio 打开即崩溃问题的解决
- CDockablePane使用心得