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

AVAssetExportSession转MP4为M4A:模拟器成功真机失败求助

MP4转M4A真机失败的问题解决思路

问题回顾

在iOS应用中使用AVAssetExportSession将MP4视频转换为M4A音频格式时,模拟器(iOS15.5/16.1)运行正常,但iPhone7(iOS15.7.1)及iOS16.1真机均失败,报错为AVFoundationErrorDomain Code=-11800,底层错误码-16979。输入URL来自iCloud Drive的文件应用。

转换代码如下:

let outputUrl = URL(fileURLWithPath: NSTemporaryDirectory() + "out.m4a")
if FileManager.default.fileExists(atPath: outputUrl.path) {
    try? FileManager.default.removeItem(atPath: outputUrl.path)
}

let asset = AVURLAsset(url: inputUrl)
// 试过`AVAssetExportPresetAppleM4A`预设,结果一样
let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetPassthrough)!
exportSession.outputFileType = AVFileType.m4a
exportSession.outputURL = outputUrl

await exportSession.export()
switch exportSession.status {
case .completed:
    return outputUrl
default:
    // 状态值为4,对应.failed
    print("Status: \(exportSession.status)")
    throw exportSession.error!
}

完整报错信息:

Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo={NSUnderlyingError=0x2808f30c0 {Error Domain=NSOSStatusErrorDomain Code=-16979 "(null)"}, NSLocalizedFailureReason=An unknown error occurred (-16979), NSLocalizedRecoverySuggestion=XXXXDEFAULTVALUEXXXX, NSURL=file:///private/var/mobile/Library/Mobile%20Documents/com~apple~CloudDocs/Downloads/%E3%81%8A%E3%81%97%E3%82%83%E3%81%B8%E3%82%99%E3%82%8A%E3%81%B2%E3%82%8D%E3%82%86%E3%81%8D.mp4, NSLocalizedDescription=The operation could not be completed}

可能的原因及解决方法

1. 文件权限问题(最常见)

从UIDocumentPickerViewController获取的iCloud文件URL需要持久化安全范围权限,真机沙箱机制严格,没有权限会导致文件访问失败,模拟器因沙箱限制宽松不会触发该问题。

解决代码:

// 获取inputUrl后,保存书签数据以持久化权限
if let bookmarkData = try? inputUrl.bookmarkData(options: .withSecurityScope, includingResourceValuesForKeys: nil, relativeTo: nil) {
    UserDefaults.standard.set(bookmarkData, forKey: "VideoFileBookmark")
}

// 后续使用URL时,恢复权限并访问
if let bookmarkData = UserDefaults.standard.data(forKey: "VideoFileBookmark") {
    var isStale = false
    guard let restoredUrl = try? URL(resolvingBookmarkData: bookmarkData, options: .withSecurityScope, relativeTo: nil, bookmarkDataIsStale: &isStale) else {
        return
    }
    // 开始访问安全范围资源
    restoredUrl.startAccessingSecurityScopedResource()
    // 用restoredUrl替代原inputUrl进行AVAsset操作
    let asset = AVURLAsset(url: restoredUrl)
    // 操作完成后必须停止访问
    defer { restoredUrl.stopAccessingSecurityScopedResource() }
}

2. 输出URL生成不规范

直接拼接字符串生成临时文件URL可能存在编码或路径识别问题,改用系统API生成更可靠:

let tempDir = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
let outputUrl = tempDir.appendingPathComponent("out.m4a")

3. 导出预设选择不当

AVAssetExportPresetPassthrough要求原视频的音频编码与M4A完全兼容,若原MP4音频编码不支持透传会直接失败。建议改用AVAssetExportPresetAppleM4A,该预设会自动处理编码转换:

let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetAppleM4A)!
exportSession.outputFileType = .m4a
// 可选:指定音频比特率优化输出质量
exportSession.audioBitRate = 128000

4. 检查原视频的音频轨道

部分MP4可能无音频轨道或音频轨道损坏,先验证资产的音频轨道有效性:

let asset = AVURLAsset(url: inputUrl)
let audioTracks = asset.tracks(withMediaType: .audio)
if audioTracks.isEmpty {
    print("视频无有效音频轨道")
    return
}

验证步骤

  1. 优先添加权限持久化代码,确保能正常访问iCloud文件;
  2. 替换输出URL的生成方式;
  3. 切换到AVAssetExportPresetAppleM4A预设;
  4. 检查原视频是否包含有效音频轨道。

内容的提问来源于stack exchange,提问作者Toru

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 19:01:21