You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:40:06