如何通过AVAssetWriter延长CGImage帧生成视频的最后一帧显示时长?
解决CGImage帧生成视频时延长最后一帧显示时长的优雅方案
嘿,我完全懂你那种用重复最后一帧凑时长的别扭感——这方法虽然能凑效,但既增加文件体积又不够优雅,咱们来聊聊更合理的解决思路:
一、生成视频时直接设置结束时间(最推荐的原生方案)
你之前用endSessionAtSourceTime:没生效,大概率是时间戳的计算或者调用时机出了问题。AVAssetWriter的时间线是基于帧的起始显示时间,最后一帧的持续时长其实是endSessionAtSourceTime减去最后一帧的presentationTime,所以只要参数设置正确,就能让最后一帧自动延续到指定时间。
举个具体的代码示例(假设你用30fps的帧速率,想延长最后一帧2秒):
// 假设lastFrameTime是最后一帧的起始显示时间(比如CMTimeMakeWithSeconds(totalPlayTime, 30)) CMTime extendedEndTime = CMTimeAdd(lastFrameTime, CMTimeMakeWithSeconds(2, 600)); // 用600作为时间刻度,精度更高 // 确保已经完成最后一帧的append操作后,再调用endSession [assetWriter endSessionAtSourceTime:extendedEndTime];
这里要注意两个关键点:
- 确保
extendedEndTime的时间刻度(timeScale)和你AVAssetWriterInput设置的一致,避免时间计算偏差 - 必须在最后一帧的
appendPixelBuffer:withPresentationTime:调用完成后,再执行endSessionAtSourceTime:
二、后期用AVMutableComposition调整已生成的视频
如果已经导出了视频,不想重新处理所有帧,可以用AVFoundation的组合功能直接拉长最后一帧的显示时长,不需要重复帧:
// 加载原视频 AVURLAsset *originalAsset = [AVURLAsset assetWithURL:yourOriginalVideoURL]; AVMutableComposition *composition = [AVMutableComposition composition]; // 添加视频轨道 AVMutableCompositionTrack *videoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; [videoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, originalAsset.duration) ofTrack:[[originalAsset tracksWithMediaType:AVMediaTypeVideo] firstObject] atTime:kCMTimeZero error:nil]; // 延长最后一帧2秒 CMTime extendedDuration = CMTimeAdd(originalAsset.duration, CMTimeMakeWithSeconds(2, 600)); videoTrack.timeRange = CMTimeRangeMake(kCMTimeZero, extendedDuration); // 导出新视频(这里省略导出的常规代码,用AVAssetExportSession即可) AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetHighestQuality]; exportSession.outputURL = yourOutputVideoURL; exportSession.outputFileType = AVFileTypeMP4; [exportSession exportAsynchronouslyWithCompletionHandler:^{ // 处理导出结果 }];
这个方法相当于告诉系统:“把视频的总时长拉长,最后一帧保持到新的结束时间”,完全不需要额外的帧数据,文件大小也不会冗余。
为什么重复帧的方案不推荐?
重复添加最后一帧会让视频文件中多出N个完全相同的帧数据,不仅增加文件体积,还可能在某些播放器中出现细微的卡顿(虽然大部分情况感知不到),而且从代码维护的角度看,这种“hack”式的写法也不如原生API清晰。
内容的提问来源于stack exchange,提问作者richy
相关产品推荐
相关产品推荐

