欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

iOS视频添加背景音乐同时保留原音

程序员文章站 2023-12-20 12:46:34
话不多说,请看代码: //抽取原视频的音频与需要的音乐混合 -(void)addmusic:(id)sender { [mbprogresshuds...

话不多说,请看代码:

//抽取原视频的音频与需要的音乐混合 
-(void)addmusic:(id)sender 
{ 
 [mbprogresshudshowhudaddedto:self.viewanimated:yes]; 

 avmutablecomposition *composition =[avmutablecompositioncomposition]; 
 audiomixparams =[[nsmutablearrayalloc]initwithobjects:nil]; 

 //录制的视频 
 nsurl *video_inputfileurl =[nsurlfileurlwithpath:self.videopath]; 
 avurlasset *songasset =[avurlasseturlassetwithurl:video_inputfileurloptions:nil]; 
 cmtime starttime =cmtimemakewithseconds(0,songasset.duration.timescale); 
 cmtime trackduration =songasset.duration; 

 //获取视频中的音频素材 
 [selfsetupandaddaudioatpath:video_inputfileurltocomposition:compositionstart:starttimedura:trackdurationoffset:cmtimemake(14*44100,44100)]; 

 //本地要插入的音乐 
 nsstring *bundledirectory =[[nsbundlemainbundle]bundlepath]; 
 nsstring *path = [bundledirectorystringbyappendingpathcomponent:@"30secs.mp3"]; 
 nsurl *asseturl2 =[nsurlfileurlwithpath:path]; 
 //获取设置完的本地音乐素材 
 [selfsetupandaddaudioatpath:asseturl2tocomposition:compositionstart:starttimedura:trackdurationoffset:cmtimemake(0,44100)]; 

 //创建一个可变的音频混合 
 avmutableaudiomix *audiomix =[avmutableaudiomixaudiomix]; 
 audiomix.inputparameters =[nsarrayarraywitharray:audiomixparams];//从数组里取出处理后的音频轨道参数 

 //创建一个输出 
 avassetexportsession *exporter =[[avassetexportsessionalloc] 
        initwithasset:composition 
        presetname:avassetexportpresetapplem4a]; 
 exporter.audiomix = audiomix; 
 exporter.outputfiletype=@"com.apple.m4a-audio"; 
 nsstring* filename =[nsstringstringwithformat:@"%@.mov",@"overmix"]; 
 //输出路径 
 nsstring *exportfile =[nsstringstringwithformat:@"%@/%@",[selfgetlibaraypath], filename]; 

 if([[nsfilemanagerdefaultmanager]fileexistsatpath:exportfile]) { 
  [[nsfilemanagerdefaultmanager]removeitematpath:exportfileerror:nil]; 
 } 
 nslog(@"是否在主线程1%d",[nsthreadismainthread]); 
 nslog(@"输出路径===%@",exportfile); 

 nsurl *exporturl =[nsurlfileurlwithpath:exportfile]; 
 exporter.outputurl = exporturl; 
 self.mixurl =exporturl; 

 [exporterexportasynchronouslywithcompletionhandler:^{ 
  int exportstatus =(int)exporter.status; 
  switch (exportstatus){ 
   caseavassetexportsessionstatusfailed:{ 
    nserror *exporterror =exporter.error; 
    nslog(@"错误,信息: %@", exporterror); 
    [mbprogresshudhidehudforview:self.viewanimated:yes]; 
    break; 
   } 
   caseavassetexportsessionstatuscompleted:{ 
    nslog(@"是否在主线程2%d",[nsthreadismainthread]); 
    nslog(@"成功"); 
    //最终混合 
    [selfthevideowithmixmusic]; 
    break; 
   } 
  } 
 }]; 
} 

