[英]Video duration changes after composing and export using AVAssetExportSession
[英]Mute Video + Transform Video Using single export operation of AVAssetExportSession
我有以下代码来修复视频的Tranform
- (AVVideoComposition *)squareVideoCompositionFor:(AVAsset *)asset {
AVAssetTrack *track = [asset tracksWithMediaType:AVMediaTypeVideo].firstObject;
CGFloat length = MAX(track.naturalSize.width, track.naturalSize.height);
CGSize size = track.naturalSize;
CGFloat scale = 0;
CGAffineTransform transform = track.preferredTransform;
if (transform.a == 0 && transform.b == 1 && transform.c == -1 && transform.d == 0) {
scale = -1;
}
else if (transform.a == 0 && transform.b == -1 && transform.c == 1 && transform.d == 0) {
scale = -1;
}
else if (transform.a == 1 && transform.b == 0 && transform.c == 0 && transform.d == 1) {
scale = 1;
}
else if (transform.a == -1 && transform.b == 0 && transform.c == 0 && transform.d == -1) {
scale = -1;
}
transform = CGAffineTransformTranslate(transform, scale * -(size.width - length) / 2, scale * -(size.height - length) / 2);
AVMutableVideoCompositionLayerInstruction *transformer = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:track];
[transformer setTransform:transform atTime:kCMTimeZero];
// CGAffineTransform finalTransform = t2;
// [transformer setTransform:finalTransform atTime:kCMTimeZero];
AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, kCMTimePositiveInfinity);
instruction.layerInstructions = @[transformer];
AVMutableVideoComposition *composition = [AVMutableVideoComposition videoComposition];
composition.frameDuration = CMTimeMake(1, 30);
composition.renderSize = CGSizeMake(length, length);
composition.instructions = @[instruction];
composition.renderScale = 1.0;
return composition;
}
并遵循静音音频的代码
- (AVMutableComposition *) removeAudioFromVideoFileFor:(AVAsset *)asset {
AVMutableComposition *composition_Mix = [AVMutableComposition composition];
AVMutableCompositionTrack *compositionVideoTrack = [composition_Mix addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
BOOL ok = NO;
AVAssetTrack * sourceVideoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
CMTimeRange x = CMTimeRangeMake(kCMTimeZero, [asset duration]);
NSError *error;
ok = [compositionVideoTrack insertTimeRange:x ofTrack:sourceVideoTrack atTime:kCMTimeZero error:&error];
return composition_Mix;
}
我在这里如何调用该函数
AVAsset *asset = [AVAsset assetWithURL:inputURL];
AVMutableComposition *composition = [self removeAudioFromVideoFileFor:asset];
AVAssetExportSession *session = [AVAssetExportSession exportSessionWithAsset:composition presetName:AVAssetExportPresetHighestQuality];
session.videoComposition = [self squareVideoCompositionFor:asset];
session.outputURL = outputURL;
session.outputFileType = AVFileTypeMPEG4;
session.shouldOptimizeForNetworkUse = true;
session.timeRange = CMTimeRangeMake(kCMTimeZero, asset.duration);
但如果我同时使用了composition
和[self squareVideoCompositionFor:asset]
则会显示错误
Error Domain = AVFoundationErrorDomain Code = -11841“Operation Stopped”UserInfo = {NSLocalizedDescription = Operation Stopped,NSLocalizedFailureReason =视频无法合成。}
如果我省略一个然后它工作正常意味着一个AVAssetExportSession可以静音来自视频或squareVideo
有没有办法可以使用AVAssetExportSession
导出的单个进度来实现这两种方法?
您的代码看起来不错,但我已对代码进行了更改以使其正常工作。
inputURL
和outputURL
应该以file://
或https://
作为前缀(因为它是url,在你的情况下它应该以file://
开头)
如果您的无效,那么您将无法获得所需的输出。
//FOR OUTPUT URL
NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
path = [path stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
//the output video will be written to file final.mp4
NSURL *outputURL = [NSURL fileURLWithPath:path];
outputURL = [outputURL URLByAppendingPathComponent:@"final.mp4"];
NSLog(@"outputURL = %@", outputURL);
//FOR INPUT URL
//This is the path of the bundle resource that is going to be used
NSURL *inputURL = [[NSBundle mainBundle] URLForResource:@"video" withExtension:@"mp4"];
NSLog(@"inputURL = %@", inputURL);
导出构图
//this will export the composition with the specified configuration
[session exportAsynchronouslyWithCompletionHandler:^{
NSLog(@"Success");
}];
当您在控制台中看到“成功”日志时,请检查应用程序的文档目录。 视频将在outptURL
上写。
注意:使用CMD + SHIFT + G并调整outputURL。 您将被重定向到应用程序的文档文件夹(仅适用于模拟器)。 对于设备,您需要下载应用容器并查看包内容。
完整的代码
removeAudioFromVideoFileFor:
和squareVideoCompositionFor:
方法看起来不错。 只需要改变以下内容。
这里“video”是app bundle中资源文件的名称。
- (void)viewDidLoad {
[super viewDidLoad];
NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
path = [path stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSURL *outputURL = [NSURL fileURLWithPath:path];
outputURL = [outputURL URLByAppendingPathComponent:@"final.mp4"];
NSLog(@"outputURL = %@", outputURL);
NSURL *inputURL = [[NSBundle mainBundle] URLForResource:@"video" withExtension:@"mp4"];
NSLog(@"inputURL = %@", inputURL);
AVAsset *asset = [AVAsset assetWithURL:inputURL];
AVMutableComposition *composition = [self removeAudioFromVideoFileFor: asset];
AVAssetExportSession *session = [AVAssetExportSession exportSessionWithAsset:composition presetName:AVAssetExportPresetHighestQuality];
session.videoComposition = [self squareVideoCompositionFor:asset];
session.outputURL = outputURL;
session.outputFileType = AVFileTypeMPEG4;
session.shouldOptimizeForNetworkUse = true;
session.timeRange = CMTimeRangeMake(kCMTimeZero, asset.duration);
[session exportAsynchronouslyWithCompletionHandler:^{
NSLog(@"Success:");
}];
}
希望它会有所帮助
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.