카메라 미리 보기 표시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

앱이 장치 카메라에 액세스 하려면 앱에서 웹캠마이크 장치 기능을 사용 하도록 선언 해야 합니다.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. 웹캠 확인란과 마이크 상자를 선택합니다.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. 이 문서의 예제에서는 기본 프로젝트 템플릿에 포함 된 네임 스페이스 외에도 Windows applicationmodel 및 System.xml 네임 스페이스의 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.

Using 지시문을 추가 하 여 페이지의 .cs 파일에 다음 네임 스페이스를 포함 합니다.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. 앱의 시나리오에 따라 페이지를 로드 하거나 대기 하 고 UI 이벤트에 대 한 응답으로 미리 보기를 시작할 때 호출 되는 OnNavigatedTo 이벤트 처리기에서 호출 하는 것이 좋습니다.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. 사용자가 장치의 개인 정보 설정에서 카메라 액세스를 사용 하지 않도록 설정한 경우 카메라를 초기화 하려고 하면 system.unauthorizedaccessexception 이 throw 됩니다.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. 따라서 주 UI 스레드에서만 MediaCapture.InitializeAsync 를 호출 해야 합니다.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 을 throw 합니다.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 속성을 displayproperties.autorotationpreferences 로 설정 하 여 사용자가 장치 방향을 변경할 때 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 을 throw 합니다.As stated in the previous section, StartPreviewAsync will throw a FileLoadException if another app has exclusive control of the capture device. Windows 10, 버전 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 속성을 확인 하 여 현재 상태를 확인 합니다.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 를 호출 하면 예외가 throw 됩니다.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 를 사용 하 여이 호출이 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을 사용 하 여이 호출이 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. 이렇게 하려면 페이지의 생성자에서 응용 프로그램을 일시 중단 하는 이벤트에 대 한 처리기를 등록 합니다.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;
}

일시 중단 이벤트 처리기에서 먼저 페이지 유형을 CurrentSourcePageType 속성과 비교 하 여 페이지가 응용 프로그램의 프레임 에 표시 되는지 확인 합니다.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();
    }
}