You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用AVAssetWriter录制MP4音视频时,如何实时获取视频时长?

嘿,这个场景我太熟悉了!用AVAssetWriter录制音视频时,它本身并不会主动提供实时录制时长,得咱们自己动手跟踪。给你两个实用的方案,其中第一个是最靠谱的:

方案1:跟踪写入样本的时间戳(推荐)

AVAssetWriterInput接收的每个CMSampleBuffer都带有精确的时间戳,咱们可以通过记录第一个样本的起始时间,然后用后续样本的时间戳减去起始时间,就能得到当前的录制时长。

具体步骤:

  1. 在你的录制类里添加几个成员变量,用来记录关键时间节点:
@property (nonatomic, assign) CMTime recordingStartTime;
@property (nonatomic, assign) CMTime currentDuration;
@property (nonatomic, assign) BOOL isRecordingStarted;
  1. 开始录制时,初始化起始时间为无效状态:
- (void)startRecording {
    // 这里放你初始化AVAssetWriter、配置Input的代码
    self.recordingStartTime = kCMTimeInvalid;
    self.isRecordingStarted = YES;
}
  1. 在处理CMSampleBuffer的方法里,实时更新时长:
- (BOOL)writeSampleBuffer:(CMSampleBufferRef)sampleBuffer toInput:(AVAssetWriterInput *)input {
    if (!self.isRecordingStarted || !input.isReadyForMoreMediaData) {
        return NO;
    }

    // 第一次写入样本时,记录起始时间
    if (CMTIME_IS_INVALID(self.recordingStartTime)) {
        self.recordingStartTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
    }

    // 计算当前时长:当前样本时间戳 - 起始时间
    CMTime currentSampleTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
    self.currentDuration = CMTimeSubtract(currentSampleTime, self.recordingStartTime);

    // 转换为秒数(方便显示或业务使用)
    NSTimeInterval durationInSeconds = CMTimeGetSeconds(self.currentDuration);
    NSLog(@"当前录制时长:%.2f秒", durationInSeconds);

    // 写入样本
    return [input appendSampleBuffer:sampleBuffer];
}

处理暂停/恢复的情况:

如果你的录制功能支持暂停,需要额外处理计时中断:

@property (nonatomic, assign) CMTime pauseAccumulatedDuration;
@property (nonatomic, assign) BOOL isPaused;

- (void)pauseRecording {
    if (!self.isPaused && self.isRecordingStarted) {
        // 记录暂停时已累计的时长
        self.pauseAccumulatedDuration = self.currentDuration;
        self.isPaused = YES;
    }
}

- (void)resumeRecording {
    if (self.isPaused) {
        // 恢复时重置起始时间,确保后续计算正确
        self.recordingStartTime = kCMTimeInvalid;
        self.isPaused = NO;
    }
}

// 同时修改写入样本时的起始时间逻辑:
if (CMTIME_IS_INVALID(self.recordingStartTime)) {
    // 恢复后,起始时间 = 当前样本时间 - 已累计的暂停时长
    self.recordingStartTime = CMTimeSubtract(CMSampleBufferGetPresentationTimeStamp(sampleBuffer), self.pauseAccumulatedDuration);
}
方案2:通过AVCaptureSession估算(仅作参考)

如果你是用AVCaptureSession采集音视频,也可以通过视频连接的帧率估算时长,但这个方法精度不如方案1,因为可能存在丢帧或采集延迟:

// 假设你持有AVCaptureConnection的引用
AVCaptureConnection *videoConnection = [self.videoInput connectionWithMediaType:AVMediaTypeVideo];
CMTime frameDuration = videoConnection.videoMinFrameDuration;
double fps = CMTimeGetSeconds(frameDuration) > 0 ? 1.0 / CMTimeGetSeconds(frameDuration) : 30.0;

// 记录开始录制的系统时间
@property (nonatomic, assign) NSTimeInterval startSystemTime;

- (void)startRecording {
    self.startSystemTime = CACurrentMediaTime();
}

// 估算时长
NSTimeInterval estimatedDuration = CACurrentMediaTime() - self.startSystemTime;

这个方法适合不需要高精度的场景,但还是优先推荐方案1。

注意事项:

  • 一定要检查CMTime的有效性,避免无效时间戳导致计算错误。
  • 视频和音频的时间戳可能略有差异,优先用视频的时间戳计算时长,因为视频是录制的核心轨道。

内容的提问来源于stack exchange,提问作者user924

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:12:03