Xamarin原生聊天APP:iOS视频无法在Android播放及转码失败求助
解决Xamarin iOS端视频转码失败导致Picker卡顿的问题
咱们先理清楚核心问题:你现在要在iOS端发送视频前转码成Android兼容的格式,替代服务器转码,但现有代码执行时Picker卡在快照界面,转码失败,日志显示Export failed: The operation could not be completed,还有调试相关的System.NotSupportedException(这个大概率是调试器的问题,不是转码本身的核心错误)。
问题根源分析
- 转码预设选择错误:你用了
AVAssetExportSessionPreset.Passthrough,这个预设是直接复制原视频流,不做任何转码,等于没解决Android兼容的问题,而且如果原视频的容器或编码和你设置的AVFileType.Mpeg4不匹配,就会导致转码失败。 - UI操作线程问题:你在
ExportAsynchronously的回调里直接调用Picker.DismissViewControllerAsync(true),但这个回调是在后台线程执行的,UI操作必须在主线程,这可能导致Picker卡顿。 - 临时文件路径处理:虽然你用了临时路径,但直接创建
NSUrl的方式可能存在格式问题,影响文件写入权限。
修复后的代码示例
// 初始化Picker时,直接指定兼容的视频质量,去掉Passthrough预设 Picker = new UIImagePickerController() { SourceType = type, MediaTypes = UIImagePickerController.AvailableMediaTypes(type), VideoQuality = UIImagePickerControllerQualityType.Medium, VideoMaximumDuration = 120f }; // 选择视频后的处理逻辑 var srcUrl = e.Info[UIImagePickerController.MediaURL] as NSUrl; AVUrlAsset avAsset = new AVUrlAsset(srcUrl, null); // 用null代替空NSDictionary,简化参数 string[] compatiblePresets = AVAssetExportSession.ExportPresetsCompatibleWithAsset(avAsset); // 选择Android兼容的预设,比如MediumQuality(会自动转码为H.264+AAC的MP4) if (compatiblePresets.Contains(AVAssetExportSessionPreset.MediumQuality.GetConstant().ToString())) { AVAssetExportSession exportSession = new AVAssetExportSession(avAsset, AVAssetExportSessionPreset.MediumQuality); // 生成符合iOS要求的临时文件路径 string destFileName = $"{Guid.NewGuid()}.mp4"; string destPath = Path.Combine(Path.GetTempPath(), destFileName); exportSession.OutputUrl = NSUrl.FromFilename(destPath); // 用FromFilename确保路径格式正确 exportSession.OutputFileType = AVFileType.Mpeg4; exportSession.ShouldOptimizeForNetworkUse = true; exportSession.ExportAsynchronously(() => { // 所有UI操作必须回到主线程执行 InvokeOnMainThread(() => { switch (exportSession.Status) { case AVAssetExportSessionStatus.Failed: Console.WriteLine(@"Export failed: " + exportSession.Error.LocalizedDescription); Picker.DismissViewControllerAsync(true); break; case AVAssetExportSessionStatus.Cancelled: Console.WriteLine(@"Export canceled"); Picker.DismissViewControllerAsync(true); break; case AVAssetExportSessionStatus.Completed: // 转码成功,获取本地路径并发送 var localPath = exportSession.OutputUrl.Path; SendMedia(localPath, ChatMessageType.Video); Picker.DismissViewControllerAsync(true); break; default: Picker.DismissViewControllerAsync(true); break; } }); }); }
关键修改点说明
- 替换转码预设:把
Passthrough换成MediumQuality,这个预设会将视频转码为Android默认播放器完全兼容的H.264编码+AAC音频的标准MP4格式,从根源解决跨平台播放问题。 - 主线程处理UI:用
InvokeOnMainThread包裹所有UI操作(包括关闭Picker),避免后台线程操作UI导致的卡顿或异常。 - 优化路径创建:用
NSUrl.FromFilename替代直接实例化NSUrl,确保路径格式符合iOS文件系统要求,避免写入权限问题。 - 明确状态分支:单独处理
Completed状态,让逻辑更清晰,避免误判转码结果。
额外建议
- 转码开始前可以显示一个加载提示(比如
ActivityIndicator),让用户知道正在处理视频,提升交互体验。 - 测试不同来源的视频(比如系统相机录制、第三方APP拍摄的视频),确保所有场景下都能成功转码。
内容的提问来源于stack exchange,提问作者H_H
相关产品推荐
相关产品推荐

