7

我正在尝试使用 AVFoundation 播放视频。我将以下代码用于将播放推进一帧的按钮。

它间歇性地工作,在某些执行中它会做正确的事情并推进一帧,但大多数时候我必须按下按钮 3 或 4 次才能推进一帧。

这让我认为这是某种精度问题,但我无法弄清楚它是什么。每次运行时,新的 CMTime 似乎都以相同的量前进。

我的另一个理论是,这可能是由于 currentTime 没有以我的帧速率设置为精确的帧边界(由通过视频搜索引起)。但我不知道如何以我的帧速率“捕捉”到最近的帧。

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

谢谢你的帮助!

4

2 回答 2

5

您的问题的答案在您从nominalFrameRate 中删除“标称”的第二行代码中。

您的代码假定视频中的帧速率是恒定的。这是不正确的。

视频可以具有恒定的 fps,但并非必须如此。例如,如果您在可变光照条件下使用手机拍摄电影,那么帧曝光时间可能会发生变化,而您的帧速率也会发生相反的变化。

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

于 2011-06-24T22:14:33.323 回答
5

It isn't very obvious (since strangely it's only available in AVPlayerItem rather than AVPlayer) but if the AVPlayerItem returns YES for canStepForward/canStepBackward then you can call stepByCount:(NSInteger)stepCount: to move forwards or backwards by a certain number of frames.

于 2013-10-11T19:37:43.587 回答