AVPlayer,播放/暂停状态的通知?

37
我正在寻找一种方法,在AVPlayer开始播放的确切时刻得到通知。有"速率"属性,但目前我正在使用NSTimer定期检查以获取更新。
我尝试了KVO,但显然它不符合KVO标准。
我知道当播放器结束时会有事件。但我在这里谈论暂停。
我还订阅了AVPlayerItem的"状态",但它向我显示HTTP资源何时完成缓存,而不是播放/暂停。我还开始收集所有的播放/暂停调用,请求即时UI更新,但需要一些运行循环才能使AVPlayer真正开始播放。我只想立即更新我的按钮。

这里有一种方法可以监测AVPlayer是否正在播放:https://dev59.com/c2035IYBdhLWcg3wC7if#9288642 - matt.writes.code
7个回答

51

为什么你说“rate”不符合KVO要求?

对我来说它是有效的。

这是我所做的:

- (void)viewDidLoad
{
    ...

    [self.player addObserver:self forKeyPath:@"rate" options:0 context:nil];
}

然后:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:@"rate"]) {
    if ([self.player rate]) {
        [self changeToPause];  // This changes the button to Pause
    }
    else {
        [self changeToPlay];   // This changes the button to Play
    }
}
}

真的吗?你在iOS4或iOS5上尝试过了吗?我会重新测试一下;也许那只是我的错误。 - steipete
3
我尝试在iOS5中使用它。为了让我的观察者被调用,我必须使用选项NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew添加观察者。 - Bianca Daniciuc
1
有没有iOS 10的替代方案? - Aymen HARRATH
@AymenHARRATH 请检查我的iOS 10答案。 - The iCoder
有没有办法区分是谁暂停了它?比如说是用户暂停的,还是我们通过编程暂停的,或者是由于错误而暂停的? - PhoenixB

23

从开始,您可以检查AVPlayer的新属性timeControlStatus

if(avPlayerObject.timeControlStatus==AVPlayerTimeControlStatusPaused)
{
//Paused mode
}
else if(avPlayerObject.timeControlStatus==AVPlayerTimeControlStatusPlaying)
{
 //Play mode
}

7
当它发生变化时,你实际上如何收到通知? - Reimond Hill

6

AVPlayer作为默认的观察者来跟踪视频当前的时长,当你暂停或恢复视频时,你可以使用一个全局变量(在观察者更新中)来获取暂停时间。

CMTime interval = CMTimeMake(1, 1);

//The capture of self here is coming in with your implicit property access of self.currentduration - you can't refer to self or properties on self from within a block that will be strongly retained by self.

//You can get around this by creating a weak reference to self before accessing timerDisp inside your block
__weak typeof(self) weakSelf = self;

self.timeObserverToken = [_player addPeriodicTimeObserverForInterval:interval queue:NULL usingBlock: ^(CMTime time)
{
    _currentDuration = (int)CMTimeGetSeconds (_player.currentTime);

    if(!_isPlaying)
    {
        _pausedDuration = _currentDuration;
    }
}

5
如果你的目标是 iOS 13 及以上版本,你可以优雅地使用 Combine 来完成此操作。
cancellable = myAVPlayerInstance.publisher(for: \.timeControlStatus)
    .sink { [unowned self] status in
       ...
    }

其中statusAVPlayer.TimeControlStatus的任何一个case


3
    player = AVPlayer(url: URL(fileURLWithPath: path))
player.addObserver(self, forKeyPath: "rate", options: NSKeyValueObservingOptions.new, context: nil)

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if keyPath == "rate" {
        if player.rate > 0 {
            print("video started")
        }
    }
}

在Swift中

1

向您的AVPlayer对象的rate值添加观察者:

player.addObserver(self, forKeyPath: "rate", options: [], context: nil)

覆盖将在 rate 更改时调用的方法:

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if keyPath == "rate", let player = object as? AVPlayer {
        if player.rate == 1 {
            print("Playing")
        } else {
            print("Paused")
        }
    }
}

0
需要向 AVPlayer 对象的 rate 值添加观察者:
player?.addObserver(self, forKeyPath: "rate", options: NSKeyValueObservingOptions.new, context: nil)

重写以下方法以观察rate属性的变化

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if keyPath == "rate" {
        if let status = player?.timeControlStatus {
            switch status{
            case .paused:
                //Paused mode
                print("paused")
            case .waitingToPlayAtSpecifiedRate:
                //Resumed
                print("resumed")
            case .playing:
                //Video Ended
                print("ended")
            @unknown default:
                print("For future versions")
            }
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接