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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 07:47:37