Swift3 iOS中添加滤镜后的视频丢失音频问题求助
解决VideoEffects添加滤镜后视频丢失音频的问题
我太懂这个糟心的情况了——用VideoEffects库给相册视频加上滤镜,结果输出的视频居然没了声音,自己折腾加音频资源也没起效。别慌,咱们一步步把音频找回来!
问题根源
VideoEffects库的核心逻辑主要聚焦在视频画面的滤镜渲染上,默认流程里没同步处理音频轨道的导出,所以最后输出的视频就只剩画面,把音频给落下了。
解决方案:手动合并原视频音频到带滤镜的视频里
咱们需要在滤镜处理完视频画面后,把原视频的音频轨道提取出来,再和带滤镜的视频轨道合并成完整的视频。下面是具体的实现思路和代码:
步骤1:先完成滤镜处理(保留你原有的VideoEffects代码)
先按原来的逻辑用VideoEffects处理视频画面,生成带滤镜的无音频视频文件到videoOutputURL。
步骤2:用AVFoundation合并音频与视频
借助AVFoundation框架,把原视频的音频轨道和滤镜处理后的视频轨道合并:
import AVFoundation func mergeAudio(from originalVideoURL: URL, toFilteredVideoURL: URL, finalOutputURL: URL) throws { // 1. 初始化原视频和滤镜后视频的Asset对象 let originalAsset = AVURLAsset(url: originalVideoURL) let filteredVideoAsset = AVURLAsset(url: toFilteredVideoURL) // 2. 获取原视频的音频轨道和滤镜后视频的视频轨道 guard let audioTrack = originalAsset.tracks(withMediaType: .audio).first else { throw NSError(domain: "AudioMissingError", code: 0, userInfo: [NSLocalizedDescriptionKey: "原视频没有音频轨道"]) } guard let videoTrack = filteredVideoAsset.tracks(withMediaType: .video).first else { throw NSError(domain: "VideoMissingError", code: 0, userInfo: [NSLocalizedDescriptionKey: "滤镜处理后的视频没有视频轨道"]) } // 3. 创建可变合成对象,用来组合音视频轨道 let composition = AVMutableComposition() // 添加视频轨道到合成对象 let videoCompositionTrack = composition.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid)! try videoCompositionTrack.insertTimeRange(CMTimeRange(start: .zero, duration: filteredVideoAsset.duration), of: videoTrack, at: .zero) // 添加音频轨道到合成对象 let audioCompositionTrack = composition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid)! try audioCompositionTrack.insertTimeRange(CMTimeRange(start: .zero, duration: originalAsset.duration), of: audioTrack, at: .zero) // 4. 配置导出会话 let exporter = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetHighestQuality)! exporter.outputURL = finalOutputURL exporter.outputFileType = .mp4 exporter.shouldOptimizeForNetworkUse = true // 5. 执行导出操作 exporter.exportAsynchronously { switch exporter.status { case .completed: print("音频合并成功!最终视频路径:\(finalOutputURL)") // 这里可以添加导出完成后的逻辑,比如保存到相册或者通知用户 case .failed: print("导出失败:\(exporter.error?.localizedDescription ?? "未知错误")") case .cancelled: print("导出被取消") default: break } } }
步骤3:调用合并函数
在你原来的滤镜处理完成后,调用上面的合并函数即可:
// originalVideoURL是你从相册选取的原视频路径 let originalVideoURL = // 你的原视频URL let finalOutputURL = documentDirectory.appendingPathComponent("Final_Output_\(timeDateFormatter.string(from: Date())).mp4") do { try mergeAudio(from: originalVideoURL, toFilteredVideoURL: videoOutputURL, finalOutputURL: finalOutputURL) } catch { print("合并音频失败:\(error.localizedDescription)") }
几个注意点
- 先确认原视频本身带有音频轨道,不然合并操作也没用哦
- 导出预设可以根据需求调整,比如要更小的文件可以用
AVAssetExportPresetMediumQuality - 确保App已经获取了相册访问权限和文档目录的写入权限
这样处理后,你得到的视频就既有滤镜效果,又能保留原视频的音频啦!
内容的提问来源于stack exchange,提问作者Anand Gautam
相关产品推荐
相关产品推荐

