热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

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

本文主要介绍了iOS视频添加背景音乐同时保留原音的实现方法。具有很好的参考价值,下面跟着小编一起来看下吧

话不多说,请看代码:

//抽取原视频的音频与需要的音乐混合 
-(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; 
} 

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


推荐阅读
  • 本文节选自《NLTK基础教程——用NLTK和Python库构建机器学习应用》一书的第1章第1.2节,作者Nitin Hardeniya。本文将带领读者快速了解Python的基础知识,为后续的机器学习应用打下坚实的基础。 ... [详细]
  • Git Bash 配置 SSH 免密登录及 Gitee SSH 密钥设置
    本文详细介绍了如何在 Git Bash 中配置 SSH 免密登录,并将生成的 SSH 密钥添加到 Gitee 账户中,以实现无需每次输入密码即可进行代码推送。 ... [详细]
  • 如何在Windows内置的Ubuntu系统中更改SSH服务的端口号设置
    如何在Windows内置的Ubuntu系统中更改SSH服务的端口号设置 ... [详细]
  • 本文详细探讨了几种常用的Java后端开发框架组合及其具体应用场景。通过对比分析Spring Boot、MyBatis、Hibernate等框架的特点和优势,结合实际项目需求,为开发者提供了选择合适框架组合的参考依据。同时,文章还介绍了这些框架在微服务架构中的应用,帮助读者更好地理解和运用这些技术。 ... [详细]
  • SecureCRT是一款功能强大的终端仿真软件,支持SSH1和SSH2协议,适用于在Windows环境下高效连接和管理Linux服务器。该工具不仅提供了稳定的连接性能,还具备丰富的配置选项,能够满足不同用户的需求。通过SecureCRT,用户可以轻松实现对远程Linux系统的安全访问和操作。 ... [详细]
  • 服务器部署中的安全策略实践与优化
    服务器部署中的安全策略实践与优化 ... [详细]
  • 本文介绍了如何利用Shell脚本高效地部署MHA(MySQL High Availability)高可用集群。通过详细的脚本编写和配置示例,展示了自动化部署过程中的关键步骤和注意事项。该方法不仅简化了集群的部署流程,还提高了系统的稳定性和可用性。 ... [详细]
  • FreeBSD环境下PHP GD库安装问题的详细解决方案
    在 FreeBSD 环境下,安装 PHP GD 库时可能会遇到一些常见的问题。本文详细介绍了从配置到编译的完整步骤,包括解决依赖关系、配置选项以及常见错误的处理方法。通过这些详细的指导,开发者可以顺利地在 FreeBSD 上完成 PHP GD 库的安装,确保其正常运行。此外,本文还提供了一些优化建议,帮助提高安装过程的效率和稳定性。 ... [详细]
  • V8不仅是一款著名的八缸发动机,广泛应用于道奇Charger、宾利Continental GT和BossHoss摩托车中。自2008年以来,作为Chromium项目的一部分,V8 JavaScript引擎在性能优化和技术创新方面取得了显著进展。该引擎通过先进的编译技术和高效的垃圾回收机制,显著提升了JavaScript的执行效率,为现代Web应用提供了强大的支持。持续的优化和创新使得V8在处理复杂计算和大规模数据时表现更加出色,成为众多开发者和企业的首选。 ... [详细]
  • Nginx作为前端服务器时,Tomcat与Apache作为后端,War包应部署在何处? ... [详细]
  • 如何安装和使用 WinSCP 与 PuTTY:连接 Linux 系统的专业工具指南
    本指南详细介绍了如何在Windows环境中安装和使用WinSCP与PuTTY,以实现与Linux系统的安全连接。WinSCP是一款开源的图形化SFTP客户端,支持SSH和SCP协议,主要用于在本地和远程计算机之间安全地传输文件。用户可以通过官方下载页面获取最新版本的WinSCP和PuTTY,按照简单的步骤完成安装,并利用这些工具进行高效的文件管理和远程操作。 ... [详细]
  • 如何在任意浏览器中轻松安装并使用VSCode——Codeserver简易指南
    code-server 是一款强大的工具,允许用户在任何服务器上部署 VSCode,并通过浏览器进行访问和使用。这一解决方案不仅简化了开发环境的搭建过程,还提供了高度灵活的工作方式。用户只需访问 GitHub 上的官方仓库(GitHub-coder/code-server),即可获取详细的安装和配置指南,快速启动并运行 code-server。无论是个人开发者还是团队协作,code-server 都能提供高效、便捷的代码编辑体验。 ... [详细]
  • SSL 错误:目标主机名与备用证书主题名称不匹配
    在使用 `git clone` 命令时,常见的 SSL 错误表现为:无法访问指定的 HTTPS 地址(如 `https://ip_or_domain/xxxx.git`),原因是目标主机名与备用证书主题名称不匹配。这通常是因为服务器的 SSL 证书配置不正确或客户端的证书验证设置有问题。建议检查服务器的 SSL 证书配置,确保其包含正确的主机名,并确认客户端的证书信任库已更新。此外,可以通过临时禁用 SSL 验证来排查问题,但请注意这会降低安全性。 ... [详细]
  • 在开发过程中,我最初也依赖于功能全面但操作繁琐的集成开发环境(IDE),如Borland Delphi 和 Microsoft Visual Studio。然而,随着对高效开发的追求,我逐渐转向了更加轻量级和灵活的工具组合。通过 CLIfe,我构建了一个高度定制化的开发环境,不仅提高了代码编写效率,还简化了项目管理流程。这一配置结合了多种强大的命令行工具和插件,使我在日常开发中能够更加得心应手。 ... [详细]
  • 优化后的摘要:默认情况下,PopupWindow在点击外部区域时会自动关闭。为了实现点击外部区域时不自动关闭的功能,可以通过自定义设置来调整PopupWindow的行为,确保其在外部点击时仍保持显示状态。这需要对PopupWindow的属性进行适当的修改和配置,以满足特定的交互需求。 ... [详细]
author-avatar
手机用户2502931035
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有