最近接触英语学习类app,根据视频跟读句子,完成配音作业,然后将自己的多个录音和原视频合成为一个新的视频。
之前看过几篇类似的博客,都是写一个视频和一个音频合成,要么是一个视频去掉音频,提取音频之类的。但是都没有多个音频根据时间节点拼接到原有的视频中去,或者理解为替换该节点的音频。
⚠️⚠️最近发现一个问题,iphoneXR/iphoneXS音频和视频合并会失败,主要错在于输出的地方;
Error Domain=AVFoundationErrorDomain Code=-11821 “Cannot Decode” UserInfo={NSLocalizedFailureReason=The media data could not be decoded. It may be damaged., NSLocalizedDescription=Cannot Decode, NSUnderlyingError=0x28338c4e0 {Error Domain=NSOSStatusErrorDomain Code=-16977 “(null)“}}
发现有用ffmpeg编码遇到用c++写的,一个是在stackOverflow上看到的, 但是都没有解决方案!!!试过很多办法测试,各种设置参数,后面发现是“presetName”导致的,只能是AVAssetExportPresetPassthrough才能成功; AVAssetExportSession* _assetExport =[[AVAssetExportSession alloc]initWithAsset:mixComposition presetName:AVAssetExportPresetPassthrough];然后顺利结局。。。。。。
不明白的地方欢迎➕抠:【3376512101】
一、思路
第一步:将分别提取原视频的音频(Ymp3)、视频(Ymp4);
第二步:将自己的多个录音根据时间节点依次合成到提取的原音频(Ymp3)中去,最后合成为一个新的音频(Xmp3);
第三部:将合成的新音频(Xmp3)和提取的原视频(Ymp4)重新合成为一个新的视频(Perfect.mp4);
⚠️⚠️-------之前有地方写错,这里还给大家再理一下思路,感觉之前说的不是很清楚。 主要讲第二步;
多个录音和原音频合并是可以有三种方式:
- 先把原音频轨道根据每段规定的时候先截取掉,然后再把每段录音根据时间插入原音频轨道;
- 在插入每段录音之前先删除音频轨道上的该时间段,然后再把每段录音根据时间插入原音频轨道;(和第一种其实相同)
- 一个取巧的办法,就是在把每段录音创建一个新的音频轨道,然后将原音频轨道该时间段的声音调到0,然后再把这些新音频轨道和原音频轨道合并;AVMutableCompositionTrack * audioTrack = [_composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
- 【以下为参考代码】
二、代码
@interface HJMergeVideoWithMusic : NSObject {
NSInteger mergeIndex;//合并到了第几个
NSArray * musicUrlArray;//所有的音频
NSArray * _musicStartTimes;//音频的时间段
NSString * _videoPath;//视频地址
AVMutableCompositionTrack * _audio_track;//视频中的音频文件
AVMutableComposition *_composition;
NSMutableArray *_audioMixParams;
}
@property (nonatomic, strong)UIView *baseView;
+ (instancetype)shared;
/**
没有背景音乐的视频添加背景音乐
@param musicPath 背景音乐地址
@param videoPath 视频地址
@param savePath 保存视频地址
@param successBlock 合成成功
*/
+ (void)mergeVideoWithMusic:(NSString *)musicPath noBgMusicVideo:(NSString *)videoPath saveVideoPath:(NSString *)savePath success:(void(^)(NSURL *recordPath))successBlock;
//抽取原视频的音频与需要的音乐混合
/**
音频视频合成
@param musicArrayPath 音频(可以是多个,多个时可支撑替换某一段的音频)
@param musicStartTime 音频的时间段,起始时间
@param videoPath 视频
@param savePath 保存地址
@param successBlock 合成成功
*/
- (void)mergeVideoWithMusicArray:(NSArray *)musicArrayPath musicStartTime:(NSArray *)musicStartTimes video:(NSString *)videoPath success:(void(^)(NSURL *recordPath))successBlock;
@end
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^【.m文件】^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@implementation HJMergeVideoWithMusic
static HJMergeVideoWithMusic *manager;
/*
单例模式
*/
+ (instancetype)shared {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager = [HJMergeVideoWithMusic new];
});
return manager;
}
/**
没有背景音乐的视频添加背景音乐
@param musicPath 背景音乐地址
@param videoPath 视频地址
@param savePath 保存视频地址
@param successBlock 合成成功
*/
+ (void)mergeVideoWithMusic:(NSString *)musicPath noBgMusicVideo:(NSString *)videoPath saveVideoPath:(NSString *)savePath success:(void(^)(NS