iOS解码videoFile.mp4时如何获取每帧的毫秒级时间戳
获取AVAssetReader解码帧的毫秒级时间戳
嘿,我刚好做过不少iOS视频解码的相关工作,这个问题其实很容易解决——你拿到的CMSampleBufferRef本身就包含了帧的时间戳信息,只需要几步就能转换成你需要的毫秒级数值。
核心步骤说明
从SampleBuffer中提取时间戳
AVFoundation提供了专门的函数来获取帧的展示时间戳(也就是这帧视频应该被显示的时间点):CMSampleBufferGetPresentationTimeStamp()。它会返回一个CMTime类型的对象,这是AVFoundation中标准的时间表示方式,用分子(value)和分母(timescale)来精确表示时间。将CMTime转换为毫秒级数值
有两种常用的转换方式,你可以根据需求选择:- 方式一:先转成秒数再乘以1000,简单直观,适合大多数场景。
- 方式二:直接用CMTime的value和timescale计算,能避免浮点数带来的微小误差,适合对精度要求极高的场景。
结合你的代码的完整示例
AVAssetReader *videoFileReader; AVAssetReaderTrackOutput *assetReaderOutput = [videoFileReader.outputs objectAtIndex:0]; CMSampleBufferRef sampleBuffer = [assetReaderOutput copyNextSampleBuffer]; if (sampleBuffer) { // 获取当前帧的展示时间戳(CMTime格式) CMTime framePresentationTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer); // 方式1:转换成毫秒级时间戳(简单直观) double timestampMs = CMTimeGetSeconds(framePresentationTime) * 1000.0; NSLog(@"当前帧毫秒时间戳:%.2f", timestampMs); // 方式2:高精度计算(避免浮点数误差) // int64_t preciseTimestampMs = (int64_t)((double)framePresentationTime.value / framePresentationTime.timescale * 1000.0); // NSLog(@"高精度毫秒时间戳:%lld", preciseTimestampMs); // 重要:使用完sampleBuffer后必须手动释放,防止内存泄漏 CFRelease(sampleBuffer); }
额外注意事项
- 如果你需要的是解码时间戳(即帧被解码完成的时间),可以用
CMSampleBufferGetDecodeTimeStamp()替代展示时间戳,但绝大多数业务场景下,展示时间戳才是你需要的。 - 别忘了一定要调用
CFRelease(sampleBuffer),因为copyNextSampleBuffer返回的是需要手动管理内存的对象,不释放会导致内存泄漏。
内容的提问来源于stack exchange,提问作者TheWaterProgrammer