//最终音频和视频混合 
-(void)thevideowithmixmusic 
{ 
 nserror *error =nil; 
 nsfilemanager *filemgr =[nsfilemanagerdefaultmanager]; 
 nsstring *documentsdirectory =[nshomedirectory() 
        stringbyappendingpathcomponent:@"documents"]; 
 nsstring *videooutputpath =[documentsdirectorystringbyappendingpathcomponent:@"test_output.mp4"]; 
 if ([filemgrremoveitematpath:videooutputpatherror:&error]!=yes) { 
  nslog(@"无法删除文件,错误信息:%@",[error localizeddescription]); 
 } 

 //声音来源路径(最终混合的音频) 
 nsurl *audio_inputfileurl =self.mixurl; 

 //视频来源路径 
 nsurl *video_inputfileurl = [nsurlfileurlwithpath:self.videopath]; 

 //最终合成输出路径 
 nsstring *outputfilepath =[documentsdirectorystringbyappendingpathcomponent:@"final_video.mp4"]; 
 nsurl *outputfileurl = [nsurlfileurlwithpath:outputfilepath]; 

 if([[nsfilemanagerdefaultmanager]fileexistsatpath:outputfilepath]) 
  [[nsfilemanagerdefaultmanager]removeitematpath:outputfilepatherror:nil]; 

 cmtime nextclipstarttime =kcmtimezero; 

 //创建可变的音频视频组合 
 avmutablecomposition* mixcomposition =[avmutablecompositioncomposition]; 

 //视频采集 
 avurlasset* videoasset =[[avurlassetalloc]initwithurl:video_inputfileurloptions:nil]; 
 cmtimerange video_timerange =cmtimerangemake(kcmtimezero,videoasset.duration); 
 avmutablecompositiontrack*a_compositionvideotrack = [mixcompositionaddmutabletrackwithmediatype:avmediatypevideopreferredtrackid:kcmpersistenttrackid_invalid]; 
 [a_compositionvideotrackinserttimerange:video_timerangeoftrack:[[videoassettrackswithmediatype:avmediatypevideo]objectatindex:0]attime:nextclipstarttimeerror:nil]; 

 //声音采集 
 avurlasset* audioasset =[[avurlassetalloc]initwithurl:audio_inputfileurloptions:nil]; 
 cmtimerange audio_timerange =cmtimerangemake(kcmtimezero,videoasset.duration);//声音长度截取范围==视频长度 
 avmutablecompositiontrack*b_compositionaudiotrack = [mixcompositionaddmutabletrackwithmediatype:avmediatypeaudiopreferredtrackid:kcmpersistenttrackid_invalid]; 
 [b_compositionaudiotrackinserttimerange:audio_timerangeoftrack:[[audioassettrackswithmediatype:avmediatypeaudio]objectatindex:0]attime:nextclipstarttimeerror:nil]; 

 //创建一个输出 
 avassetexportsession* _assetexport =[[avassetexportsessionalloc]initwithasset:mixcompositionpresetname:avassetexportpresetmediumquality]; 
 _assetexport.outputfiletype =avfiletypequicktimemovie; 
 _assetexport.outputurl =outputfileurl; 
 _assetexport.shouldoptimizefornetworkuse=yes; 
 self.theendvideourl=outputfileurl; 

 [_assetexportexportasynchronouslywithcompletionhandler: 
 ^(void ) { 
  [mbprogresshudhidehudforview:self.viewanimated:yes]; 
  //播放 
  nsurl*url = [nsurlfileurlwithpath:outputfilepath]; 
  mpmovieplayerviewcontroller *themovie =[[mpmovieplayerviewcontrolleralloc]initwithcontenturl:url]; 
  [selfpresentmovieplayerviewcontrolleranimated:themovie]; 
  themovie.movieplayer.moviesourcetype=mpmoviesourcetypefile; 
  [themovie.movieplayerplay]; 
 } 
 ]; 
 nslog(@"完成!输出路径==%@",outputfilepath); 
} 

//通过文件路径建立和添加音频素材 
- (void)setupandaddaudioatpath:(nsurl*)asseturltocomposition:(avmutablecomposition*)composition start:(cmtime)startdura:(cmtime)duraoffset:(cmtime)offset{ 

 avurlasset *songasset =[avurlasseturlassetwithurl:asseturloptions:nil]; 

 avmutablecompositiontrack *track =[compositionaddmutabletrackwithmediatype:avmediatypeaudiopreferredtrackid:kcmpersistenttrackid_invalid]; 
 avassettrack *sourceaudiotrack =[[songassettrackswithmediatype:avmediatypeaudio]objectatindex:0]; 

 nserror *error =nil; 
 bool ok =no; 

 cmtime starttime = start; 
 cmtime trackduration = dura; 
 cmtimerange trange =cmtimerangemake(starttime,trackduration); 

 //设置音量 
 //avmutableaudiomixinputparameters(输入参数可变的音频混合) 
 //audiomixinputparameterswithtrack(音频混音输入参数与轨道) 
 avmutableaudiomixinputparameters *trackmix =[avmutableaudiomixinputparametersaudiomixinputparameterswithtrack:track]; 
 [trackmixsetvolume:0.8fattime:starttime]; 

 //素材加入数组 
 [audiomixparamsaddobject:trackmix]; 

 //insert audio into track //offsetcmtimemake(0, 44100) 
 ok = [trackinserttimerange:trangeoftrack:sourceaudiotrackattime:kcmtimeinvaliderror:&error]; 
} 

 #pragma mark - 保存路径 
-(nsstring*)getlibaraypath 
{ 
 nsfilemanager *filemanager =[nsfilemanagerdefaultmanager]; 
 nsarray* paths =nssearchpathfordirectoriesindomains(nsdocumentdirectory,nsuserdomainmask,yes); 
 nsstring* path = [pathsobjectatindex:0]; 
 nsstring *movdirectory = [pathstringbyappendingpathcomponent:@"tmpmovmix"]; 
 [filemanagercreatedirectoryatpath:movdirectorywithintermediatedirectories:yesattributes:nilerror:nil]; 
 return movdirectory; 
} 

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!

上一篇:

下一篇: