[英]Mute Video + Transform Video Using single export operation of AVAssetExportSession
I have following code to fix Tranform of video 我有以下代码来修复视频的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;
}
And Following code for Mute Audio 并遵循静音音频的代码
- (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;
}
Here how i call the function 我在这里如何调用该函数
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);
But it shows error if I used both composition
and [self squareVideoCompositionFor:asset]
但如果我同时使用了composition
和[self squareVideoCompositionFor:asset]
则会显示错误
Error Domain=AVFoundationErrorDomain Code=-11841 "Operation Stopped" UserInfo={NSLocalizedDescription=Operation Stopped, NSLocalizedFailureReason=The video could not be composed.} Error Domain = AVFoundationErrorDomain Code = -11841“Operation Stopped”UserInfo = {NSLocalizedDescription = Operation Stopped,NSLocalizedFailureReason =视频无法合成。}
If I omit one then it is working fine means One AVAssetExportSession can either mute audio from video or squareVideo 如果我省略一个然后它工作正常意味着一个AVAssetExportSession可以静音来自视频或squareVideo
Is there a way I can achieve both using single progress of export of AVAssetExportSession
? 有没有办法可以使用AVAssetExportSession
导出的单个进度来实现这两种方法?
Your code looks good but I have made changes in your code to get it work. 您的代码看起来不错,但我已对代码进行了更改以使其正常工作。
The inputURL
and outputURL
should be prefixed with either file://
or https://
(as it is url, in your case it should be start with file://
) inputURL
和outputURL
应该以file://
或https://
作为前缀(因为它是url,在你的情况下它应该以file://
开头)
If your is not valid then you will not get the desired output. 如果您的无效,那么您将无法获得所需的输出。
//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);
Export the composition 导出构图
//this will export the composition with the specified configuration
[session exportAsynchronouslyWithCompletionHandler:^{
NSLog(@"Success");
}];
When you see the "Success" log in console check the document directory of your application. 当您在控制台中看到“成功”日志时,请检查应用程序的文档目录。 The video will be written at outptURL
. 视频将在outptURL
上写。
NOTE: USE CMD + SHIFT + G and pase the outputURL. 注意:使用CMD + SHIFT + G并调整outputURL。 You will be redirected to the document folder of your app (For simulator only). 您将被重定向到应用程序的文档文件夹(仅适用于模拟器)。 For device, you need to download the app container and see the package content. 对于设备,您需要下载应用容器并查看包内容。
Complete CODE 完整的代码
The removeAudioFromVideoFileFor:
and squareVideoCompositionFor:
methods looks good. removeAudioFromVideoFileFor:
和squareVideoCompositionFor:
方法看起来不错。 just need to change the following. 只需要改变以下内容。
Here "video" is the name of the resource file in app bundle. 这里“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:");
}];
}
Hope it will help 希望它会有所帮助
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.