You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

iOS解码videoFile.mp4时如何获取每帧的毫秒级时间戳

获取AVAssetReader解码帧的毫秒级时间戳

嘿,我刚好做过不少iOS视频解码的相关工作,这个问题其实很容易解决——你拿到的CMSampleBufferRef本身就包含了帧的时间戳信息,只需要几步就能转换成你需要的毫秒级数值。

核心步骤说明

  1. 从SampleBuffer中提取时间戳
    AVFoundation提供了专门的函数来获取帧的展示时间戳(也就是这帧视频应该被显示的时间点):CMSampleBufferGetPresentationTimeStamp()。它会返回一个CMTime类型的对象,这是AVFoundation中标准的时间表示方式,用分子(value)和分母(timescale)来精确表示时间。

  2. 将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

火山引擎 最新活动