频道栏目
首页 > 程序开发 > 移动开发 > 其他 > 正文
多段视频合并核心代码
2017-05-19 09:59:00      个评论    来源:flg1554112450的博客  
收藏   我要投稿

多段视频合并核心代码。//将所有分段视频合成为一段完整视频,并且裁剪为正方形包含所有视频分段的文件URL数组,必须是[NSURL fileURLWithString:...]得到的。

- (void)mergeAndExportVideosAtFileURLs:(NSArray *)fileArray{

/// fileArray 是多短视频的本地存储路径数组,,视频存于沙盒目录

NSMutableArray *fileURLArray = [NSMutableArray array];

//// fileArray里的视频路径是字符串类型,,转换成URL

for (NSString *str in fileArray) {

[fileURLArray addObject:[NSURL fileURLWithPath:str]];

}

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 *assetArray = [[NSMutableArray alloc] init];

for (NSURL *fileURL in fileURLArray) {

AVAsset *asset = [AVAsset assetWithURL:fileURL];

if (!asset) {

continue;

}

[assetArray addObject:asset];

NSArray *dataSourceArray = [NSArray arrayWithArray: [asset tracksWithMediaType:AVMediaTypeVideo]];

AVAssetTrack *assetTrack = ([dataSourceArray count]>0)?[dataSourceArray objectAtIndex:0]:nil;

[assetTrackArray addObject:assetTrack];

renderSize.width = MAX(renderSize.width, assetTrack.naturalSize.height);

renderSize.height = MAX(renderSize.height, assetTrack.naturalSize.width);

}

CGFloat renderW = MIN(renderSize.width, renderSize.height);

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] count]>0)?[[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0]:nil

atTime:totalDuration error:nil];

AVMutableCompositionTrack *videoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];

[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;

rate = renderW / MIN(assetTrack.naturalSize.width, assetTrack.naturalSize.height);

CGAffineTransform layerTransform = CGAffineTransformMake(assetTrack.preferredTransform.a, assetTrack.preferredTransform.b, assetTrack.preferredTransform.c, assetTrack.preferredTransform.d, assetTrack.preferredTransform.tx * 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];

[layerInstructionArray addObject:layerInstruciton];

}

//获取保存路径

NSString *timeStr = [CamerTool getVideoName]; /// 合并视频的存储名

NSURL *mergeFileURL = [NSURL fileURLWithPath:[[FLGfileManager shareManager] getVideoPath:timeStr]];

//导出合并的视频

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.renderSize = CGSizeMake(renderW, renderW);

#pragma mark // 录制视频压缩质量调整

AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetHighestQuality];

exporter.videoComposition = mainCompositionInst;

exporter.outputURL = mergeFileURL;

exporter.outputFileType = AVFileTypeMPEG4;

exporter.shouldOptimizeForNetworkUse = YES;

[exporter exportAsynchronouslyWithCompletionHandler:^{

// 如果导出的状态为完成

if ([exporter status] == AVAssetExportSessionStatusCompleted) {

dispatch_async(dispatch_get_main_queue(), ^{

NSLog(@"视频合并成功");

/// 反归档出合并视频名称的数组,,,,,沙盒路径每次启动会发生改变,,不能直接存视频路径,,存名称,,每次启动取出视频的时候重新拼接视频路径。。。

NSMutableArray *plist = [NSMutableArray array];

plist = [NSKeyedUnarchiver unarchiveObjectWithFile:[[FLGfileManager shareManager] getPathPlist]];

if (plist.count == 0) {

plist = [NSMutableArray arrayWithObject:timeStr];

}else{

[plist addObject:timeStr];

}

/// 将合并视频的名称数组归档到本地

[NSKeyedArchiver archiveRootObject:plist toFile:[[FLGfileManager shareManager] getPathPlist]];

//// 视频合并成功,,到播放器视频播放查看

VideoPlayViewController *video = [[VideoPlayViewController alloc] init];

video.videoUrl = mergeFileURL;

UINavigationController *nan = [[UINavigationController alloc] initWithRootViewController:video];

///视频合并成功删除子视频

[self presentViewController:nan animated:YES completion:^{

for (NSString *url in fileArray) {

/// 已知路径数组,,去删除好了

[[FLGfileManager shareManager] deleteVideo:url];

}

}];

});

}else if ([exporter status] == AVAssetExportSessionStatusFailed){

NSLog(@"视频合并失败");

}

}];

}

 

点击复制链接 与好友分享!回本站首页
上一篇:使用VideoToolBox硬解码MJPEG编码格式视频
下一篇:Unity 工程代码全部做成DLL
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站