カメラ プレビューの表示Display the camera preview

この記事では、ユニバーサル Windows プラットフォーム (UWP) アプリで XAML ページ内にカメラ プレビュー ストリームをすばやく表示する方法について説明します。This article describes how to quickly display the camera preview stream within a XAML page in a Universal Windows Platform (UWP) app. カメラを使って写真やビデオをキャプチャするアプリを作成するには、デバイスとカメラの向きの処理や、キャプチャされたファイルのエンコーディング オプションの設定などのタスクを実行する必要があります。Creating an app that captures photos and videos using the camera requires you to perform tasks like handling device and camera orientation or setting encoding options for the captured file. アプリ シナリオによっては、このような他の考慮事項について考えなくても、カメラからプレビュー ストリームをそのまま表示することができます。For some app scenarios, you may want to just simply show the preview stream from the camera without worrying about these other considerations. この記事では、最小限のコードでそれを行う方法を示します。This article shows you how to do that with a minimum of code. プレビュー ストリームの操作が完了したら、必ず以下の手順に従ってプレビュー ストリームを正しくシャットダウンする必要がある点に注意してください。Note that you should always shut down the preview stream properly when you are done with it by following the steps below.

写真やビデオをキャプチャするカメラ アプリの作成方法について詳しくは、「MediaCapture を使った基本的な写真、ビデオ、およびオーディオのキャプチャ」をご覧ください。For information on writing a camera app that captures photos or videos, see Basic photo, video, and audio capture with MediaCapture.

アプリ マニフェストに機能宣言を追加するAdd capability declarations to the app manifest

アプリからデバイスのカメラにアクセスするには、アプリでデバイス機能 (webcammicrophone) の使用を宣言する必要があります。In order for your app to access a device's camera, you must declare that your app uses the webcam and microphone device capabilities.

アプリケーション マニフェストに機能を追加します。Add capabilities to the app manifest

  1. Microsoft Visual Studio のソリューション エクスプローラーで、package.appxmanifest 項目をダブルクリックしてアプリケーション マニフェストのデザイナーを開きます。In Microsoft Visual Studio, in Solution Explorer, open the designer for the application manifest by double-clicking the package.appxmanifest item.
  2. [機能] タブをクリックします。Select the Capabilities tab.
  3. [Web カメラ] のボックスと [マイク] のボックスをオンにします。Check the box for Webcam and the box for Microphone.

ページに CaptureElement コントロールを追加するAdd a CaptureElement to your page

CaptureElement を使って、XAML ページ内にプレビュー ストリームを表示します。Use a CaptureElement to display the preview stream within your XAML page.

<CaptureElement Name="PreviewControl" Stretch="Uniform"/>

MediaCapture を使ってプレビュー ストリームを開始するUse MediaCapture to start the preview stream

MediaCapture オブジェクトは、デバイスのカメラに対するアプリのインターフェイスです。The MediaCapture object is your app's interface to the device's camera. このクラスは、Windows.Media.Capture 名前空間のメンバーです。This class is a member of the Windows.Media.Capture namespace. この記事の例では、既定のプロジェクト テンプレートに含まれている API に加えて、Windows.ApplicationModel 名前空間と System.Threading.Tasks 名前空間の API も使われます。The example in this article also uses APIs from the Windows.ApplicationModel and System.Threading.Tasks namespaces, in addition to those included by the default project template.

ページの .cs ファイルに次の名前空間を含めるには using ディレクティブを追加します。Add using directives to include the following namespaces in your page's .cs file.

using Windows.UI.Core;
using Windows.UI.Xaml.Navigation;
using Windows.Media.Capture;
using Windows.ApplicationModel;
using System.Threading.Tasks;
using Windows.System.Display;
using Windows.Graphics.Display;

MediaCapture オブジェクトのクラス メンバー変数と、カメラが現在プレビューを表示しているかどうかを追跡するブール値を宣言します。Declare a class member variable for the MediaCapture object and a boolean to track whether the camera is currently previewing.

MediaCapture mediaCapture;
bool isPreviewing;

プレビューの実行中にディスプレイがオフになっていないことを確認するために使用する、DisplayRequest 型の変数を宣言します。Declare a variable of type DisplayRequest that will be used to make sure the display does not turn off while the preview is running.

DisplayRequest displayRequest = new DisplayRequest();

カメラのプレビューを起動するヘルパー メソッド (この例では StartPreviewAsync) を作成します。Create a helper method to start up the camera preview, called StartPreviewAsync in this example. アプリのシナリオによって、ページが読み込まれるときに呼び出される OnNavigatedTo イベント ハンドラーからこれを呼び出すことも、UI イベントへの応答でプレビューを待機して起動することもできます。Depending on your app's scenario, you may want to call this from the OnNavigatedTo event handler that is called when the page is loaded or wait and launch the preview in response to UI events.

