使用 MediaCapture 存取相機預覽

本文說明如何在 WinUI 3 桌面應用程式中顯示相機預覽串流、處理專屬控制情境,以及管理應用程式生命週期事件。 若想快速了解如何顯示相機預覽,請參見「 在 WinUI 應用程式中顯示相機預覽」。

顯示相機預覽

在 WinUI 3 中,你會使用 MediaPlayerElement 來顯示攝影機預覽。 UWP CaptureElement 控制項在 WinUI 3 中無法使用。

在你的 XAML 頁面新增一個 MediaPlayerElement

<MediaPlayerElement x:Name="PreviewElement"
                    AutoPlay="True"
                    HorizontalAlignment="Stretch" />

初始化 MediaCapture

建立一個 MediaCapture 實例,並以所需的設定初始化它。 你可以透過設定 VideoDeviceID 來指定特定的攝影機裝置。

using Windows.Media.Capture;
using Windows.Devices.Enumeration;

private MediaCapture _mediaCapture;

private async Task InitializeCameraAsync()
{
    _mediaCapture = new MediaCapture();

    var settings = new MediaCaptureInitializationSettings
    {
        StreamingCaptureMode = StreamingCaptureMode.Video
    };

    // Optionally select a specific camera
    var devices = await DeviceInformation.FindAllAsync(
        DeviceClass.VideoCapture);

    if (devices.Count > 0)
    {
        settings.VideoDeviceId = devices[0].Id;
    }

    try
    {
        await _mediaCapture.InitializeAsync(settings);
    }
    catch (UnauthorizedAccessException)
    {
        // Camera access denied — prompt the user to enable camera
        // access in Windows Settings.
        return;
    }
}

預覽開始與結束

初始化 MediaCapture完成後,將相機 MediaPlayerElement 連接到預覽顯示器。 在 WinUI 3 中,使用 a MediaFrameSource 來向玩家傳送畫面:

using Windows.Media.Capture;
using Windows.Media.Capture.Frames;
using Microsoft.UI.Xaml.Controls;

private async Task StartPreviewAsync()
{
    // Get a frame source for the preview stream
    var frameSource = _mediaCapture.FrameSources.FirstOrDefault(
        source => source.Value.Info.MediaStreamType ==
            Windows.Media.Capture.MediaStreamType.VideoPreview
            || source.Value.Info.SourceKind ==
            MediaFrameSourceKind.Color);

    if (frameSource.Value != null)
    {
        var mediaSource = Windows.Media.Core.MediaSource
            .CreateFromMediaFrameSource(frameSource.Value);
        PreviewElement.Source = mediaSource;
    }
}

private async Task StopPreviewAsync()
{
    await _mediaCapture.StopPreviewAsync();
    PreviewElement.Source = null;
}

Note

在 WinUI 3 中,沒有 CaptureElement 控制功能。 而是透過從 MediaFrameSource 建立 MediaSource,將 MediaCapture 連接到 MediaPlayerElement。 這讓你能控制哪個畫面來源(前置鏡頭、後置鏡頭等)提供預覽。 請參閱 WinUI 應用程式中顯示相機預覽,了解如何使用 Windows 相機範例的推薦方法。

處理專屬控制

當其他應用程式獨佔攝影機控制時,你的 MediaCapture 實例會收到 失敗 事件。 例如,請在你的初始化方法中註冊此事件:

_mediaCapture.Failed += MediaCapture_Failed;

然後在事件發生時整理你的預覽:

private void MediaCapture_Failed(MediaCapture sender,
    MediaCaptureFailedEventArgs errorEventArgs)
{
    DispatcherQueue.TryEnqueue(async () =>
    {
        await StopPreviewAsync();
        // Display an error message to the user
    });
}

Important

在 WinUI 3 桌面應用程式中,可以用 DispatcherQueue.TryEnqueue 來將呼叫傳回 UI 執行緒。 UWP CoreDispatcher.RunAsync 方法無法使用。

處理視窗生命週期事件

在 WinUI 3 桌面應用程式中,即使視窗最小化或隱藏,相機資源仍保持活躍。 當視窗不可見時,你應該停止預覽,視窗再次顯示時再重新啟動。 在視窗建構函式或初始化方法中,註冊 VisibilityChanged 事件:

this.VisibilityChanged += Window_VisibilityChanged;

接著實作處理常式:

private async void Window_VisibilityChanged(object sender,
    Microsoft.UI.Xaml.WindowVisibilityChangedEventArgs args)
{
    if (args.Visible)
    {
        await StartPreviewAsync();
    }
    else
    {
        await StopPreviewAsync();
    }
}

清理資源

當視窗關閉時,停止預覽並釋放該 MediaCapture 實例。 例如,在你的視窗建構器中註冊事件 Closed

this.Closed += Window_Closed;

接著實作該處理常式:

private async void Window_Closed(object sender,
    Microsoft.UI.Xaml.WindowEventArgs args)
{
    await StopPreviewAsync();
    _mediaCapture?.Dispose();
    _mediaCapture = null;
}