Swift实现MOV转MP4报错Unsupported value for standard codec求助
解决iOS端MOV转MP4时的"Unsupported value for standard codec"异常
我开发的Flutter应用需要将视频上传至服务器,但iOS设备拍摄的MOV格式视频无法在Edge浏览器中播放。尝试用Swift代码将MOV转换为MP4时出现报错:
Error : Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Unsupported value for standard codec'
原代码片段:
let myArgs = args as? [String: Any] let movpath = myArgs?["movpath"] as? String let mp4Path = myArgs?["mp4path"] as? String let movurl = URL(fileURLWithPath: movpath!) let mp4url = URL(fileURLWithPath: mp4Path!) let avAsset = AVURLAsset(url: movurl, options: nil) //Create Export session let exportSession = AVAssetExportSession(asset: avAsset, presetName: AVAssetExportPresetPassthrough) // exportSession = AVAssetExportSession(asset: composition, presetName: mp4Quality) exportSession!.outputURL = mp4url exportSession!.outputFileType = AVFileType.mp4 exportSession!.shouldOptimizeForNetworkUse = true var start = CMTimeMakeWithSeconds(0.0,preferredTimescale: 0) var range = CMTimeRangeMake(start:start, duration: avAsset.duration) exportSession!.timeRange = range exportSession!.exportAsynchronously { result(exportSession!.outputURL) }
问题原因及修复方案
核心错误原因
使用AVAssetExportPresetPassthrough预设时,原MOV文件的编码格式(如ProRes或苹果专属编码)无法直接封装进MP4容器,编码器不兼容导致抛出异常;同时CMTimeMakeWithSeconds传入的preferredTimescale为0,属于非法参数,会引发时间范围配置错误。
具体修复步骤
- 替换导出预设:将
AVAssetExportPresetPassthrough替换为支持MP4的编码预设,比如AVAssetExportPresetHighestQuality或AVAssetExportPresetMediumQuality,这类预设会自动将视频转码为MP4兼容的H.264/H.265编码。 - 修复时间刻度参数:
CMTimeMakeWithSeconds的preferredTimescale需传入合法值(如AVFoundation常用的600),不能为0。 - 添加安全判断:移除强制解包操作,通过可选绑定避免空值崩溃;同时增加导出结果状态判断,处理失败场景。
修复后的代码:
guard let myArgs = args as? [String: Any], let movpath = myArgs["movpath"] as? String, let mp4Path = myArgs["mp4path"] as? String else { result(nil) return } let movurl = URL(fileURLWithPath: movpath) let mp4url = URL(fileURLWithPath: mp4Path) let avAsset = AVURLAsset(url: movurl, options: nil) // 使用兼容MP4的编码预设 guard let exportSession = AVAssetExportSession(asset: avAsset, presetName: AVAssetExportPresetHighestQuality) else { result(nil) return } exportSession.outputURL = mp4url exportSession.outputFileType = .mp4 exportSession.shouldOptimizeForNetworkUse = true // 修复时间刻度参数,使用合法值600 let start = CMTimeMakeWithSeconds(0.0, preferredTimescale: 600) let range = CMTimeRangeMake(start: start, duration: avAsset.duration) exportSession.timeRange = range exportSession.exportAsynchronously { // 处理导出结果 switch exportSession.status { case .completed: result(exportSession.outputURL) case .failed, .cancelled: print("导出失败: \(exportSession.error?.localizedDescription ?? "未知错误")") result(nil) default: result(nil) } }
补充说明
- 若需精准控制编码参数(如指定H.264编码),可使用
AVAssetWriter替代AVAssetExportSession,但实现复杂度更高。 - 导出前需确保目标路径的MP4文件不存在,否则会导出失败,可提前删除目标文件。
内容的提问来源于stack exchange,提问作者Anoop
相关产品推荐
相关产品推荐

