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

发布于 2024-12-06 17:03:33 字数 563 浏览 0 评论 0原文

我正在寻找一种方法来在 AVPlayer 开始播放的确切时刻收到通知。有“rate”属性,但目前我正在使用 NSTimer 定期检查它以获取更新。

我尝试了 KVO,但显然它不符合 KVO 标准。

我知道有事件播放器已结束。但我在这里谈论的是暂停。

我还通过 KVO 订阅了 AVPlayerItem 的“状态”,但它向我显示 HTTP 资源何时完成缓存,没有播放/暂停。我还开始收集所有播放/暂停的调用,然后请求即时 UI 更新,但在 AVPlayer 真正开始播放之前需要更多的运行循环。我只想立即更新我的按钮。

I'm searching for a way to get notified the exact moment when AVPlayer starts playing. There's the "rate" property, but currently I am checking it periodically with an NSTimer to get updates.

I tried KVO, but apparently it's not KVO compliant.

I know that there are events when the player ENDED. But i'm talking about pause here.

I also KVO subscribed to AVPlayerItem's "status", but it's showing me when the HTTP asset has finished caching, no play/pause. I also started collecting all calls of play/pause, requesting an instant UI update afterwards, but it takes some more runloops before AVPlayer really starts playing. I'd just love to update my button instantly.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

一杯敬自由 2024-12-13 17:03:34
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")
    }
  }
}

迅速

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

in swift

时间海 2024-12-13 17:03:34

将观察者添加到 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")
        }
    }
}

Add an observer to your AVPlayer object's rate value:

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

And override the method that will be called when the rate changes:

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")
        }
    }
}
┾廆蒐ゝ 2024-12-13 17:03:34

需要向 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")
            }
        }
    }
}

Need to add an observer to AVPlayer object's rate value:

player?.addObserver(self, forKeyPath: "rate", options: NSKeyValueObservingOptions.new, context: nil)

Override below method to observe changes in rate property

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")
            }
        }
    }
}
年少掌心 2024-12-13 17:03:33

为什么说“率”不是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
    }
}
}

Why do you say that "rate" is not KVO complaint?
It works for me.

Here is what I did:

- (void)viewDidLoad
{
    ...

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

And then:

- (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
    }
}
}
橘味果▽酱 2024-12-13 17:03:33

对于 iOS 10 及以上版本,您可以检查 AVPlayer timeControlStatus 的新属性。

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

For iOS 10 onwards You can check new property of AVPlayer timeControlStatus.

if(avPlayerObject.timeControlStatus==AVPlayerTimeControlStatusPaused)
{
//Paused mode
}
else if(avPlayerObject.timeControlStatus==AVPlayerTimeControlStatusPlaying)
{
 //Play mode
}
想挽留 2024-12-13 17:03:33

AVPalyer 作为默认观察者来跟踪视频的当前持续时间,当您暂停或恢复视频时,您可以通过使用一个全局变量来获取暂停时间(观察者内部更新该变量)

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;
    }
}

AVPalyer as default observer to track the current duration of the video ,when you pause or resume the video you can get paused time by using one global variable (inside observer update that variable)

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;
    }
}
风轻花落早 2024-12-13 17:03:33

如果您的目标是 iOS 13 及更高版本,则可以使用 Combine 优雅地实现此目的:

cancellable = myAVPlayerInstance.publisher(for: \.timeControlStatus)
    .sink { [unowned self] status in
       ...
    }

其中 statusAVPlayer 的任何 case .TimeControlStatus

If you're targeting iOS 13 and up, you can pull this off elegantly using Combine:

cancellable = myAVPlayerInstance.publisher(for: \.timeControlStatus)
    .sink { [unowned self] status in
       ...
    }

where status is any case of AVPlayer.TimeControlStatus

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文