WinUI3应用相机预览接收器设置:如何配置及未自动设置原因?
WinUI3相机预览启停实现方案
你遇到的「Preview sink not set」异常,核心原因是WinUI3的MediaPlayerElement无法像UWP的CaptureElement那样自动关联MediaCapture的预览接收器,直接调用StartPreviewAsync()会因为没有绑定有效的预览输出目标而报错。以下是正确的实现步骤:
1. XAML布局
使用Image控件承载预览画面,搭配启停按钮:
<Grid> <Image x:Name="PreviewImage" Stretch="UniformToFill"/> <StackPanel VerticalAlignment="Bottom" HorizontalAlignment="Center" Orientation="Horizontal" Margin="0,0,0,20"> <Button x:Name="StartPreviewBtn" Content="启动预览" Click="StartPreviewBtn_Click" Margin="10"/> <Button x:Name="StopPreviewBtn" Content="停止预览" Click="StopPreviewBtn_Click" Margin="10" IsEnabled="False"/> </StackPanel> </Grid>
2. C#逻辑实现
通过MediaFrameReader获取相机帧并渲染到Image控件,替代StartPreviewAsync()的方式:
声明全局变量
private MediaCapture _mediaCapture; private MediaFrameReader _frameReader; private SoftwareBitmapSource _bitmapSource;
启动预览按钮事件
private async void StartPreviewBtn_Click(object sender, RoutedEventArgs e) { _mediaCapture = new MediaCapture(); var initSettings = new MediaCaptureInitializationSettings { StreamingCaptureMode = StreamingCaptureMode.Video, SharingMode = MediaCaptureSharingMode.ExclusiveControl }; try { await _mediaCapture.InitializeAsync(initSettings); // 获取摄像头的彩色帧源 var frameSource = _mediaCapture.FrameSources.Values .FirstOrDefault(s => s.Info.SourceKind == MediaFrameSourceKind.Color); if (frameSource == null) { return; } // 创建帧读取器并订阅帧到达事件 _frameReader = await _mediaCapture.CreateFrameReaderAsync(frameSource); _frameReader.FrameArrived += FrameReader_FrameArrived; // 启动帧读取 var startStatus = await _frameReader.StartAsync(); if (startStatus != MediaFrameReaderStatus.Success) { return; } StartPreviewBtn.IsEnabled = false; StopPreviewBtn.IsEnabled = true; } catch (Exception ex) { // 自行添加异常提示逻辑 System.Diagnostics.Debug.WriteLine($"启动预览失败:{ex.Message}"); } }
帧到达事件处理(渲染画面)
private async void FrameReader_FrameArrived(MediaFrameReader sender, MediaFrameArrivedEventArgs args) { using (var frame = sender.TryAcquireLatestFrame()) { if (frame?.VideoMediaFrame?.SoftwareBitmap == null) { return; } // 转换为SoftwareBitmapSource支持的BGRA8格式 using (var convertedBitmap = SoftwareBitmap.Convert( frame.VideoMediaFrame.SoftwareBitmap, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore)) { await DispatcherQueue.EnqueueAsync(() => { if (_bitmapSource == null) { _bitmapSource = new SoftwareBitmapSource(); PreviewImage.Source = _bitmapSource; } _bitmapSource.SetBitmapAsync(convertedBitmap); }); } } }
停止预览按钮事件
private async void StopPreviewBtn_Click(object sender, RoutedEventArgs e) { if (_frameReader != null) { await _frameReader.StopAsync(); _frameReader.FrameArrived -= FrameReader_FrameArrived; _frameReader.Dispose(); _frameReader = null; } if (_mediaCapture != null) { _mediaCapture.Dispose(); _mediaCapture = null; } _bitmapSource = null; PreviewImage.Source = null; StartPreviewBtn.IsEnabled = true; StopPreviewBtn.IsEnabled = false; }
3. 权限配置
在Package.appxmanifest中添加摄像头权限:
<Capabilities> <DeviceCapability Name="webcam" /> </Capabilities>
关键说明
- WinUI3中没有UWP的
CaptureElement控件,无法直接将MediaCapture赋值给UI控件的Source,必须通过MediaFrameReader手动获取并渲染帧。 - 不要调用
MediaCapture.StartPreviewAsync(),该方法需要绑定UWP专属的预览接收器,WinUI3环境下无法直接使用。
内容的提问来源于stack exchange,提问作者Xeena
相关产品推荐
相关产品推荐

