+ (void)mergeWithVideoPaths:(NSArray<NSString*> *)videoPathArray withOutPath:(NSString *)outPath isSaveToPhotos:(BOOL)isSaveToPhotos {
//若已存在目标输出文件 则直接返回掉。
NSURL *mergeFileURL = [NSURL fileURLWithPath:outPath];
if ([[NSFileManager defaultManager] fileExistsAtPath:outPath]) {
NSLog(@"[warning]文件已存在");
return;
}
AVMutableComposition *mixComposition = [AVMutableComposition composition];
//音频轨道。
AVMutableCompositionTrack *audioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
//视频轨道。
AVMutableCompositionTrack *videoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
CMTime totalDuration = kCMTimeZero;
for(int i=0; i < videoPathArray.count; i++) {
if (![[NSFileManager defaultManager] fileExistsAtPath:videoPathArray[i]]) {
NSLog(@"[error]_miss_source_file-%@", videoPathArray[i]);
return;
}
//AVURLAsset:此类主要用于获取多媒体的信息,包括视频和音频的类型、时长、每秒帧数,其实还可以用来获取视频的指定位置的缩略图。
//AVURLAsset *asset = [AVURLAsset assetWithURL:[NSURL URLWithString:videoPathArray[i]]];//error.
AVURLAsset *asset = [AVURLAsset assetWithURL:[NSURL fileURLWithPath:videoPathArray[i]]];
NSError *errorForAudio = nil;
//获取AVAsset中的音频。
AVAssetTrack *audioAssetTrack = [asset tracksWithMediaType:AVMediaTypeAudio].firstObject;
//向通道内加入音频。
BOOL bAudio = [audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration) ofTrack:audioAssetTrack atTime:totalDuration error:&errorForAudio];
NSLog(@"errorForAudio:%@%d", errorForAudio, bAudio);
NSError *errorForVideo = nil;//获取AVAsset中的视频。
AVAssetTrack *videoAssetTrack = [asset tracksWithMediaType:AVMediaTypeVideo].firstObject;
//向通道内加入视频。
BOOL bVideo = [videoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration) ofTrack:videoAssetTrack atTime:totalDuration error:&errorForVideo];
NSLog(@"errorForVideo:%@%d", errorForVideo, bVideo);
totalDuration = CMTimeAdd(totalDuration, asset.duration);
}
//这里开始导出合成之后的视频。
AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetHighestQuality];
exporter.outputURL = mergeFileURL;
NSLog(@"exporter.supportedFileTypes = %@", exporter.supportedFileTypes);
if ([outPath hasSuffix:@".mp4"]) {
exporter.outputFileType = AVFileTypeMPEG4;
} else {
exporter.outputFileType = AVFileTypeQuickTimeMovie;
}
exporter.shouldOptimizeForNetworkUse = YES;
[exporter exportAsynchronouslyWithCompletionHandler:^(void){
//导出的状态。
switch(exporter.status) {
case AVAssetExportSessionStatusUnknown:
NSLog(@"exporterUnknow.");
break;
case AVAssetExportSessionStatusCancelled:
NSLog(@"exporterCanceled.");
break;
case AVAssetExportSessionStatusFailed:
//导出失败。
NSLog(@"exporterFailed \\\' %@ \'/.", exporter.error.localizedDescription);
break;
case AVAssetExportSessionStatusWaiting:
NSLog(@"exporterWaiting.");
break;
case AVAssetExportSessionStatusExporting:
NSLog(@"exporterExporting.");
break;
case AVAssetExportSessionStatusCompleted:
//导出成功。
NSLog(@"exporterCompleted.");
dispatch_async(dispatch_get_main_queue(), ^{
//这里是回到你的主线程做一些事情。
if (isSaveToPhotos) {
//[CjhMediaManager saveVideoToPhotosWithWithUrl:exporter.outputURL];
}
});
break;
}
}];
}
来源: https://www.jianshu.com/p/e38db628ae0b
网友评论