我正在尝试使用AVPlayer
到UISlider
进行流畅的视频清理我已搜索过,似乎Apple有一个Technical Q&A并解释了如何实现这一目标,但我的问题是应该怎样我使用此方法并使用UISlider更改玩家当前时间:
stopPlayingAndSeekSmoothlyToTime(newChaseTime:CMTime)
这是我的代码:
//Play Intro Movie
let videoURL = Bundle.main.url(forResource: "intro", withExtension: "mp4")
player = AVPlayer(url:videoURL!)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = self.view.frame
view.layer.addSublayer(playerLayer)
//videoPlayer.play()
view.addSubview(slider)
slider.maximumValue = 0
slider.maximumValue = Float(CMTimeGetSeconds((player.currentItem?.asset.duration)!))
以下是Apple示例代码:
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.seek(to: seekTimeInProgress, toleranceBefore: kCMTimeZero,
toleranceAfter: kCMTimeZero, completionHandler:
{ (isFinished:Bool) -> Void in
if CMTimeCompare(seekTimeInProgress, self.chaseTime) == 0
{
self.isSeekInProgress = false
}
else
{
self.trySeekToChaseTime()
}
})
}
答案 0 :(得分:4)
在滑块值更改事件中,只需调用
即可 stopPlayingAndSeekSmoothlyToTime(CMTime.init(seconds: (player.currentItem?.asset.duration.seconds)!* slider.value, preferredTimescale: 1000))
Apples示例代码将更改播放器当前时间。如果你非常快速地擦洗滑块,你也可以调整toleranceBefore和toleranceAfter。
答案 1 :(得分:4)
虽然我没有使用与你stopPlayingAndSeekSmoothlyToTime
相同的方法,但我认为我应该帮助你寻找玩家的行动。
func sliderValueChanged() {
var timeToSeek = player.currentItem?.asset.duration.seconds
timeToSeek = timeToSeek * Double(slider.value)
player.seek(to: CMTimeMake(Int64(timeToSeek), 1))
}
此外,您应该将slider.maximumValue
设置为1.希望这会有所帮助。
注意:请不要忘记处理currentItem
可选值。如果是nil
,则应为timeToSeek
变量设置值0。
答案 2 :(得分:2)
尝试在开头添加选择器,如下所示:
playerView.timeSlider.addTarget(self, action: #selector(PlayerViewController.timeSliderBeganTracking(_:)), for:.touchDown) // moved
playerView.timeSlider.addTarget(self, action: #selector(PlayerViewController.timeSliderEndedTracking(_:)), for: .touchUpInside)
playerView.timeSlider.addTarget(self, action: #selector(PlayerViewController.timeSliderEndedTracking(_:)), for: .touchUpOutside )
然后在timeSliderBeganTracking
设置isSeekInProgress
到true
并暂停您的播放器并使计时器无效并删除观察员(如果您有)
然后在timeSliderEndedTracking
寻求当前这样的时间:
let currentSeconds = Float64(self.playerView.timeSlider.value)
container.player.seek(to: CMTimeMakeWithSeconds(currentSeconds, 100))
然后将观察者和计时器添加回来,最后将isSeekInProgress
设置为false
HERE您可以找到创建自定义videoPlayer的完整示例
答案 3 :(得分:0)
我知道这是一个老问题,我也遇到过。该解决方案现在可以帮助某人。苹果样品使滑块超级光滑漂亮。要使示例工作:
private static var context = 1
func playVideo() {
...
player.addObserver(self, forKeyPath: #keyPath(AVPlayer.currentItem.status), options: [.new, .initial], context: &VideoViewController.context)
...
}
override public func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
guard let keyPath = keyPath else { return }
guard context == &VideoViewController.context else { return }
switch keyPath {
case #keyPath(AVPlayer.currentItem.status):
if let newStatus = change.map({ $0[.newKey] as? NSNumber }),
let parsedNewStatus = newStatus.map({ AVPlayerItem.Status(rawValue: $0.intValue) ?? .unknown}) {
playerCurrentItemStatus = parsedNewStatus
} else {
playerCurrentItemStatus = .unknown
}
default: break
}
}
观察并更新playerCurrentItemStatus