AVPlayer开始播放后立即寻找
AVPlayer seek right after it starts to play
我需要在音频文件开始播放后立即跳转到特定时间。所以我将 seekToTime 方法与完成处理程序一起使用
avPlayer.play()
...
avPlayer?.seekToTime(jumpTime, completionHandler: { isComplete in
if isComplete {
MPNowPlayingInfoCenter.defaultCenter().nowPlayingInfo![MPNowPlayingInfoPropertyElapsedPlaybackTime] = CMTimeGetSeconds((self.avPlayer!.currentItem?.currentTime())!)
}
})
问题是开始播放来自互联网的文件需要时间。由于某种原因,带有完成处理程序的 seekToTime 版本使应用程序崩溃,因为它是在 avPlayer 开始播放之前调用的。没有完成处理程序的版本工作正常。
错误:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'AVPlayerItem cannot service a seek request with a completion handler until its status is AVPlayerItemStatusReadyToPlay.'
有没有办法通过 avPlayer.play()
使用回调?
是的,有办法。
您需要观察播放器的变化:
avPlayer?.addPeriodicTimeObserverForInterval(CMTime(value: 1, timescale: 3), queue: dispatch_get_main_queue()) { [weak self] time in
self?.handleCallback(time)
}
然后你处理回调中的状态:
func handleCallback(time: CMTime) {
if avPlayer?.status == .ReadyToPlay {
// place your seek logic here
}
}
请看苹果的回答:
https://developer.apple.com/library/content/qa/qa1820/_index.html
class MyClass {
var isSeekInProgress = false
let player = <#A valid player object #>
var chaseTime = kCMTimeZero
// your player.currentItem.status
var playerCurrentItemStatus:AVPlayerItemStatus = .Unknown
...
func stopPlayingAndSeekSmoothlyToTime(newChaseTime:CMTime)
{
player.pause()
if CMTimeCompare(newChaseTime, chaseTime) != 0
{
chaseTime = newChaseTime;
if !isSeekInProgress
{
trySeekToChaseTime()
}
}
}
func trySeekToChaseTime()
{
if playerCurrentItemStatus == .Unknown
{
// wait until item becomes ready (KVO player.currentItem.status)
}
else if playerCurrentItemStatus == .ReadyToPlay
{
actuallySeekToTime()
}
}
func actuallySeekToTime()
{
isSeekInProgress = true
let seekTimeInProgress = chaseTime
player.seekToTime(seekTimeInProgress, toleranceBefore: kCMTimeZero,
toleranceAfter: kCMTimeZero, completionHandler:
{ (isFinished:Bool) -> Void in
if CMTimeCompare(seekTimeInProgress, chaseTime) == 0
{
isSeekInProgress = false
}
else
{
trySeekToChaseTime()
}
})
}
}
我需要在音频文件开始播放后立即跳转到特定时间。所以我将 seekToTime 方法与完成处理程序一起使用
avPlayer.play()
...
avPlayer?.seekToTime(jumpTime, completionHandler: { isComplete in
if isComplete {
MPNowPlayingInfoCenter.defaultCenter().nowPlayingInfo![MPNowPlayingInfoPropertyElapsedPlaybackTime] = CMTimeGetSeconds((self.avPlayer!.currentItem?.currentTime())!)
}
})
问题是开始播放来自互联网的文件需要时间。由于某种原因,带有完成处理程序的 seekToTime 版本使应用程序崩溃,因为它是在 avPlayer 开始播放之前调用的。没有完成处理程序的版本工作正常。
错误:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'AVPlayerItem cannot service a seek request with a completion handler until its status is AVPlayerItemStatusReadyToPlay.'
有没有办法通过 avPlayer.play()
使用回调?
是的,有办法。
您需要观察播放器的变化:
avPlayer?.addPeriodicTimeObserverForInterval(CMTime(value: 1, timescale: 3), queue: dispatch_get_main_queue()) { [weak self] time in
self?.handleCallback(time)
}
然后你处理回调中的状态:
func handleCallback(time: CMTime) {
if avPlayer?.status == .ReadyToPlay {
// place your seek logic here
}
}
请看苹果的回答: https://developer.apple.com/library/content/qa/qa1820/_index.html
class MyClass {
var isSeekInProgress = false
let player = <#A valid player object #>
var chaseTime = kCMTimeZero
// your player.currentItem.status
var playerCurrentItemStatus:AVPlayerItemStatus = .Unknown
...
func stopPlayingAndSeekSmoothlyToTime(newChaseTime:CMTime)
{
player.pause()
if CMTimeCompare(newChaseTime, chaseTime) != 0
{
chaseTime = newChaseTime;
if !isSeekInProgress
{
trySeekToChaseTime()
}
}
}
func trySeekToChaseTime()
{
if playerCurrentItemStatus == .Unknown
{
// wait until item becomes ready (KVO player.currentItem.status)
}
else if playerCurrentItemStatus == .ReadyToPlay
{
actuallySeekToTime()
}
}
func actuallySeekToTime()
{
isSeekInProgress = true
let seekTimeInProgress = chaseTime
player.seekToTime(seekTimeInProgress, toleranceBefore: kCMTimeZero,
toleranceAfter: kCMTimeZero, completionHandler:
{ (isFinished:Bool) -> Void in
if CMTimeCompare(seekTimeInProgress, chaseTime) == 0
{
isSeekInProgress = false
}
else
{
trySeekToChaseTime()
}
})
}
}