iOS 视频旋转及平移详解
2016-07-12 10:59
393 查看
//必须是fileURL
//截取将会是视频的中间部分
//这里假设拍摄出来的视频总是高大于宽的
/*!
@method mergeAndExportVideosAtFileURLs:
@param fileURLArray
包含所有视频分段的文件URL数组,必须是[NSURL fileURLWithString:...]得到的
@discussion
将所有分段视频合成为一段完整视频,并且裁剪为正方形
*/
#if 1
- (void)mergeAndExportVideosAtFileURLs:(NSArray *)fileURLArray
{
// NSLog(@"the getVideoCount is %lu", (unsigned long)[self getVideoCount]);
// if (self.getVideoCount != fileURLArray.count) {
// NSLog(@"必定崩溃-------");
// NSLog(@"必定崩溃-------");
// NSLog(@"必定崩溃-------");
// }
NSLog(@"the fileURLArray is %@", fileURLArray);
if (fileURLArray.count <= 0) {
#warning 小片段视频还未成功生成就开始 合并 视频
NSLog(@"严重错误!!!!!!!!!!!!!!!!!!!!!");
return;
}else{
for (NSURL *fileURL in fileURLArray) {
NSString *path = fileURL.resourceSpecifier;
if ([[NSFileManager defaultManager] fileExistsAtPath:path])
{
JFLog(DBGUI, @"mergeAndExportVideosAtFileURLs theVideoPath is %@", path);
NSUInteger size;
NSDictionary *attr = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil];
size = [attr[NSFileSize] unsignedIntegerValue];
JFLog(DBGUI, @"mergeAndExportVideosAtFileURLs fileSize is %lu", size/(1024*1024));
}
}
}
dispatch_async(_serialQueue, ^{
// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSError *error = nil;
CGSize renderSize = CGSizeMake(0, 0);
NSMutableArray *layerInstructionArray = [[NSMutableArray alloc] init];
AVMutableComposition *mixComposition = [[AVMutableComposition alloc] init];
CMTime totalDuration = kCMTimeZero;
//先去assetTrack 也为了取renderSize
NSMutableArray *assetTrackArray = [[NSMutableArray alloc] init];
NSMutableArray *assetAudioTrackArray = [NSMutableArray arrayWithCapacity:0];
NSMutableArray *assetArray = [[NSMutableArray alloc] init];
for (NSURL *fileURL in fileURLArray) {
AVAsset *asset = [AVAsset assetWithURL:fileURL];
// AVURLAsset *asset = [AVURLAsset URLAssetWithURL:fileURL options:nil];
// NSString *tracksKey = @"tracks";
NSString *tracksKey = @"AVMediaTypeAudio";
if (!asset) {
continue;
}
[assetArray addObject:asset];
AVAssetTrack *assetTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
[assetTrackArray addObject:assetTrack];
// AVAssetTrack *assetAudioTrack = [[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
// [assetAudioTrackArray addObject:assetAudioTrack];
renderSize.width = MAX(renderSize.width, assetTrack.naturalSize.height);
renderSize.height = MAX(renderSize.height, assetTrack.naturalSize.width);
}
NSLog(@"the assetAudioTrackArray is %@", assetAudioTrackArray);
CGFloat renderW = MIN(renderSize.width, renderSize.height);
NSLog(@"the renderW is %f", renderW);
NSLog(@"the assetArray cout is %lu", (unsigned long)[assetArray count]);
NSLog(@"the assetTrackArray cout is %lu", (unsigned long)[assetTrackArray count]);
for (int i = 0; i < [assetArray count] && i < [assetTrackArray count]; i++) {
AVAsset *asset = [assetArray objectAtIndex:i];
AVAssetTrack *assetTrack = [assetTrackArray objectAtIndex:i];
// AVMutableCompositionTrack *audioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
// [audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration)
// ofTrack:[[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0]
// atTime:totalDuration
// error:nil];
#warning 这里加一个判断
//[asset tracksWithMediaType:AVMediaTypeAudio]取出的数组可能为空 这段视频没有音频
NSArray *arr = [asset tracksWithMediaType:AVMediaTypeAudio];
JFLog(DBGUI, @"the audioTrackArr is %@", arr);
if (arr.count <= 0) {
NSLog(@"没有视频!!!!!!!!!!!!!!!!!!!!!");
NSLog(@"没有视频!!!!!!!!!!!!!!!!!!!!!");
}
if (arr.count > 0) {
AVMutableCompositionTrack *audioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration) ofTrack:[arr objectAtIndex:0] atTime:totalDuration error:nil];
}
// [audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration) ofTrack:([arr count]>0)?[arr objectAtIndex:0]:nil atTime:totalDuration error:nil];
AVMutableCompositionTrack *videoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
NSLog(@"the assetduration is %lld", asset.duration.value/asset.duration.timescale);
[videoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration)
ofTrack:assetTrack
atTime:totalDuration
error:&error];
//fix orientationissue
AVMutableVideoCompositionLayerInstruction *layerInstruciton = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];
totalDuration = CMTimeAdd(totalDuration, asset.duration);
CGFloat rate;
NSLog(@"the renderW is %f", renderW);
NSLog(@"assetTrack.naturalSize.width is %f", assetTrack.naturalSize.width);
NSLog(@"assetTrack.naturalSize.height is %f", assetTrack.naturalSize.height);
rate = renderW / MIN(assetTrack.naturalSize.width, assetTrack.naturalSize.height);
NSLog(@"the rate is %f", rate);
NSLog(@" preferredTransform.a is %f", assetTrack.preferredTransform.a);
NSLog(@" preferredTransform.b is %f", assetTrack.preferredTransform.b);
NSLog(@" preferredTransform.c is %f", assetTrack.preferredTransform.c);
NSLog(@" preferredTransform.d is %f", assetTrack.preferredTransform.d);
NSLog(@" preferredTransform.tx is %f", assetTrack.preferredTransform.tx);
NSLog(@" preferredTransform.ty is %f", assetTrack.preferredTransform.ty);
CGAffineTransform translateToCenter;
CGAffineTransform mixedTransform;
// AVMutableVideoComposition *waterMarkVideoComposition = [AVMutableVideoComposition videoComposition];
// waterMarkVideoComposition.frameDuration = CMTimeMake(1, 30);
int degrees = [self degressFromVideoFileWithURL:assetTrack];
// degrees = 180;
if (degrees == 0) {
// AVAssetExportSession *session = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetMediumQuality];
// session.outputURL = outputURL;
// session.outputFileType = AVFileTypeQuickTimeMovie;
}else{
if(degrees == 90){
//顺时针旋转90°
NSLog(@"视频旋转90度,home按键在左");
translateToCenter = CGAffineTransformMakeTranslation(assetTrack.naturalSize.height, 0.0);
// mixedTransform = CGAffineTransformRotate(translateToCenter,0);
mixedTransform = CGAffineTransformRotate(translateToCenter,M_PI_2);
// videoTrack.renderSize = CGSizeMake(assetTrack.naturalSize.height,assetTrack.naturalSize.width);
}else if(degrees == 180){
//顺时针旋转180°
NSLog(@"视频旋转180度,home按键在上");
translateToCenter = CGAffineTransformMakeTranslation(assetTrack.naturalSize.width, assetTrack.naturalSize.height);
mixedTransform = CGAffineTransformRotate(translateToCenter,M_PI);
// waterMarkVideoComposition.renderSize = CGSizeMake(assetTrack.naturalSize.width,assetTrack.naturalSize.height);
}else if(degrees == 270){
//顺时针旋转270°
NSLog(@"视频旋转270度,home按键在右");
translateToCenter = CGAffineTransformMakeTranslation(0.0, assetTrack.naturalSize.width);
mixedTransform = CGAffineTransformRotate(translateToCenter,M_PI_2*3.0);
// waterMarkVideoComposition.renderSize = CGSizeMake(assetTrack.naturalSize.height,assetTrack.naturalSize.width);
}
}
CGAffineTransform preferredTransform = assetTrack.preferredTransform;
CGAffineTransform trans = CGAffineTransformTranslate(preferredTransform, 0.0, -assetTrack.naturalSize.height);
CGAffineTransform transNew = CGAffineTransformRotate(preferredTransform,M_PI_2*3);
transNew = CGAffineTransformTranslate(transNew, 0, -(assetTrack.naturalSize.width - assetTrack.naturalSize.height) / 2.0);
transNew = CGAffineTransformConcat(trans, transNew);
transNew = CGAffineTransformScale(transNew, rate, rate);//放缩,解决前后摄像结果大小不对称
// CGAffineTransform layerTransform = CGAffineTransformMake(assetTrack.preferredTransform.a, assetTrack.preferredTransform.b, assetTrack.preferredTransform.c, assetTrack.preferredTransform.d, assetTrack.preferredTransform.tx * rate, assetTrack.preferredTransform.ty * rate);
// layerTransform = (a = 0, b = 1, c = -1, d = 0, tx = 1080, ty = 0)
CGAffineTransform layerTransform = CGAffineTransformMake(assetTrack.preferredTransform.a, assetTrack.preferredTransform.b, assetTrack.preferredTransform.c, assetTrack.preferredTransform.d, assetTrack.naturalSize.height * rate, assetTrack.preferredTransform.ty * rate);
//
// layerTransform = CGAffineTransformConcat(layerTransform, CGAffineTransformMake(1, 0, 0, 1, 0, -(assetTrack.naturalSize.width - assetTrack.naturalSize.height) / 2.0));//向上移动取中部影响
////
// layerTransform = CGAffineTransformScale(layerTransform, rate, rate);//放缩,解决前后摄像结果大小不对称
// [layerInstruciton setTransform:layerTransform atTime:kCMTimeZero];
// [layerInstruciton setOpacity:0.0 atTime:totalDuration];
[layerInstruciton setTransform:transNew atTime:kCMTimeZero];
// [layerInstruciton setTransform:mixedTransform atTime:kCMTimeZero];
// [layerInstruciton setTransform:assetTrack.preferredTransform atTime:kCMTimeZero];
//data
[layerInstructionArray addObject:layerInstruciton];
}
//get save path
NSURL *mergeFileURL = [NSURL fileURLWithPath:[[self class] getVideoMergeFilePathString]];
//export
AVMutableVideoCompositionInstruction *mainInstruciton = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
mainInstruciton.timeRange = CMTimeRangeMake(kCMTimeZero, totalDuration);
mainInstruciton.layerInstructions = layerInstructionArray;
AVMutableVideoComposition *mainCompositionInst = [AVMutableVideoComposition videoComposition];
mainCompositionInst.instructions = @[mainInstruciton];
mainCompositionInst.frameDuration = CMTimeMake(1, 30);
// mainCompositionInst.frameDuration = CMTimeMake(1, 24);
NSLog(@"the renderSize is %@", NSStringFromCGSize(CGSizeMake(renderW, renderW)));
mainCompositionInst.renderSize = CGSizeMake(renderW, renderW);
AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetMediumQuality];
exporter.videoComposition = mainCompositionInst;
exporter.outputURL = mergeFileURL;
exporter.outputFileType = AVFileTypeMPEG4;
exporter.shouldOptimizeForNetworkUse = YES;
[exporter exportAsynchronouslyWithCompletionHandler:^{
if ([exporter status] != AVAssetExportSessionStatusCompleted) {
NSLog(@"the status is %ld", (long)[exporter status]);
NSLog(@"the outPutPath is %@", [exporter.outputURL absoluteString]);
NSLog(@"the error is %@", [exporter error].userInfo);
NSLog(@"the error is %@", [exporter error]);
}
if ([exporter status] == AVAssetExportSessionStatusFailed) {
if (DEBUG) {
NSLog(@"error ");
}
}
NSString *path = mergeFileURL.resourceSpecifier;
// NSString *pa1 = outputFileURL.absoluteString;
// NSString *pa2 = outputFileURL.resourceSpecifier;
// NSString *pa3 = outputFileURL.scheme;
// NSString *pa4 = outputFileURL.relativePath;
NSLog(@"theVideoPath is %@", path);
NSLog(@"outputFileURL is %@", mergeFileURL);
if ([[NSFileManager defaultManager] fileExistsAtPath:path])
{
NSLog(@"theVideoPath is %@", path);
NSUInteger size;
NSDictionary *attr = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil];
size = [attr[NSFileSize] unsignedIntegerValue];
NSLog(@"didFinishRecordingToOutputFileAtURL fileSize is %lu", size/(1024*1024));
}
NSLog(@"the outputFile is %@", mergeFileURL);
dispatch_async(dispatch_get_main_queue(), ^{
MSPreViewController *VC = [MSPreViewController new];
VC.videoURL = mergeFileURL;
NSLog(@"navi is %@", self.navigationController);
[self.navigationController pushViewController:VC animated:YES];
});
// return;
// dispatch_async(dispatch_get_main_queue(), ^{
// if ([_delegate respondsToSelector:@selector(videoRecorder:didFinishMergingVideosToOutPutFileAtURL:)]) {
// [_delegate videoRecorder:self didFinishMergingVideosToOutPutFileAtURL:mergeFileURL];
// }
// });
}];
});
}
#endif
//截取将会是视频的中间部分
//这里假设拍摄出来的视频总是高大于宽的
/*!
@method mergeAndExportVideosAtFileURLs:
@param fileURLArray
包含所有视频分段的文件URL数组,必须是[NSURL fileURLWithString:...]得到的
@discussion
将所有分段视频合成为一段完整视频,并且裁剪为正方形
*/
#if 1
- (void)mergeAndExportVideosAtFileURLs:(NSArray *)fileURLArray
{
// NSLog(@"the getVideoCount is %lu", (unsigned long)[self getVideoCount]);
// if (self.getVideoCount != fileURLArray.count) {
// NSLog(@"必定崩溃-------");
// NSLog(@"必定崩溃-------");
// NSLog(@"必定崩溃-------");
// }
NSLog(@"the fileURLArray is %@", fileURLArray);
if (fileURLArray.count <= 0) {
#warning 小片段视频还未成功生成就开始 合并 视频
NSLog(@"严重错误!!!!!!!!!!!!!!!!!!!!!");
return;
}else{
for (NSURL *fileURL in fileURLArray) {
NSString *path = fileURL.resourceSpecifier;
if ([[NSFileManager defaultManager] fileExistsAtPath:path])
{
JFLog(DBGUI, @"mergeAndExportVideosAtFileURLs theVideoPath is %@", path);
NSUInteger size;
NSDictionary *attr = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil];
size = [attr[NSFileSize] unsignedIntegerValue];
JFLog(DBGUI, @"mergeAndExportVideosAtFileURLs fileSize is %lu", size/(1024*1024));
}
}
}
dispatch_async(_serialQueue, ^{
// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSError *error = nil;
CGSize renderSize = CGSizeMake(0, 0);
NSMutableArray *layerInstructionArray = [[NSMutableArray alloc] init];
AVMutableComposition *mixComposition = [[AVMutableComposition alloc] init];
CMTime totalDuration = kCMTimeZero;
//先去assetTrack 也为了取renderSize
NSMutableArray *assetTrackArray = [[NSMutableArray alloc] init];
NSMutableArray *assetAudioTrackArray = [NSMutableArray arrayWithCapacity:0];
NSMutableArray *assetArray = [[NSMutableArray alloc] init];
for (NSURL *fileURL in fileURLArray) {
AVAsset *asset = [AVAsset assetWithURL:fileURL];
// AVURLAsset *asset = [AVURLAsset URLAssetWithURL:fileURL options:nil];
// NSString *tracksKey = @"tracks";
NSString *tracksKey = @"AVMediaTypeAudio";
if (!asset) {
continue;
}
[assetArray addObject:asset];
AVAssetTrack *assetTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
[assetTrackArray addObject:assetTrack];
// AVAssetTrack *assetAudioTrack = [[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
// [assetAudioTrackArray addObject:assetAudioTrack];
renderSize.width = MAX(renderSize.width, assetTrack.naturalSize.height);
renderSize.height = MAX(renderSize.height, assetTrack.naturalSize.width);
}
NSLog(@"the assetAudioTrackArray is %@", assetAudioTrackArray);
CGFloat renderW = MIN(renderSize.width, renderSize.height);
NSLog(@"the renderW is %f", renderW);
NSLog(@"the assetArray cout is %lu", (unsigned long)[assetArray count]);
NSLog(@"the assetTrackArray cout is %lu", (unsigned long)[assetTrackArray count]);
for (int i = 0; i < [assetArray count] && i < [assetTrackArray count]; i++) {
AVAsset *asset = [assetArray objectAtIndex:i];
AVAssetTrack *assetTrack = [assetTrackArray objectAtIndex:i];
// AVMutableCompositionTrack *audioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
// [audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration)
// ofTrack:[[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0]
// atTime:totalDuration
// error:nil];
#warning 这里加一个判断
//[asset tracksWithMediaType:AVMediaTypeAudio]取出的数组可能为空 这段视频没有音频
NSArray *arr = [asset tracksWithMediaType:AVMediaTypeAudio];
JFLog(DBGUI, @"the audioTrackArr is %@", arr);
if (arr.count <= 0) {
NSLog(@"没有视频!!!!!!!!!!!!!!!!!!!!!");
NSLog(@"没有视频!!!!!!!!!!!!!!!!!!!!!");
}
if (arr.count > 0) {
AVMutableCompositionTrack *audioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration) ofTrack:[arr objectAtIndex:0] atTime:totalDuration error:nil];
}
// [audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration) ofTrack:([arr count]>0)?[arr objectAtIndex:0]:nil atTime:totalDuration error:nil];
AVMutableCompositionTrack *videoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
NSLog(@"the assetduration is %lld", asset.duration.value/asset.duration.timescale);
[videoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration)
ofTrack:assetTrack
atTime:totalDuration
error:&error];
//fix orientationissue
AVMutableVideoCompositionLayerInstruction *layerInstruciton = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];
totalDuration = CMTimeAdd(totalDuration, asset.duration);
CGFloat rate;
NSLog(@"the renderW is %f", renderW);
NSLog(@"assetTrack.naturalSize.width is %f", assetTrack.naturalSize.width);
NSLog(@"assetTrack.naturalSize.height is %f", assetTrack.naturalSize.height);
rate = renderW / MIN(assetTrack.naturalSize.width, assetTrack.naturalSize.height);
NSLog(@"the rate is %f", rate);
NSLog(@" preferredTransform.a is %f", assetTrack.preferredTransform.a);
NSLog(@" preferredTransform.b is %f", assetTrack.preferredTransform.b);
NSLog(@" preferredTransform.c is %f", assetTrack.preferredTransform.c);
NSLog(@" preferredTransform.d is %f", assetTrack.preferredTransform.d);
NSLog(@" preferredTransform.tx is %f", assetTrack.preferredTransform.tx);
NSLog(@" preferredTransform.ty is %f", assetTrack.preferredTransform.ty);
CGAffineTransform translateToCenter;
CGAffineTransform mixedTransform;
// AVMutableVideoComposition *waterMarkVideoComposition = [AVMutableVideoComposition videoComposition];
// waterMarkVideoComposition.frameDuration = CMTimeMake(1, 30);
int degrees = [self degressFromVideoFileWithURL:assetTrack];
// degrees = 180;
if (degrees == 0) {
// AVAssetExportSession *session = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetMediumQuality];
// session.outputURL = outputURL;
// session.outputFileType = AVFileTypeQuickTimeMovie;
}else{
if(degrees == 90){
//顺时针旋转90°
NSLog(@"视频旋转90度,home按键在左");
translateToCenter = CGAffineTransformMakeTranslation(assetTrack.naturalSize.height, 0.0);
// mixedTransform = CGAffineTransformRotate(translateToCenter,0);
mixedTransform = CGAffineTransformRotate(translateToCenter,M_PI_2);
// videoTrack.renderSize = CGSizeMake(assetTrack.naturalSize.height,assetTrack.naturalSize.width);
}else if(degrees == 180){
//顺时针旋转180°
NSLog(@"视频旋转180度,home按键在上");
translateToCenter = CGAffineTransformMakeTranslation(assetTrack.naturalSize.width, assetTrack.naturalSize.height);
mixedTransform = CGAffineTransformRotate(translateToCenter,M_PI);
// waterMarkVideoComposition.renderSize = CGSizeMake(assetTrack.naturalSize.width,assetTrack.naturalSize.height);
}else if(degrees == 270){
//顺时针旋转270°
NSLog(@"视频旋转270度,home按键在右");
translateToCenter = CGAffineTransformMakeTranslation(0.0, assetTrack.naturalSize.width);
mixedTransform = CGAffineTransformRotate(translateToCenter,M_PI_2*3.0);
// waterMarkVideoComposition.renderSize = CGSizeMake(assetTrack.naturalSize.height,assetTrack.naturalSize.width);
}
}
CGAffineTransform preferredTransform = assetTrack.preferredTransform;
CGAffineTransform trans = CGAffineTransformTranslate(preferredTransform, 0.0, -assetTrack.naturalSize.height);
CGAffineTransform transNew = CGAffineTransformRotate(preferredTransform,M_PI_2*3);
transNew = CGAffineTransformTranslate(transNew, 0, -(assetTrack.naturalSize.width - assetTrack.naturalSize.height) / 2.0);
transNew = CGAffineTransformConcat(trans, transNew);
transNew = CGAffineTransformScale(transNew, rate, rate);//放缩,解决前后摄像结果大小不对称
// CGAffineTransform layerTransform = CGAffineTransformMake(assetTrack.preferredTransform.a, assetTrack.preferredTransform.b, assetTrack.preferredTransform.c, assetTrack.preferredTransform.d, assetTrack.preferredTransform.tx * rate, assetTrack.preferredTransform.ty * rate);
// layerTransform = (a = 0, b = 1, c = -1, d = 0, tx = 1080, ty = 0)
CGAffineTransform layerTransform = CGAffineTransformMake(assetTrack.preferredTransform.a, assetTrack.preferredTransform.b, assetTrack.preferredTransform.c, assetTrack.preferredTransform.d, assetTrack.naturalSize.height * rate, assetTrack.preferredTransform.ty * rate);
//
// layerTransform = CGAffineTransformConcat(layerTransform, CGAffineTransformMake(1, 0, 0, 1, 0, -(assetTrack.naturalSize.width - assetTrack.naturalSize.height) / 2.0));//向上移动取中部影响
////
// layerTransform = CGAffineTransformScale(layerTransform, rate, rate);//放缩,解决前后摄像结果大小不对称
// [layerInstruciton setTransform:layerTransform atTime:kCMTimeZero];
// [layerInstruciton setOpacity:0.0 atTime:totalDuration];
[layerInstruciton setTransform:transNew atTime:kCMTimeZero];
// [layerInstruciton setTransform:mixedTransform atTime:kCMTimeZero];
// [layerInstruciton setTransform:assetTrack.preferredTransform atTime:kCMTimeZero];
//data
[layerInstructionArray addObject:layerInstruciton];
}
//get save path
NSURL *mergeFileURL = [NSURL fileURLWithPath:[[self class] getVideoMergeFilePathString]];
//export
AVMutableVideoCompositionInstruction *mainInstruciton = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
mainInstruciton.timeRange = CMTimeRangeMake(kCMTimeZero, totalDuration);
mainInstruciton.layerInstructions = layerInstructionArray;
AVMutableVideoComposition *mainCompositionInst = [AVMutableVideoComposition videoComposition];
mainCompositionInst.instructions = @[mainInstruciton];
mainCompositionInst.frameDuration = CMTimeMake(1, 30);
// mainCompositionInst.frameDuration = CMTimeMake(1, 24);
NSLog(@"the renderSize is %@", NSStringFromCGSize(CGSizeMake(renderW, renderW)));
mainCompositionInst.renderSize = CGSizeMake(renderW, renderW);
AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetMediumQuality];
exporter.videoComposition = mainCompositionInst;
exporter.outputURL = mergeFileURL;
exporter.outputFileType = AVFileTypeMPEG4;
exporter.shouldOptimizeForNetworkUse = YES;
[exporter exportAsynchronouslyWithCompletionHandler:^{
if ([exporter status] != AVAssetExportSessionStatusCompleted) {
NSLog(@"the status is %ld", (long)[exporter status]);
NSLog(@"the outPutPath is %@", [exporter.outputURL absoluteString]);
NSLog(@"the error is %@", [exporter error].userInfo);
NSLog(@"the error is %@", [exporter error]);
}
if ([exporter status] == AVAssetExportSessionStatusFailed) {
if (DEBUG) {
NSLog(@"error ");
}
}
NSString *path = mergeFileURL.resourceSpecifier;
// NSString *pa1 = outputFileURL.absoluteString;
// NSString *pa2 = outputFileURL.resourceSpecifier;
// NSString *pa3 = outputFileURL.scheme;
// NSString *pa4 = outputFileURL.relativePath;
NSLog(@"theVideoPath is %@", path);
NSLog(@"outputFileURL is %@", mergeFileURL);
if ([[NSFileManager defaultManager] fileExistsAtPath:path])
{
NSLog(@"theVideoPath is %@", path);
NSUInteger size;
NSDictionary *attr = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil];
size = [attr[NSFileSize] unsignedIntegerValue];
NSLog(@"didFinishRecordingToOutputFileAtURL fileSize is %lu", size/(1024*1024));
}
NSLog(@"the outputFile is %@", mergeFileURL);
dispatch_async(dispatch_get_main_queue(), ^{
MSPreViewController *VC = [MSPreViewController new];
VC.videoURL = mergeFileURL;
NSLog(@"navi is %@", self.navigationController);
[self.navigationController pushViewController:VC animated:YES];
});
// return;
// dispatch_async(dispatch_get_main_queue(), ^{
// if ([_delegate respondsToSelector:@selector(videoRecorder:didFinishMergingVideosToOutPutFileAtURL:)]) {
// [_delegate videoRecorder:self didFinishMergingVideosToOutPutFileAtURL:mergeFileURL];
// }
// });
}];
});
}
#endif
相关文章推荐
- iOS开发笔记--iOS动画(Core Animation)总结
- iOS日常笔记
- IOS封装自定义Cell方法
- IOS Dev Intro - Variable property attributes or Modifiers in iOS
- iOS: 音效和音乐的播放,封装的工具类
- iOS设计模式(十) 享元模式
- IOS Dev Intro - Memory Management
- 《Motion Design for iOS》(三十四)
- 谈谈iOS Animation
- 李洪强iOS之Foundation框架—字符串
- iOS动画(Core Animation)总结
- ios常用的框架
- IOS 中获取手机的 udid 和 imei 号
- iOS 推送消息长度
- Xcode断点调试技巧
- iOS JS交互
- iOS 偏好设置-简单使用
- IOS Dev Intro - ARC Memory Leak
- iOS App开发中扩展RCLabel组件进行基于HTML的文本布局
- iOS TableView滚动时的视觉差效果