我正在构建AVPlayerLooper example code Apple提供的功能,专门利用他们在/account#/profile
,PlayerLooper.swift
和LooperViewController.swift
协议中为您提供的示例AVPlayerLooper设置。
我想要做的是能够更新在PlayerLooper.swift文件中实例化的AVPlayerLooper上的timeRange属性。
为此,我稍微修改了以下函数,该函数实例化并启动播放器looper:
Looper.swift
出于演示目的,在func start(in parentLayer: CALayer, loopTimeRange: CMTimeRange) {
player = AVQueuePlayer()
playerLayer = AVPlayerLayer(player: player)
guard let playerLayer = playerLayer else { fatalError("Error creating player layer") }
playerLayer.frame = parentLayer.bounds
parentLayer.addSublayer(playerLayer)
let playerItem = AVPlayerItem(url: videoURL)
playerItem.asset.loadValuesAsynchronously(forKeys: [ObserverContexts.playerItemDurationKey], completionHandler: {()->Void in
/*
The asset invokes its completion handler on an arbitrary queue when
loading is complete. Because we want to access our AVPlayerLooper
in our ensuing set-up, we must dispatch our handler to the main queue.
*/
DispatchQueue.main.async(execute: {
guard let player = self.player else { return }
var durationError: NSError? = nil
let durationStatus = playerItem.asset.statusOfValue(forKey: ObserverContexts.playerItemDurationKey, error: &durationError)
guard durationStatus == .loaded else { fatalError("Failed to load duration property with error: \(String(describing: durationError))") }
//self.playerLooper = AVPlayerLooper(player: player, templateItem: playerItem)
self.playerLooper = AVPlayerLooper(player: player, templateItem: playerItem, timeRange: loopTimeRange)
self.startObserving()
player.play()
})
})
}
中,我创建了一个简单的按钮,使用新的CMTimeRange触发LooperViewController
,如下所示:
looper?.start()
然而,在调用该函数之前,我调用looper?.start(in: view.layer, loopTimeRange: CMTimeRange(start: CMTime(value: 0, timescale: 600), duration: CMTime(value: 3000, timescale: 600)))
,它执行以下操作:
looper?.stop()
我基本上完全重新实例化AVPlayerLooper以设置新的timeRange属性,因为我没有看到任何方法在第一次设置后实际访问和重置该属性。
问题在于,虽然这似乎最初有效并且弯针玩家将调整并开始循环新的时间范围,但它最终会在几个循环之后停止播放。在任何地方都不会抛出任何错误,并且代码中已经设置的观察者都没有报告循环正在停止或者循环有错误。
我的方法完全错了吗? AVPlayerLooper是否意味着要以这种方式进行调整,还是应该寻找另一种方法来设置可调节的循环播放器?
答案 0 :(得分:1)
您实际上可以更新AVPlayerLooper
,而无需拆除整个内容。您需要做的是先从AVQueuePlayer
中删除所有项目,然后使用新的时间范围重新初始化循环器。像这样:
if self.avQueuePlayer.rate == 0 {
self.avQueuePlayer.removeAllItems()
let range = CMTimeRange(start: self.startTime, end: self.endTime)
self.avPlayerLooper = AVPlayerLooper(player: self.avQueuePlayer, templateItem: self.avPlayerItem, timeRange: range)
self.avQueuePlayer.play()
}
您必须确定要removeAllItems()
,否则它将崩溃。否则,这将更改时间范围,同时允许您使用当前图层等设置来查看播放器。