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

iPhone如何播放3GPP视频?AVFoundation转3GPP为MP4报错怎么解决

问题原因

你当前报错的核心原因是使用了AVAssetExportPresetPassthrough导出预设:这个预设的逻辑是不对媒体流做任何编解码转换,直接将源流封装到目标容器中。但Twilio返回的3GPP文件通常采用AMR音频、H.263这类编码,AVFoundation不支持直接将这类编码的流无转码封装到MP4容器,因此抛出不支持媒体操作的错误。

转码失败修复方案

把导出预设从AVAssetExportPresetPassthrough替换为实际触发编解码的预设,同时增加兼容性校验逻辑,修正后的代码如下:

func encodeVideo(videoURL: URL){
    let avAsset = AVURLAsset(url: videoURL)
    // 先校验资源是否有可读取的音视频轨道
    guard avAsset.tracks(withMediaType: .video).isEmpty == false || avAsset.tracks(withMediaType: .audio).isEmpty == false else {
        print("无效的媒体资源")
        return
    }
    let startDate = Date()
    // 替换passthrough为转码预设,可根据需求选低/中/高画质,或者指定分辨率预设
    guard let exportSession = AVAssetExportSession(asset: avAsset, presetName: AVAssetExportPresetHighestQuality) else {
        print("不支持当前导出预设")
        return
    }
    
    let docDir2 = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
    let filePath = docDir2.appendingPathComponent("rendered-Video.mp4")
    deleteFile(filePath)
    
    // 校验当前资源是否支持导出为MP4格式
    guard exportSession.supportedFileTypes.contains(.mp4) else {
        print("不支持导出为MP4格式")
        return
    }
    exportSession.outputURL = filePath
    exportSession.outputFileType = .mp4
    exportSession.shouldOptimizeForNetworkUse = true
    exportSession.timeRange = CMTimeRangeMake(start: .zero, duration: avAsset.duration)
    
    exportSession.exportAsynchronously{
        DispatchQueue.main.async {
            switch exportSession.status{
            case .failed:
                print("导出失败:\(exportSession.error!)")
            case .cancelled:
                print("导出取消")
            case .completed:
                let endDate = Date()
                let time = endDate.timeIntervalSince(startDate)
                print("导出耗时:\(time)")
                print("导出成功")
                print(exportSession.outputURL ?? "")
            default:
                break
            }
        }
    }
}

func deleteFile(_ filePath:URL) {
    guard FileManager.default.fileExists(atPath: filePath.path) else{
        return
    }
    do {
        try FileManager.default.removeItem(atPath: filePath.path)
    }catch{
        print("删除文件失败:\(error)")
    }
}

直接播放3GPP格式的方案

iOS原生AVPlayer本身完全支持3GPP格式播放,不需要额外转码,只要确认下载到本地的3GPP文件完整、扩展名正确(.3gp或者.3gpp),直接传入AVPlayer即可播放,示例代码如下:

import AVKit
// 直接播放本地3GPP文件
func play3gppVideo(url: URL) {
    let player = AVPlayer(url: url)
    let playerVC = AVPlayerViewController()
    playerVC.player = player
    // 这里弹出播放器控制器即可
    present(playerVC, animated: true) {
        player.play()
    }
}

注意事项

  • 转码前建议先校验AVAsset的音视频轨道是否存在,避免下载的文件损坏导致报错
  • 如果对画质要求不高,可以选择更低档位的转码预设(比如AVAssetExportPresetMediumQuality)减少转码耗时
  • 大文件转码时建议添加进度监听,给用户明确的进度提示

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 23:15:02