Xamarin相机视频质量调整与大视频无损压缩上传问题求助
Hey there! Let's tackle your two Xamarin video-related issues one by one:
From your code snippet, I can see you're using the CrossMedia plugin—great choice! Adjusting video quality is straightforward by configuring StoreVideoOptions when calling TakeVideoAsync. Here's how to update your existing code:
private async void TakeVideo_Clicked(object sender, EventArgs e) { if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakeVideoSupported) { await DisplayAlert("Oops", "No camera available.", "OK"); return; } // Configure video quality and optimization settings var videoOptions = new StoreVideoOptions { Quality = VideoQuality.Medium, // Pick Low/Medium/High for preset levels // Use CustomVideoSize if you want to lock to a specific resolution (e.g., 1080p) CustomVideoSize = new VideoSize { Width = 1920, Height = 1080 }, FrameRate = 30, // Standard 30fps balances smoothness and file size CompressionQuality = 75, // Adjust between 0-100 (higher = better quality/larger file) SaveToAlbum = true, Directory = "MyAppVideos" }; var file = await CrossMedia.Current.TakeVideoAsync(videoOptions); if (file == null) return; await DisplayAlert("Video Saved!", $"Path: {file.Path}", "OK"); }
Quick tips:
VideoQuality.Highdelivers maximum quality but creates larger files—stick withMediumfor most everyday use cases.CustomVideoSizelets you avoid overshooting resolution (e.g., using 4K when 1080p is sufficient) which cuts down file size immediately.
A 2-minute video hitting 300MB means your current setup is using an unoptimized codec or extremely high bitrate. Let's fix this with two approaches:
Option 1: Optimize during capture (prevent large files upfront)
Build on the settings from the first question, and add platform-specific bitrate controls to cap file size without losing quality:
For Android, tweak the bitrate directly in platform-specific options:
var androidVideoOptions = new AndroidStoreVideoOptions { BitRate = 5_000_000, // 5 Mbps is ideal for 1080p video (visually lossless) Quality = VideoQuality.Medium, CustomVideoSize = new VideoSize { Width = 1920, Height = 1080 } }; var file = await CrossMedia.Current.TakeVideoAsync(androidVideoOptions);
For iOS, the preset quality levels already handle bitrate optimization well, but you can refine further post-capture (see Option 2).
Option 2: Compress existing videos post-capture
If you already have large videos, use cross-platform libraries or native APIs to re-encode them efficiently:
Using Xamarin.FFmpeg (cross-platform solution)
First, install the Xamarin.FFmpeg NuGet package, then use this code to compress videos with H.264 (the gold standard for balanced quality/size):
var inputPath = file.Path; var outputPath = Path.Combine(Path.GetDirectoryName(inputPath), $"compressed_{Path.GetFileName(inputPath)}"); // FFmpeg command: Visually lossless compression with H.264 video and AAC audio var arguments = $"-i \"{inputPath}\" -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k \"{outputPath}\""; var result = await FFmpeg.ExecuteAsync(arguments); if (result == 0) { await DisplayAlert("Success!", "Video compressed without quality loss.", "OK"); // Use outputPath for your upload logic } else { await DisplayAlert("Error", "Compression failed. Check FFmpeg logs for details.", "OK"); }
- CRF 23: The default for H.264, it delivers visually identical quality to the original while cutting file size drastically.
- Preset:
mediumbalances compression speed and file size—useslowfor smaller files (takes longer) orfastfor quicker results.
Using iOS-native AVAssetExportSession
For iOS-specific optimization, use Apple's built-in export session:
public async Task<string> CompressiOSVideo(string inputPath) { var asset = AVAsset.FromUrl(NSUrl.FromFilename(inputPath)); var exportSession = new AVAssetExportSession(asset, AVAssetExportPresetMediumQuality); var outputPath = Path.Combine(Path.GetDirectoryName(inputPath), $"compressed_{Path.GetFileName(inputPath)}"); exportSession.OutputUrl = NSUrl.FromFilename(outputPath); exportSession.OutputFileType = AVFileType.Mpeg4; exportSession.ShouldOptimizeForNetworkUse = true; var tcs = new TaskCompletionSource<string>(); exportSession.ExportAsynchronously(() => { if (exportSession.Status == AVAssetExportSessionStatus.Completed) tcs.SetResult(outputPath); else tcs.SetException(new Exception($"Export failed: {exportSession.Error.LocalizedDescription}")); exportSession.Dispose(); }); return await tcs.Task; }
内容的提问来源于stack exchange,提问作者Swathy

