繁体   English   中英

使用 AVAssetExportSession 合成和导出后的视频持续时间更改

[英]Video duration changes after composing and export using AVAssetExportSession

我正在尝试从视频中裁剪一个方框。 以下是流程

  1. 获取视频资产
  2. 从该资产中获取视频轨道
  3. 创建具有帧持续时间 (30fps) 和 renderSize(必需矩形)的 AVMutableComposition 实例
  4. 使用 timeRange (0-asset.duration) 创建 AVMutableVideoCompositionInstruction 实例
  5. 创建 LayerInstruction 实例
  6. 设置它的变换以给予帧偏移
  7. 在指令中设置层指令
  8. 在 mutableComposition 实例中设置指令
  9. 使用上述资产和 HighestQuality 预设创建 AVAssetExportSession 实例
  10. 设置它的输出 URL 、 timeRange 和输出文件类型
  11. 异步导出

现在发生的情况是,视频显示正确,但在某些情况下其持续时间会有所不同

  1. 如果视频在最后有移动,则不会进行剪切,并且输出的视频与原始视频的时间相同
  2. 如果视频是静态的,使得视频中没有运动,或者在视频的最后,一些静态帧被移除,视频长度变小
  3. 在视频中有大量移动的某些情况下,持续时间会增加。

持续时间的变化从 0.1 秒到 1 秒。 这可能是一个非常小的变化,但在我需要这个过程的地方,视频持续时间必须精确。

如果你想深入研究,我正在添加代码。

AVAsset *asset ;
asset = [AVAsset assetWithURL:customURL];


//create an avassetrack with our asset
AVAssetTrack *clipVideoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];

CMTime originalVideoDur = asset.duration;
float orgDurFloat = (float)originalVideoDur.value / (float)originalVideoDur.timescale;


//create a video composition and preset some settings
AVMutableVideoComposition* videoComposition = [AVMutableVideoComposition videoComposition];
videoComposition.frameDuration = CMTimeMake(1, 30);

//here we are setting its render size to its height x height (Square)
CGFloat outputWidth = UIScreen.mainScreen.bounds.size.width * UIScreen.mainScreen.scale;
videoComposition.renderSize = CGSizeMake(outputWidth, outputWidth);

//create a video instruction
AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, asset.duration);

AVMutableVideoCompositionLayerInstruction* transformer = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:clipVideoTrack];

CGAffineTransform finalTransform = [self getOutputTransformOfAsset:asset track:clipVideoTrack];
[transformer setTransform:finalTransform atTime:kCMTimeZero];

//add the transformer layer instructions, then add to video composition
instruction.layerInstructions = [NSArray arrayWithObject:transformer];
videoComposition.instructions = [NSArray arrayWithObject: instruction];

//Create an Export Path to store the cropped video
NSString * documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *exportPath = [documentsPath stringByAppendingFormat:@"/CroppedVideo2.mp4"];
NSURL *exportUrl = [NSURL fileURLWithPath:exportPath];

//Remove any prevouis videos at that path
[[NSFileManager defaultManager]  removeItemAtURL:exportUrl error:nil];

//Export
exporter = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetHighestQuality] ;
exporter.videoComposition = videoComposition;
exporter.outputURL = exportUrl;
exporter.outputFileType = AVFileTypeMPEG4;
exporter.timeRange = CMTimeRangeMake(kCMTimeZero, asset.duration);

[exporter exportAsynchronouslyWithCompletionHandler:^
 {
     dispatch_async(dispatch_get_main_queue(), ^{
         //Call when finished
     });
 }];

我测试过但不起作用的事情是:

  • 更改 AVAssetExportSession 预设。 (无效果,除了低质量产生较小的持续时间差异但仍然是巨大的差异)
  • 帧持续时间(较短的帧持续时间较小的持续时间差异,1 帧持续时间在持续时间上提供最佳结果,但输出视频不可用)

发现问题:老实说这不是问题,这是一种系统错误。 导出器无缘无故地忽略了最后一个静态帧。 在 kCMTimeZero 设置变换时,我添加了新行,在视频末尾设置相同的变换。

[transformer setTransform:finalTransform atTime:asset.duration];

现在导出器不会忽略最后几帧。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM