/**
* 合成视频输出到指定路径,注意区分是否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();
});
}];
}
使用AVMutableComposition将声音与视频合成一个视频
最新推荐文章于 2021-06-08 15:16:47 发布