您的位置:首页 > 其它

使用AVMutableComposition将声音与视频合成一个视频

2015-09-02 10:33 375 查看
/**
*  合成视频输出到指定路径,注意区分是否3D视频
*
*  @param audioUrl     音频文件url
*  @param videoUrl     视频文件url
*  @param storePath    沙盒目录下的文件夹
*  @param storeName    合成的文件名字
*  @param tbool        是否3D视频,YES表示是3D视频
*  @param successBlock 成功block
*  @param failureBlcok 失败block
*/
-(void)mergeAudio:(NSURL*)audioUrl andVideo:(NSURL *)videoUrl toStorePath:(NSString *)storePath WithStoreName:(NSString *)storeName andIf3D:(BOOL)tbool success:(void (^)(void))successBlock failure:(void (^)(void))failureBlcok
{
AVMutableComposition *mixComposition = [self mergeAudio:audioUrl andVideo:videoUrl];
NSURL *outputFileUrl = [self joinStorePaht:storePath togetherStoreName:storeName];
[self storeAVMutableComposition:mixComposition withStoreUrl:outputFileUrl andVideoUrl:videoUrl WihtName:storeName andIf3D:tbool success:successBlock failure:failureBlcok];
}

/**
*  音频视频合成得到AVMutableComposition,以较短文件长度作为时间长度
*
*  @param audioUrl 音频文件
*  @param videoUrl 视频文件
*
*  @return AVMutableComposition
*/
-(AVMutableComposition *)mergeAudio:(NSURL*)audioUrl andVideo:(NSURL *)videoUrl
{
AVMutableComposition* mixComposition = [AVMutableComposition composition];

AVURLAsset *audioAsset = [[AVURLAsset alloc]initWithURL:audioUrl options:nil];
AVURLAsset *videoAsset = [[AVURLAsset alloc]initWithURL:videoUrl options:nil];

CMTime ctime;

if (CMTimeGetSeconds(audioAsset.duration)>=CMTimeGetSeconds(videoAsset.duration))
{
ctime = videoAsset.duration;
}else
{
ctime = audioAsset.duration;
}

CMTimeRange audio_timeRange = CMTimeRangeMake(kCMTimeZero, ctime);

AVMutableCompositionTrack *b_compositionAudioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[b_compositionAudioTrack insertTimeRange:audio_timeRange ofTrack:[[audioAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:kCMTimeZero error:nil];

CMTimeRange video_timeRange = CMTimeRangeMake(kCMTimeZero,ctime);

AVMutableCompositionTrack *a_compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
[a_compositionVideoTrack insertTimeRange:video_timeRange ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:kCMTimeZero error:nil];
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;
}
/**
*  存储合成的视频
*
*  @param mixComposition mixComposition参数
*  @param storeUrl       存储的路径
*  @param successBlock   successBlock
*  @param failureBlcok   failureBlcok
*/
-(void)storeAVMutableComposition:(AVMutableComposition*)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;
AVAssetExportSession* _assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetHighestQuality];
_assetExport.outputFileType = @"com.apple.quicktime-movie";
//    _assetExport.outputFileType = @"public.mpeg-4";
_assetExport.outputURL = storeUrl;
[_assetExport exportAsynchronouslyWithCompletionHandler:^{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//在系统相册存储一份
UISaveVideoAtPathToSavedPhotosAlbum([storeUrl path], nil, nil, nil);
//            在本地沙盒中存储一份,存储成功返回YES,如果不想存到沙盒,直接返回调用<span style="font-family: Arial, Helvetica, sans-serif;">successBlock();</span>
//                        BOOL successful = [welf.photoStore storeVideoImageScale:videoUrl WihtName:aName andIf3D:tbool];
//                        dispatch_async(dispatch_get_main_queue(), ^{
//                            if (successful) {
//                                successBlock();
//                            }else
//                            {
//                                failureBlcok();
//                            }
//                        });
successBlock();
});
}];
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息