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 では、 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 コントロールはありません。 代わりに、MediaCaptureからMediaPlayerElementを作成して、MediaSourceMediaFrameSourceに接続します。 これにより、プレビューを提供するフレーム ソース (フロント カメラ、リア カメラなど) を制御できます。 Windows カメラ サンプルを使用した推奨される方法については、「WinUI アプリでカメラ プレビューを表示する」を参照してください。

排他制御を処理する

別のアプリがカメラを排他的に制御すると、 MediaCapture インスタンスは Failed イベントを受け取ります。 たとえば初期化メソッドで、このイベントを登録します:

_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;
}