NSBundle *mainBundle = [NSBundle mainBundle];
NSString *firstVideo = [mainBundle pathForResource:@"prefixSourceVideo" ofType:@"mp4"];
NSArray *tArray = @[[NSURL fileURLWithPath:firstVideo],movUrl]; // 注意:只能合并多个本地的视频
/**
* 多个视频合成为一个视频输出到指定路径,注意区分是否3D视频
*
* @param tArray 视频文件NSURL地址
* @param storePath 沙盒目录下的文件夹名字
* @param storeName 合成的文件名字
* @param tbool 是否3D视频,YES表示是3D视频
* @param successBlock 成功block
* @param failureBlcok 失败block
*/
-(void)mergeVideoToOneVideo:(NSArray *)tArray toStorePath:(NSString *)storePath WithStoreName:(NSString *)storeName andIf3D:(BOOL)tbool success:(void (^)(void))successBlock failure:(void (^)(void))failureBlcok
{
weakSelf(self)
AVMutableComposition *mixComposition = [self mergeVideostoOnevideo:tArray success:^(AVMutableComposition* composition){
NSURL *outputFileUrl = [weakSelf joinStorePaht:storePath togetherStoreName:storeName];
[weakSelf storeAVMutableComposition:composition withStoreUrl:outputFileUrl andVideoUrl:[tArray objectAtIndex:0] WihtName:storeName andIf3D:tbool success:successBlock failure:failureBlcok];
} failure:^{
}];
}
/**
* 多个视频合成为一个
*
* @param array 多个视频的NSURL地址
*
* @return 返回AVMutableComposition
*/
-(AVMutableComposition *)mergeVideostoOnevideo:(NSArray*)array success:(void (^)(AVMutableComposition* composition))successBlock failure:(void (^)(void))failureBlcok
{
AVMutableComposition* mixComposition = [AVMutableComposition composition];
//合成视频轨道
AVMutableCompositionTrack *a_compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
Float64 tmpDuration =0.0f;
NSError *error;
for (NSInteger i=0; i
{
AVURLAsset *videoAsset = [[AVURLAsset alloc]initWithURL:array[i] options:nil];
CMTimeRange video_timeRange = CMTimeRangeMake(kCMTimeZero,videoAsset.duration);
/**
* 依次加入每个asset
*
* @param TimeRange 加入的asset持续时间
* @param Track 加入的asset类型,这里都是video
* @param Time 从哪个时间点加入asset,这里用了CMTime下面的CMTimeMakeWithSeconds(tmpDuration, 0),timesacle为0
*
*/
BOOL tbool = [a_compositionVideoTrack insertTimeRange:video_timeRange ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:CMTimeMakeWithSeconds(tmpDuration, 0) error:&error];
tmpDuration += CMTimeGetSeconds(videoAsset.duration);
}
if (error == nil) {
if (successBlock) {
successBlock(mixComposition);
}
}
else {
if (failureBlcok) {
failureBlcok();
}
}
return mixComposition;
}
/**
* 拼接url地址
*
* @param sPath 沙盒文件夹名
* @param sName 文件名称
*
* @return 返回拼接好的url地址
*/
-(NSURL *)joinStorePaht:(NSString *)sPath togetherStoreName:(NSString *)sName
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentPath = [paths objectAtIndex:0];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *storePath = [documentPath stringByAppendingPathComponent:sPath];
BOOL isExist = [fileManager fileExistsAtPath:storePath];
if(!isExist){
[fileManager createDirectoryAtPath:storePath withIntermediateDirectories:YES attributes:nil error:nil];
}
NSString *realName = [NSString stringWithFormat:@"%@.mp4", sName];
storePath = [storePath stringByAppendingPathComponent:realName];
NSURL *outputFileUrl = [NSURL fileURLWithPath:storePath];
return outputFileUrl;
}
/**
* 存储合成的视频,以及转mp4格式带压缩
*
* @param mixComposition mixComposition参数 ( 当其是AVURLAsset类时——仅转码压缩,,AVMutableComposition类时——合并视频,进行的转码压缩同时导出操作 )
* @param storeUrl 存储的路径 (完整的url路径)
* @param successBlock successBlock
* @param failureBlcok failureBlcok
*/
-(void)storeAVMutableComposition:(id)mixComposition withStoreUrl:(NSURL *)storeUrl andVideoUrl:(NSURL *)videoUrl WihtName:(NSString *)aName andIf3D:(BOOL)tbool success:(void (^)(void))successBlock failure:(void (^)(void))failureBlcok
{
__weak typeof(self) welf = self;
NSLog(@"操作类型%@", [mixComposition class]);
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc]
initWithAsset:mixComposition
presetName:AVAssetExportPresetMediumQuality];
self.exportSession = exportSession;
exportSession.outputURL = storeUrl;
exportSession.shouldOptimizeForNetworkUse = YES;
exportSession.outputFileType = AVFileTypeMPEG4;
dispatch_semaphore_t wait = dispatch_semaphore_create(0l);
// [self showHudInView:self.view hint:@"正在压缩"];
// __weak typeof(self) weakSelf = self;
[exportSession exportAsynchronouslyWithCompletionHandler:^{
// [weakSelf hideHud];
switch ([exportSession status]) {
case AVAssetExportSessionStatusFailed: {
NSLog(@"failed, error:%@.", exportSession.error);
if (failureBlcok) {
failureBlcok();
}
} break;
case AVAssetExportSessionStatusCancelled: {
NSLog(@"cancelled.");
} break;
case AVAssetExportSessionStatusCompleted: {
NSLog(@"completed.");
NSLog(@"%@-%f",self.progressLabel.text,self.hud.progress);
if (successBlock) {
successBlock();
}
} break;
case AVAssetExportSessionStatusExporting: {
NSLog(@"Exporting");
}
break;
default: {
NSLog(@"others.");
} break;
}
dispatch_semaphore_signal(wait);
}];
long timeout = dispatch_semaphore_wait(wait, DISPATCH_TIME_FOREVER);
if (timeout) {
NSLog(@"timeout.");
}
if (wait) {
//dispatch_release(wait);
wait = nil;
}
}
http://blog.csdn.net/hhxxhbmy/article/details/48175319