CMTime和AVFoundation中的单帧移动

我试图用AVFoundation播放video。 我正在使用下面的代码为一个button提前播放一帧。

它间歇地工作,在一些执行中,它会做正确的事情,并提前一帧,但大多数时间,我将不得不按下button3或4次,才会推进一个框架。

这让我觉得这是一个精确的问题,但我无法弄清楚它是什么。 每次运行时,新的CMTime似乎都以相同的数量前进。

我的另一个理论是,它可能是由于currentTime没有被设置为一个精确的帧边界在我的帧速率(通过寻找video)。 但是我不知道如何以我的帧率“捕捉”到最近的帧。

AVAssetTrack *videoTrack = ...; Float64 frameRate = [videoTrack nominalFrameRate]; CMTime currentTime = [self.playerItem currentTime]; CMTime oneFrame = CMTimeMakeWithSeconds(1.0 / frameRate, currentTime.timescale); CMTime added = CMTimeAdd(currentTime, oneFrame); [self.player seekToTime:added toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero]; 

谢谢你的帮助!

你的问题的答案是在第二行代码中你从nominalFrameRate中删除“名义”。

您的代码假设您的video中的帧频是不变的。 这是不正确的。

video可以有一个固定的FPS,但不一定。 例如,如果您在可变光照条件下使用手机拍摄电影,则曝光时间可能会改变,帧频也会相反。

要“捕捉”到帧边界,您需要使用AVAssetReader来遍历各个帧。 每个框架标有一个演示时间标记(它的“t”),但如果你正在步进那并不重要,除非你正在更新一个位置标记。

这不是很明显(因为奇怪,它只在AVPlayerItem而不是AVPlayer中可用),但是如果AVPlayerItem为canStepForward/canStepBackward返回YES,则可以调用stepByCount:(NSInteger)stepCount:向前或向后移动一定数量的帧。