使用AVAssetWriter录制MP4音视频时,如何实时获取视频时长?
嘿,这个场景我太熟悉了!用AVAssetWriter录制音视频时,它本身并不会主动提供实时录制时长,得咱们自己动手跟踪。给你两个实用的方案,其中第一个是最靠谱的:
方案1:跟踪写入样本的时间戳(推荐)
AVAssetWriterInput接收的每个CMSampleBuffer都带有精确的时间戳,咱们可以通过记录第一个样本的起始时间,然后用后续样本的时间戳减去起始时间,就能得到当前的录制时长。
具体步骤:
- 在你的录制类里添加几个成员变量,用来记录关键时间节点:
@property (nonatomic, assign) CMTime recordingStartTime; @property (nonatomic, assign) CMTime currentDuration; @property (nonatomic, assign) BOOL isRecordingStarted;
- 开始录制时,初始化起始时间为无效状态:
- (void)startRecording { // 这里放你初始化AVAssetWriter、配置Input的代码 self.recordingStartTime = kCMTimeInvalid; self.isRecordingStarted = YES; }
- 在处理
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
相关产品推荐
相关产品推荐