MediaCapture クラスの新しいインスタンスを作成し、InitializeAsync を呼び出してキャプチャ デバイスを初期化します。Create a new instance of the MediaCapture class and call InitializeAsync to initialize the capture device. カメラがないデバイスなどではこのメソッドが失敗することがあるため、try ブロック内から呼び出してください。This method may fail, on devices that don't have a camera for example, so you should call it from within a try block. ユーザーがデバイスのプライバシー設定でカメラへのアクセスを無効にしている場合、カメラを初期化しようとすると UnauthorizedAccessException がスローされます。An UnauthorizedAccessException will be thrown when you attempt to initialize the camera if the user has disabled camera access in the device's privacy settings. この例外は、開発中、アプリ マニフェストに適切な機能を追加し忘れた場合も表示されます。You will also see this exception during development if you have neglected to add the proper capabilities to your app manifest.

重要: 一部のデバイス ファミリでは、アプリがデバイスのカメラへのアクセスを付与される前に、ユーザー同意のプロンプトがユーザーに表示されます。Important On some device families, a user consent prompt is displayed to the user before your app is granted access to the device's camera. このため、MediaCapture.InitializeAsync のみをメイン UI スレッドから呼び出す必要があります。For this reason, you must only call MediaCapture.InitializeAsync from the main UI thread. 別のスレッドからカメラを初期化しようとすると、初期化エラーになる可能性があります。Attempting to initialize the camera from another thread may result in initialization failure.

Source プロパティを設定して、MediaCaptureCaptureElement に接続します。Connect the MediaCapture to the CaptureElement by setting the Source property. StartPreviewAsync を呼び出してプレビューを開始します。Start the preview by calling StartPreviewAsync. 別のアプリがキャプチャ デバイスを排他的に制御している場合、このメソッドは FileLoadException をスローします。This method will throw a FileLoadException if another app has exclusive control of the capture device. 排他的制御での変更をリッスンについては、次のセクションを参照してください。See the next section for information listening for changes in exclusive control.

RequestActive を呼び出して、プレビューの実行中にデバイスがスリープ状態にならないことを確認します。Call RequestActive to make sure the device doesn't go to sleep while the preview is running. 最後に、DisplayInformation.AutoRotationPreferences プロパティを Landscape に設定して、ユーザーがデバイスの向きを変更したときに UI と CaptureElement が回転することを防ぎます。Finally, set the DisplayInformation.AutoRotationPreferences property to Landscape to prevent the UI and the CaptureElement from rotating when the user changes the device orientation. デバイスの向きの変更処理について詳しくは、「MediaCapture を使ってデバイスの向きを処理する」をご覧ください。For more information on handling device orientation changes, see Handle device orientation with MediaCapture.

       private async Task StartPreviewAsync()
       {
           try
           {

               mediaCapture = new MediaCapture();
               await mediaCapture.InitializeAsync();

               displayRequest.RequestActive();
               DisplayInformation.AutoRotationPreferences = DisplayOrientations.Landscape;
           }
           catch (UnauthorizedAccessException)
           {
               // This will be thrown if the user denied access to the camera in privacy settings
               ShowMessageToUser("The app was denied access to the camera");
               return;
           }

           try
           {
               PreviewControl.Source = mediaCapture;
               await mediaCapture.StartPreviewAsync();
               isPreviewing = true;
           }
           catch (System.IO.FileLoadException)
           {
               mediaCapture.CaptureDeviceExclusiveControlStatusChanged += _mediaCapture_CaptureDeviceExclusiveControlStatusChanged;
           }

       }

排他的制御での変更を処理するHandle changes in exclusive control

前のセクションで説明したように、別のアプリがキャプチャ デバイスを排他的に制御している場合、StartPreviewAsyncFileLoadException をスローします。As stated in the previous section, StartPreviewAsync will throw a FileLoadException if another app has exclusive control of the capture device. Windows 10 Version 1703 以降では、デバイスの排他的制御の状態が変化するたびに発生する MediaCapture.CaptureDeviceExclusiveControlStatusChanged イベントのハンドラーを登録できます。Starting with Windows 10, version 1703, you can register a handler for the MediaCapture.CaptureDeviceExclusiveControlStatusChanged event, which is raised whenever the exclusive control status of the device changes. このイベントのハンドラーで、MediaCaptureDeviceExclusiveControlStatusChangedEventArgs.Status プロパティを調べて、現在の状態を確認します。In the handler for this event, check the MediaCaptureDeviceExclusiveControlStatusChangedEventArgs.Status property to see what the current status is. 新しい状態が SharedReadOnlyAvailable である場合、現在プレビューを開始できないことがわかり、UI を更新してユーザーに警告することができます。If the new status is SharedReadOnlyAvailable, then you know you can't currently start the preview and you may want to update your UI to alert the user. 新しい状態が ExclusiveControlAvailable である場合は、カメラのプレビューを再試行することができます。If the new status is ExclusiveControlAvailable, then you can try starting the camera preview again.

