音频及视频播放:
效果图:
实现思路:
1:利用AVPlayer和AVPlayerItem实现音频播放器,
let url = NSURL(string: vocieModel!.voiceuri!)!
songItem = AVPlayerItem(URL: url)
player = AVPlayer(playerItem: songItem!)
player.play()
2:开始播放后获取播放进度,利用
addPeriodicTimeObserverForInterval
方法获取当前播放的音频时间,从服务器获取音频总时长,将比值设置给进度条,这就实现了显示进度条功能
weak var weakSelf = self
//监听播放进度 每到一定时间都会回调一次
PeriodicTime = player.addPeriodicTimeObserverForInterval(CMTimeMake(1, 1), queue:dispatch_get_main_queue()) { (CMTime time) -> Void in
//获取当前秒数
let current = CMTimeGetSeconds(time);
let total = CMTimeGetSeconds(weakSelf!.songItem!.duration);
weakSelf!.progress.setValue(Float(current)/Float(total), animated: true)
weakSelf!.time.text = NSString(format: "%02ld:%02ld", Int(current)/60,Int(current)%60) as String
let arr = (self.songItem!.loadedTimeRanges) as NSArray
//本次缓冲的时间范围
let cmTime = (arr.firstObject?.CMTimeRangeValue)! as CMTimeRange
//
let totalBuffer = CMTimeGetSeconds(cmTime.start) + CMTimeGetSeconds(cmTime.duration) as NSTimeInterval //缓冲总长度
// progress.
XYDEBUG("共缓冲\(NSString(format: "%.2f", totalBuffer))")
}
3:监听播放完成的通知
监听的对象就是AVPlayerItem,在相应方法中移除对象,隐藏按钮和正在播放时间
// 监听AVPlayer播放完成通知
XYNotification.addObserver(self, selector: "playbackFinish:", name: AVPlayerItemDidPlayToEndTimeNotification, object: songItem)
我的进度条就是UISlider控件显示的,这里我是在该控件上添加一个拖动手势
UIPanGestureRecognizer。然后监听手势拖动方法,
//拖动的时候,计算比例
func progressVaule(sender: UIGestureRecognizer) {
// 1.获取点击的位置
let locat = sender.locationInView(sender.view)
// 2.获取点击的在slider长度中占据的比例
let ratio = locat.x / self.progress.bounds.size.width;
// 3.改变歌曲播放的时间
let cd = CMTimeGetSeconds(songItem!.duration)
//音频跳转指定位置
songItem?.seekToTime(CMTimeMake(Int64(CGFloat(cd) * ratio), 1), completionHandler: { (Bool bool) -> Void in
self.player.play()
})
}
到这就能实现一个音频播放了,
注:AVPlayerItem可以利用KVO机制获取音频加载状态、缓冲状态
代码如下:
// kvo 媒体加载状态
songItem!.addObserver(self, forKeyPath: "status", options: .New, context: nil)
// kvo 数据缓冲状态
songItem!.addObserver(self, forKeyPath: "loadedTimeRanges", options: .New, context: nil)
// KVO方法中获取其status的改变
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer) {
let songAv = object as? AVPlayerItem
if (keyPath == "status"){
switch player.status{
case .ReadyToPlay :
XYDEBUG("播放")
player.play()
break
case .Failed :
XYDEBUG("Failed")
break
case .Unknown :
XYDEBUG("未知状态")
break
}
}else if(keyPath == "loadedTimeRanges"){
let arr = (songAv?.loadedTimeRanges)! as NSArray
// //本次缓冲的时间范围
let cmTime = (arr.firstObject?.CMTimeRangeValue)! as CMTimeRange
//
let totalBuffer = CMTimeGetSeconds(cmTime.start) + CMTimeGetSeconds(cmTime.duration) as NSTimeInterval //缓冲总长度
// progress.
XYDEBUG("共缓冲\(NSString(format: "%.2f", totalBuffer))")
}
}