| title | Show the camera preview in a WinUI app |
|---|---|
| description | Learn how to show the camera preview in a WinUI app. |
| ms.topic | article |
| ms.date | 06/14/2024 |
| ms.author | drewbat |
| author | drewbatgit |
| ms.localizationpriority | medium |
In this quickstart, you will learn how to create a basic WinUI camera app that displays the camera preview. In a WinUI app, you use the MediaPlayerElement control in the Microsoft.UI.Xaml.Controls namespace to render the camera preview and the WinRT class MediaCapture to access the device's camera preview stream. MediaCapture provides APIs for performing a wide range of camera-related tasks such as such as capturing photos and videos and configuring the camera's device driver. See the other articles in this section for details about other MediaCapture features.
The code in this walkthrough is adapted from the MediaCapture WinUI sample on github.
- Your device must have developer mode enabled. For more information see Settings for developers.
- Visual Studio 2026 or later with the WinUI application development workload.
In Visual Studio, create a new project. In the Create a new project dialog, set the language filter to "C#" and the platform filter to "Windows", then select the "WinUI Blank App (Packaged)" project template.
The simple UI for this example includes a MediaPlayerElement control for displaying the camera preview, a ComboBox that allows you to select from the device's cameras, and buttons for initializing the MediaCapture class, starting and stopping the camera preview, and resetting the sample. We also include a TextBlock for displaying status messages.
In your project's MainWindow.xml file, replace the default StackPanel control with the following XAML.
:::code language="xaml" source="~/../snippets-windows/winappsdk/audio-video-camera/camera-winui/CS/CameraWinUI/MainWindow.xaml" id="SnippetCameraWinUIXaml":::
The rest of the code in this article will be added to the MainWindow class definition in your project's MainWindow.xaml.cs file. First, add a few class variables that will persist throughout the lifetime of the window. These variables include:
- A DeviceInformationCollection that will store a DeviceInformation object for each available camera. The DeviceInformation object conveys information such as the unique identifier and the friendly name for the camera.
- A MediaCapture object that handles interactions with the selected camera's driver and allows you to retrieve the camera's video stream.
- A MediaFrameSource object that represents a source of media frames, such as a video stream.
- A boolean to track when the camera preview is running. Some camera settings can't be changed while the preview is running, so it's a good practice to track the state of the camera preview.
:::code language="csharp" source="~/../snippets-windows/winappsdk/audio-video-camera/camera-winui/CS/CameraWinUI/MainWindow.xaml.cs" id="SnippetCameraWinUIClassVars":::
Next we'll create a helper method to detect the cameras that are present on the current device and populate the ComboBox in the UI with the camera names, allowing the user to select a camera to preview.The DeviceInformation.FindAllAsync allows you to query for many different kinds of devices. We use MediaDevice.GetVideoCaptureSelector to retrieve the identifier that specifies that we only want to retrieve video capture devices.
:::code language="csharp" source="~/../snippets-windows/winappsdk/audio-video-camera/camera-winui/CS/CameraWinUI/MainWindow.xaml.cs" id="SnippetCameraWinUIPopulateCameraList":::
Add a call to this helper method to the MainWindow class constructor so that the ComboBox gets populated when the window loads.
:::code language="csharp" source="~/../snippets-windows/winappsdk/audio-video-camera/camera-winui/CS/CameraWinUI/MainWindow.xaml.cs" id="SnippetCameraWinUIConstructor":::
Initialize the MediaCapture object by calling InitializeAsync, passing in a MediaCaptureInitializationSettings object containing the requested initialization parameters. There are a lot of optional initialization parameters that enable different scenarios. See the API reference page for the complete list. In this simple example we specify a few basic settings, including:
- The VideoDeviceId property specifies the unique identifier of the camera that the MediaCapture will attach to. We get the device ID from the DeviceInformationCollection, using the selected index of the ComboBox.
- The SharingMode property specifies whether the app is requesting shared, read-only access to the camera, which allows you to view and capture from the video stream, or exclusive control of the camera, which allows you to change the camera configuration. Multiple apps can read from a camera simultaneously, but only one app at a time can have exclusive control.
- The StreamingCaptureMode property specifies whether we want to capture video, audio, or audio and video.
- The MediaCaptureMemoryPreference allows us to request to specifically use CPU memory for video frames. The value Auto lets the system use GPU memory if it's available.
Before initializing the MediaCapture object we call AppCapability.CheckAccess method to determine if the user has denied our app access to the camera in Windows Settings.
Note
Windows allows users to grant or deny access to the device's camera in Windows Settings, under Privacy & Security -> Camera. When initializing the capture device, apps should check whether they have access to the camera and handle the case where access is denied by the user. For more information, see Handle the Windows camera privacy setting.
The InitializeAsync call is made from inside a try block so that we can recover if initialization fails. Apps should handle initialization failure gracefully. In this simple example, we'll just display an error message on failure.
:::code language="csharp" source="~/../snippets-windows/winappsdk/audio-video-camera/camera-winui/CS/CameraWinUI/MainWindow.xaml.cs" id="SnippetCameraWinUIInitMediaCapture":::
When the user clicks the start preview button, we will attempt to create a MediaFrameSource for a video stream from the camera device with which the MediaCapture object was initialized. The available frame sources are exposed by the MediaCapture.FrameSources property.
To find a frame source that is color video data, as opposed to a depth camera for example, we look for a frame source that has a SourceKind of Color. Some camera drivers provide a dedicated preview stream that is separate from the record stream. To get the preview video stream, we try to select a frame source that has a MediaStreamType of VideoPreview. If no preview streams are found, we can get the record video stream by selecting a MediaStreamType of VideoRecord. If neither of these frame sources are available, then this capture device can't be used for video preview.
Once we have selected a frame source, we create a new MediaPlayer object that will be rendered by the MediaPlayerElement in our UI. We set the Source property of the MediaPlayer to a new MediaSource object we create from our selected MediaFrameSource.
Call Play on the MediaPlayer object to begin rendering the video stream.
:::code language="csharp" source="~/../snippets-windows/winappsdk/audio-video-camera/camera-winui/CS/CameraWinUI/MainWindow.xaml.cs" id="SnippetCameraWinUIStartPreview":::
Implement a handler for the MediaFailed event so that you can handle errors rendering the preview.
:::code language="csharp" source="~/../snippets-windows/winappsdk/audio-video-camera/camera-winui/CS/CameraWinUI/MainWindow.xaml.cs" id="SnippetCameraWinUIMediaFailed":::
To stop the camera preview, call Pause on the MediaPlayer object.
:::code language="csharp" source="~/../snippets-windows/winappsdk/audio-video-camera/camera-winui/CS/CameraWinUI/MainWindow.xaml.cs" id="SnippetCameraWinUIStopPreview":::
To make it easier to test out the sample app, add a method to reset the state of the app. Camera apps should always dispose of the camera and associated resources when the camera is no longer needed.
:::code language="csharp" source="~/../snippets-windows/winappsdk/audio-video-camera/camera-winui/CS/CameraWinUI/MainWindow.xaml.cs" id="SnippetCameraWinUIReset":::