本文介绍了在AVPlayerLooper上更新timeRange属性的推荐方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我基于 AVPlayerLooper示例代码 Apple提供了,特别是利用了他们在PlayerLooper.swiftLooperViewController.swiftLooper.swift协议中为您提供的示例AVPlayerLooper设置.

I am building off of the AVPlayerLooper example code Apple provides, specifically utilizing the example AVPlayerLooper setup they've given you in PlayerLooper.swift, LooperViewController.swift, and the Looper.swift protocol.

我想做的是能够更新在PlayerLooper.swift文件中实例化的AVPlayerLooper上的timeRange属性.

What I would like to do is be able to update the timeRange property on the AVPlayerLooper that is instantiated inside of the PlayerLooper.swift file.

为此,我对以下函数进行了一些修改,该函数实例化并启动了播放器循环程序:

To this end, I have slightly modified the following function which instantiates and starts the player looper:

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()
            })
        })
    }

出于演示目的,在LooperViewController中,我创建了一个简单的按钮,使用新的CMTimeRange触发looper?.start(),如下所示:

For demonstration purposes, in LooperViewController, I created a simple button that triggers looper?.start() with a new CMTimeRange like so:

looper?.start(in: view.layer, loopTimeRange: CMTimeRange(start: CMTime(value: 0, timescale: 600), duration: CMTime(value: 3000, timescale: 600)))

但是,在调用该函数之前,我会调用looper?.stop(),它会执行以下操作:

Before that function is called, however, I call looper?.stop(), which does the following:

func stop() {
        player?.pause()
        stopObserving()

        playerLooper?.disableLooping()
        playerLooper = nil

        playerLayer?.removeFromSuperlayer()
        playerLayer = nil

        player = nil
    }

我基本上是完全重新实例化AVPlayerLooper以便设置新的timeRange属性,因为在第一次设置后,我看不到任何实际访问和重置该属性的方法.

I'm basically completely re-instantiating the AVPlayerLooper in order to set the new timeRange property because I don't see any way to actually access, and reset, that property once it's been setup the first time.

问题在于,尽管这似乎最初可行,并且循环播放器播放器将进行调整并开始循环播放新的时间范围,但最终会在循环几次之后停止播放.没有任何地方抛出错误,并且代码中已经设置的观察者都没有报告该循环正在停止或该循环存在一些错误.

The problem is that, while this seems to initially work and the looper player will adjust and start looping the new timerange, it will eventually just stop playing after a few loops. No errors are thrown anywhere, and none of the observers that are already setup in the code are reporting that the loop is stopping or that there was some error with the loop.

我的方法完全错误吗?是要以这种方式调整AVPlayerLooper,还是我应该寻找另一种方法来拥有可调整的循环播放器?

Is my approach here entirely wrong? Is AVPlayerLooper meant to be adjusted in this way or should I look for another approach to having an adjustable looping player?

推荐答案

您实际上可以更新AVPlayerLooper而不用拆散整个内容.您需要做的是先从AVQueuePlayer中删除所有项目,然后用新的时间范围重新初始化弯针.像这样:

You can actually update the AVPlayerLooper without tearing down the whole thing. What you need to do is to remove all items from the AVQueuePlayer first and then reinstantiate the looper with the new time range. Something like this:

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(),否则它将崩溃.否则,这将更改时间范围,同时允许您使用当前图层等设置来查看播放器.

You must be sure to removeAllItems() or it will crash. Otherwise this will change the time range while allowing you to use the current layer, etc., setup to view the player.

这篇关于在AVPlayerLooper上更新timeRange属性的推荐方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-12 23:51