AVPlayer 的 addPeriodicTimeObserverForInterval 中的 CMTime:回调永远不会达到项目的持续时间

Posted

技术标签:

【中文标题】AVPlayer 的 addPeriodicTimeObserverForInterval 中的 CMTime:回调永远不会达到项目的持续时间【英文标题】:CMTime in AVPlayer's addPeriodicTimeObserverForInterval: callback never reaches item's duration 【发布时间】:2016-06-22 19:12:36 【问题描述】:

我使用 AVPlayer 的 -(id)addPeriodicTimeObserverForInterval: queue: usingBlock: 方法将 UI 更新到播放进度。但是,我的进度条永远不会结束。

CMTime duration = self.player.currentItem.asset.duration;
float totalSeconds = (Float64)(duration.value * 1000) / (Float64)(duration.timescale);
NSLog(@"duration: %.2f", totalSeconds);

__weak __typeof(self) welf = self;

_mTimeObserver = [self.player addPeriodicTimeObserverForInterval:CMTimeMake(10, 1000)
                                              queue:NULL // main queue
                                         usingBlock:^(CMTime time) 

  float totalSeconds = (Float64)(time.value * 1000) / (Float64)(time.timescale);
  NSLog(@"progress %f", totalSeconds);

                                                ];

日志:

App[2373:792179] duration: 3968.00

点击播放按钮

App[2373:792179] progress 0011.176
App[2373:792179] progress 0021.175
...
App[2373:792179] progress 3701.319
App[2373:792179] progress 3704.000

我不应该期望最后一个数字是3968.0 吗?

音频从服务器流式传输。

编辑

最后的进度编号是 ALWAYS duration - 0.264 sec 无论实际持续时间长度是多少。

这太奇怪了,我希望我们可以在 SO 上使用表情符号。

【问题讨论】:

【参考方案1】:

好问题。尝试使用CMTimeGetSeconds(time) 而不是自己计算总秒数。

另外,尝试使用CMTimeMakeWithSeconds(10.0, NSEC_PER_SEC) 为周期性时间观察器创建时间。

这篇文章帮助我理解了 CMTime 的谜团:https://warrenmoore.net/understanding-cmtime

【讨论】:

相同的东西(其他声音):duration:4.736 maxProgress:4.472。可能是什么原因?编辑:刚刚看到你更新的答案,我会尝试其他选项 @kerd 这很有趣。您还可以使用CMTimeGetSeconds 打印持续时间吗?还有一件事:尝试更细粒度的回调值。尝试1.0/30.0,而不是 10 秒。 在第一条评论中,我写了来自CMTimeGetSeconds 的结果。抱歉,如果不清楚。此外,我尝试过的 CMTimeMakeWithSeconds(10.0, NSEC_PER_SEC) 是最好的颗粒——它花了 10 纳秒,而不是我在原始帖子中使用的 0.01 秒。 试试CMTimeMakeWithSeconds(1.0/30.0, NSEC_PER_SEC)。在您的第一条评论中,maxProgress 低于持续时间。问题是 高于 比持续时间。所以可能是回调没有触发,因为它不够细粒度。 @kerd 实际上检查CMTimeGetSeconds(self.player.currentTime) 比使用传入的time 更准确,因为这实际上是调用块的时间。【参考方案2】:

文档明确指出:

只要您希望播放器调用时间观察器,就必须保留返回的值。

【讨论】:

抱歉,您能否协助进一步了解这些信息如何提供帮助?顺便说一句,观察者不是已经被调用了吗? 他的意思是你需要持有对观察者对象的强引用,否则它将被释放。例如,您的 UIViewController 可能有一个名为 playerTimeObserver 的属性。

以上是关于AVPlayer 的 addPeriodicTimeObserverForInterval 中的 CMTime:回调永远不会达到项目的持续时间的主要内容,如果未能解决你的问题,请参考以下文章

AVPlayer 类事件

AVPlayer + 循环 + 背景

AVPlayer 问题,同时直播 (iOS)

带有 AVPlayer 的 AVAudioSession:当 AVPlayer 播放器正在播放时,状态菜单中的“播放”图标不显示

AVPlayer

带有自定义 UITableViewCell 的 AVPlayer