代码如下,导入框架#import <AVFoundation/AVFoundation.h>
//给视频配音,startTime表示开始时刻,取值范围 0-1
+ (void)dubForVideoWith:(NSURL *)fileUrl
audioUrl:(NSURL *)audioUrl
startTime:(CGFloat)startTime
success:(void(^)(NSURL *url))success
fail:(void(^)(NSString *error))fail {
//先检测文件是否存在
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:fileUrl.path] || ![fileManager fileExistsAtPath:audioUrl.path]) {
if (fail) {
fail(@"不存在该资源,无法合成");
}
return;
}
//开始合成
//获取资源
AVAsset *videoAsset = [AVAsset assetWithURL:fileUrl];
AVAsset *audioAsset = [AVAsset assetWithURL:audioUrl];
//剪辑操作类
AVMutableComposition *mixComposition = [[AVMutableComposition alloc] init];
//视音频轨道的插入、删除和拓展接口
AVMutableCompositionTrack *videoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
AVMutableCompositionTrack *audioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
//插入视频,此时视频是没有声音的,只有画面
[videoTrack insertTimeRange:CMTimeRangeFromTimeToTime(kCMTimeZero, videoAsset.duration) ofTrack:[videoAsset tracksWithMediaType:AVMediaTypeVideo].firstObject atTime:kCMTimeZero error:nil];
//插入音频,当音频时长小于视频时长时候会导致视频后半段没有声音
CGFloat totalTime = audioAsset.duration.value / audioAsset.duration.timescale; //音频总时长
CGFloat startValue = totalTime * startTime; //第几秒开始
CGFloat timeScale = audioAsset.duration.timescale; //帧率
//保护
startValue = MAX(startValue, 0);
startValue = MIN(startValue, audioAsset.duration.value);
//计算出插入时间
CMTime atTime = CMTimeMakeWithSeconds(startValue, timeScale);
//在计算出的插入时间开始插入音频
[audioTrack insertTimeRange:CMTimeRangeFromTimeToTime(kCMTimeZero, audioAsset.duration) ofTrack:[audioAsset tracksWithMediaType:AVMediaTypeAudio].firstObject atTime:atTime error:nil];
//输出路径
NSTimeInterval current = [[NSDate date] timeIntervalSince1970];
NSString *outputPath = [NSString stringWithFormat:@"%@/tmp/%ld.mp4",NSHomeDirectory(),(NSInteger)current]; //临时文件路径
unlink([outputPath UTF8String]);
NSURL *outputUrl = [NSURL fileURLWithPath:outputPath];
//导出
AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition
presetName:AVAssetExportPresetHighestQuality];
exporter.outputURL=outputUrl;
exporter.outputFileType = AVFileTypeQuickTimeMovie;
exporter.shouldOptimizeForNetworkUse = YES;
[exporter exportAsynchronouslyWithCompletionHandler:^{
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"导出操作完成");
if ([fileManager fileExistsAtPath:outputPath]) {
NSLog(@"合成成功");
if (success) {
success(outputUrl);
}
}else {
if (fail) {
fail(@"文件不存在,合成失败,请在合成代码中寻找原因");
}
}
});
}];
}
网友评论