private async void _mediaCapture_CaptureDeviceExclusiveControlStatusChanged(MediaCapture sender, MediaCaptureDeviceExclusiveControlStatusChangedEventArgs args)
{
    if (args.Status == MediaCaptureDeviceExclusiveControlStatus.SharedReadOnlyAvailable)
    {
        ShowMessageToUser("The camera preview can't be displayed because another app has exclusive access");
    }
    else if (args.Status == MediaCaptureDeviceExclusiveControlStatus.ExclusiveControlAvailable && !isPreviewing)
    {
        await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
        {
            await StartPreviewAsync();
        });
    }
}

プレビュー ストリームをシャットダウンするShut down the preview stream

プレビュー ストリームを使い終わったら、必ずストリームをシャットダウンして関連するリソースを適切に破棄し、デバイスで他のアプリがカメラを使うことができるようにしてください。When you are done using the preview stream, you should always shut down the stream and properly dispose of the associated resources to ensure that the camera is available to other apps on the device. プレビュー ストリームをシャットダウンするために必要な手順は次のとおりです。The required steps for shutting down the preview stream are:

  • 現在、カメラがプレビューを表示中の場合は、StopPreviewAsync を呼び出してプレビュー ストリームを停止します。If the camera is currently previewing, call StopPreviewAsync to stop the preview stream. プレビューが実行されていないときに StopPreviewAsync を呼び出すと、例外がスローされます。An exception will be thrown if you call StopPreviewAsync while the preview is not running.
  • CaptureElementSource プロパティを null に設定します。Set the Source property of the CaptureElement to null. CoreDispatcher.RunAsync を使用して、この呼び出しが UI スレッドで実行されることを確認します。Use CoreDispatcher.RunAsync to make sure this call is executed on the UI thread.
  • MediaCapture オブジェクトの Dispose メソッドを呼び出してオブジェクトを解放します。Call the MediaCapture object's Dispose method to release the object. 再度、CoreDispatcher.RunAsync を使用して、この呼び出しが UI スレッドで実行されることを確認します。Again, use CoreDispatcher.RunAsync to make sure this call is executed on the UI thread.
  • MediaCapture メンバー変数を null に設定します。Set the MediaCapture member variable to null.
  • RequestRelease を呼び出して、アクティブでないときに画面をオフにできるようにします。Call RequestRelease to allow the screen to turn off when inactive.
private async Task CleanupCameraAsync()
{
    if (mediaCapture != null)
    {
        if (isPreviewing)
        {
            await mediaCapture.StopPreviewAsync();
        }

        await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        {
            PreviewControl.Source = null;
            if (displayRequest != null)
            {
                displayRequest.RequestRelease();
            }

            mediaCapture.Dispose();
            mediaCapture = null;
        });
    }
    
}

OnNavigatedFrom メソッドをオーバーライドすることで、ユーザーがページから離れるときにプレビュー ストリームをシャットダウンする必要があります。You should shut down the preview stream when the user navigates away from your page by overriding the OnNavigatedFrom method.

protected async override void OnNavigatedFrom(NavigationEventArgs e)
{
    await CleanupCameraAsync();
}

アプリの中断中もプレビュー ストリームを適切にシャットダウンする必要があります。You should also shut down the preview stream properly when your app is suspending. これを行うには、ページのコンストラクターで Application.Suspending イベントのハンドラーを登録します。To do this, register a handler for the Application.Suspending event in your page's constructor.

public MainPage()
{
    this.InitializeComponent();

    Application.Current.Suspending += Application_Suspending;
}

Suspending イベント ハンドラーで、まずページの種類と CurrentSourcePageType プロパティを比較することで、アプリケーションの Frame にページが表示されることを確認します。In the Suspending event handler, first check to make sure that the page is being displayed the application's Frame by comparing the page type to the CurrentSourcePageType property. ページが現在表示されていない場合、OnNavigatedFrom イベントが既に発生しており、プレビュー ストリームはシャットダウンしています。If the page is not currently being displayed, then the OnNavigatedFrom event should already have been raised and the preview stream shut down. 現在ページが表示されている場合、ハンドラーに渡されるイベント引数から SuspendingDeferral オブジェクトを取得し、プレビュー ストリームがシャットダウンするまでシステムがアプリを中断しないことを確認します。If the page is currently being displayed, get a SuspendingDeferral object from the event args passed into the handler to make sure the system does not suspend your app until the preview stream has been shut down. ストリームをシャットダウンした後、保留の Complete メソッドを呼び出し、システムがアプリの中断を続行できるようにします。After shutting down the stream, call the deferral's Complete method to let the system continue suspending your app.

private async void Application_Suspending(object sender, SuspendingEventArgs e)
{
    // Handle global application events only if this page is active
    if (Frame.CurrentSourcePageType == typeof(MainPage))
    {
        var deferral = e.SuspendingOperation.GetDeferral();
        await CleanupCameraAsync();
        deferral.Complete();
    }
}