在 iOS 中不使用播放方法显示视频帧

Showing video frames without using play method in iOS

我想了解视频文件中 CMTime 和 fps 的功能。我正在尝试使用 for 循环在 AVPlayer 中呈现视频的每一帧。我知道使用 AVPlayer 的播放方法可以轻松完成此任务。但我想知道帧是如何显示的。我创建了一个 for 循环,并尝试通过不断更新 AVPlayer 的 seekToTime 方法来逐帧呈现每一帧。我能够开发一个解决方案,但它没有显示所有帧,而且视频看起来不稳定。

这是我的代码:

for(float t=0; t < asset.duration.value; t++)
{
    CMTime tt = CMTimeMake(t, asset.duration.timescale);
    [self.player seekToTime:tt];
    NSLog(@"%lld, %d",tt.value, tt.timescale);
}

这里,player 是AVPlayer 的实例,asset 是我要呈现其帧的视频资产。 我也尝试过使用 CMTimeMakeSeconds(t, asset.duration.timescale),但没有用。

请提出您的建议。 谢谢。

每秒帧数在视频文件中通常不是一个常量 - 帧数在发生时发生。如果您想知道那是什么时候,您可以使用 AVAssetReaderAVAssetReaderTrackOutput 类 检查帧的显示时间戳:

let reader = try! AVAssetReader(asset: asset)

let videoTrack = asset.tracksWithMediaType(AVMediaTypeVideo)[0]
let trackReaderOutput = AVAssetReaderTrackOutput(track: videoTrack, outputSettings:nil)

reader.addOutput(trackReaderOutput)
reader.startReading()

while let sampleBuffer = trackReaderOutput.copyNextSampleBuffer() {
    // pts shows when this frame is presented
    // relative to the start of the video file
    let pts = CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
}

在您的代码中,您错误地对视频时间轴进行了采样。以下是如何以 30 fps 对其进行采样(如上所述,这可能与实际帧边界不对应):

for (CMTime t = kCMTimeZero; CMTimeCompare(t, asset.duration) < 0;  t = CMTimeAdd(t, CMTimeMake(1, 30))) {
    [player seekToTime:t];
}