Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En este inicio rápido, aprenderá a crear una aplicación básica de cámara WinUI 3 que muestre la vista previa de la cámara. En una aplicación WinUI 3, usas el control MediaPlayerElement en el espacio de nombres Microsoft.UI.Xaml.Controls para representar la vista previa de la cámara y la clase WinRT MediaCapture para acceder a la secuencia de vista previa de la cámara del dispositivo. MediaCapture proporciona API para realizar una amplia gama de tareas relacionadas con la cámara, como capturar fotos y vídeos y configurar el controlador de dispositivo de la cámara. Consulte los otros artículos de esta sección para obtener más información sobre otras características de MediaCapture .
El código de esta guía se adapta del ejemplo de MediaCapture en WinUI 3 en GitHub.
Sugerencia
Para obtener la versión de UWP de este artículo, consulta Mostrar la vista previa de la cámara en la documentación de UWP.
Prerrequisitos
- El dispositivo debe tener habilitado el modo de desarrollador. Para obtener más información, consulte Configuración para desarrolladores.
- Visual Studio 2022 o posterior con la carga de trabajo de desarrollo de aplicaciones WinUI.
Creación de una aplicación WinUI 3
En Visual Studio, cree un nuevo proyecto. En el cuadro de diálogo Crear un nuevo proyecto , establezca el filtro de lenguaje en "C#" y el filtro de plataforma en "Windows", seleccione la plantilla de proyecto "Aplicación vacía, empaquetada (WinUI 3 en el escritorio)".
Creación de la interfaz de usuario
La interfaz de usuario sencilla de este ejemplo incluye un control MediaPlayerElement para mostrar la vista previa de la cámara, un ComboBox que permite seleccionar entre las cámaras del dispositivo y botones para inicializar la clase MediaCapture , iniciar y detener la vista previa de la cámara y restablecer la muestra. También se incluye un TextBlock para mostrar mensajes de estado.
En el archivo MainWindow.xml del proyecto, reemplace el control StackPanel predeterminado por el código XAML siguiente.
<Grid ColumnDefinitions="4*,*" ColumnSpacing="4">
<MediaPlayerElement x:Name="mpePreview" Grid.Row="0" Grid.Column="0" AreTransportControlsEnabled="False" ManipulationMode="None"/>
<StackPanel Orientation="Vertical" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Top">
<TextBlock Text="Status:" Margin="0,0,10,0"/>
<TextBlock x:Name="tbStatus" Text=""/>
<TextBlock Text="Preview Source:" Margin="0,0,10,0"/>
<ComboBox x:Name="cbDeviceList" HorizontalAlignment="Stretch" SelectionChanged="cbDeviceList_SelectionChanged"></ComboBox>
<Button x:Name="bStartMediaCapture" Content="Initialize MediaCapture" IsEnabled="False" Click="bStartMediaCapture_Click"/>
<Button x:Name="bStartPreview" Content="Start preview" IsEnabled="False" Click="bStartPreview_Click"/>
<Button x:Name="bStopPreview" Content="Stop preview" IsEnabled="False" Click="bStopPreview_Click"/>
<Button x:Name="bReset" Content="Reset" Click="bReset_Click" />
</StackPanel>
</Grid>
Actualización de la definición de la clase MainWindow
El resto del código de este artículo se agregará a la definición de clase MainWindow en el archivo MainWindow.xaml.cs del proyecto. En primer lugar, agregue algunas variables de clase que se conservarán durante toda la vigencia de la ventana. Estas variables incluyen:
- DeviceInformationCollection que almacenará un objeto DeviceInformation para cada cámara disponible. El objeto DeviceInformation transmite información como el identificador único y el nombre descriptivo de la cámara.
- Un objeto MediaCapture que controla las interacciones con el controlador de la cámara seleccionada y le permite recuperar la secuencia de vídeo de la cámara.
- Objeto MediaFrameSource que representa un origen de fotogramas multimedia, como una secuencia de vídeo.
- Boolean para realizar un seguimiento cuando se ejecuta la vista previa de la cámara. Algunas configuraciones de cámara no se pueden cambiar mientras se ejecuta la vista previa, por lo que es recomendable realizar un seguimiento del estado de la vista previa de la cámara.
private DeviceInformationCollection m_deviceList;
private MediaCapture m_mediaCapture;
private MediaFrameSource m_frameSource;
private MediaPlayer m_mediaPlayer;
private bool m_isPreviewing;
Rellenar la lista de cámaras disponibles
A continuación, crearemos un método auxiliar para detectar las cámaras que están presentes en el dispositivo actual y rellenaremos el ComboBox en la interfaz de usuario con los nombres de cámara, lo que permite al usuario seleccionar una cámara para obtener una vista previa. DeviceInformation.FindAllAsync permite consultar muchos tipos diferentes de dispositivos. Usamos MediaDevice.GetVideoCaptureSelector para recuperar el identificador que especifica que solo queremos recuperar dispositivos de captura de vídeo.
private async void PopulateCameraList()
{
cbDeviceList.Items.Clear();
m_deviceList = await DeviceInformation.FindAllAsync(MediaDevice.GetVideoCaptureSelector());
if(m_deviceList.Count == 0)
{
tbStatus.Text = "No video capture devices found.";
return;
}
foreach (var device in m_deviceList)
{
cbDeviceList.Items.Add(device.Name);
bStartMediaCapture.IsEnabled = true;
}
}
Agregue una llamada a este método auxiliar al constructor de clase MainWindow para que el ComboBox se rellene cuando se cargue la ventana.
public MainWindow()
{
this.InitializeComponent();
PopulateCameraList();
}
Inicialización del objeto MediaCapture
Inicialice el objeto MediaCapture llamando a InitializeAsync, pasando un objeto MediaCaptureInitializationSettings que contiene los parámetros de inicialización solicitados. Hay muchos parámetros de inicialización opcionales que permiten diferentes escenarios. Consulte la página de referencia de API para obtener la lista completa. En este ejemplo sencillo se especifican algunas opciones básicas, entre las que se incluyen:
- La propiedad VideoDeviceId especifica el identificador único de la cámara a la que se asociará MediaCapture . Obtenemos el identificador de dispositivo de DeviceInformationCollection mediante el índice seleccionado de ComboBox.
- La propiedad SharingMode especifica si la aplicación solicita acceso compartido y de solo lectura a la cámara, lo que permite ver y capturar desde la secuencia de vídeo o el control exclusivo de la cámara, lo que permite cambiar la configuración de la cámara. Varias aplicaciones pueden leer desde una cámara simultáneamente, pero solo una aplicación a la vez puede tener control exclusivo.
- La propiedad StreamingCaptureMode especifica si queremos capturar vídeo, audio o audio y vídeo.
- MediaCaptureMemoryPreference nos permite solicitar específicamente el uso de memoria de CPU para fotogramas de vídeo. El valor Auto permite al sistema usar memoria de GPU si está disponible.
Antes de inicializar el objeto MediaCapture llamamos al método AppCapability.CheckAccess para determinar si el usuario ha denegado el acceso de la aplicación a la cámara en Configuración de Windows.
Nota:
Windows permite a los usuarios conceder o denegar el acceso a la cámara del dispositivo en Configuración de Windows, en Privacidad y seguridad -> Cámara. Al inicializar el dispositivo de captura, las aplicaciones deben comprobar si tienen acceso a la cámara y controlar el caso en el que el usuario deniega el acceso. Para obtener más información, consulte Controlar la configuración de privacidad de la cámara de Windows.
La llamada a InitializeAsync se realiza desde dentro de un bloque try para que podamos recuperar si se produce un error en la inicialización. Las aplicaciones deben controlar correctamente el error de inicialización. En este ejemplo sencillo, solo mostraremos un mensaje de error en caso de error.
private async void bStartMediaCapture_Click(object sender, RoutedEventArgs e)
{
if (m_mediaCapture != null)
{
tbStatus.Text = "MediaCapture already initialized.";
return;
}
// Supported in Windows Build 18362 and later
if(AppCapability.Create("Webcam").CheckAccess() != AppCapabilityAccessStatus.Allowed)
{
tbStatus.Text = "Camera access denied. Launching settings.";
bool result = await Windows.System.Launcher.LaunchUriAsync(new Uri("ms-settings:privacy-webcam"));
if (AppCapability.Create("Webcam").CheckAccess() != AppCapabilityAccessStatus.Allowed)
{
tbStatus.Text = "Camera access denied in privacy settings.";
return;
}
}
try
{
m_mediaCapture = new MediaCapture();
var mediaCaptureInitializationSettings = new MediaCaptureInitializationSettings()
{
VideoDeviceId = m_deviceList[cbDeviceList.SelectedIndex].Id,
SharingMode = MediaCaptureSharingMode.ExclusiveControl,
StreamingCaptureMode = StreamingCaptureMode.Video,
MemoryPreference = MediaCaptureMemoryPreference.Auto
};
await m_mediaCapture.InitializeAsync(mediaCaptureInitializationSettings);
tbStatus.Text = "MediaCapture initialized successfully.";
bStartPreview.IsEnabled = true;
}
catch (Exception ex)
{
tbStatus.Text = "Initialize media capture failed: " + ex.Message;
}
}
Inicialización de la vista previa de la cámara
Cuando el usuario hace clic en el botón iniciar vista previa, intentaremos crear un objeto MediaFrameSource para una secuencia de vídeo desde el dispositivo de cámara con el que se inicializó el objeto MediaCapture . Los orígenes de fotogramas disponibles se exponen mediante la propiedad MediaCapture.FrameSources .
Para buscar un origen de fotogramas que sea datos de vídeo de color, en lugar de una cámara de profundidad por ejemplo, buscamos un origen de fotogramas que tenga SourceKind de Color. Algunos controladores de cámara proporcionan una secuencia de vista previa dedicada que es independiente de la secuencia de registros. Para obtener la secuencia de vídeo en versión preliminar, intentamos seleccionar un origen de fotogramas que tenga MediaStreamType de VideoPreview. Si no se encuentra ninguna secuencia de vista previa, podemos obtener la secuencia de vídeo de grabación seleccionando mediaStreamType de VideoRecord. Si ninguno de estos orígenes de fotogramas está disponible, este dispositivo de captura no se puede usar para la vista previa de vídeo.
Una vez que hayamos seleccionado un origen de fotogramas, creamos un nuevo objeto MediaPlayer que será representado por MediaPlayerElement en nuestra interfaz de usuario. Establecemos la propiedad Source del objeto MediaPlayer en un nuevo objeto MediaSource que creamos a partir de nuestro objeto MediaFrameSource seleccionado.
Llame a Play en el objeto MediaPlayer para empezar a representar la secuencia de vídeo.
private void bStartPreview_Click(object sender, RoutedEventArgs e)
{
m_frameSource = null;
// Find preview source.
// The preferred preview stream from a camera is defined by MediaStreamType.VideoPreview on the RGB camera (SourceKind == color).
var previewSource = m_mediaCapture.FrameSources.FirstOrDefault(source => source.Value.Info.MediaStreamType == MediaStreamType.VideoPreview
&& source.Value.Info.SourceKind == MediaFrameSourceKind.Color).Value;
if (previewSource != null)
{
m_frameSource = previewSource;
}
else
{
var recordSource = m_mediaCapture.FrameSources.FirstOrDefault(source => source.Value.Info.MediaStreamType == MediaStreamType.VideoRecord
&& source.Value.Info.SourceKind == MediaFrameSourceKind.Color).Value;
if (recordSource != null)
{
m_frameSource = recordSource;
}
}
if (m_frameSource == null)
{
tbStatus.Text = "No video preview or record stream found.";
return;
}
// Create MediaPlayer with the preview source
m_mediaPlayer = new MediaPlayer();
m_mediaPlayer.RealTimePlayback = true;
m_mediaPlayer.AutoPlay = false;
m_mediaPlayer.Source = MediaSource.CreateFromMediaFrameSource(m_frameSource);
m_mediaPlayer.MediaFailed += MediaPlayer_MediaFailed; ;
// Set the mediaPlayer on the MediaPlayerElement
mpePreview.SetMediaPlayer(m_mediaPlayer);
// Start preview
m_mediaPlayer.Play();
tbStatus.Text = "Start preview succeeded!";
m_isPreviewing = true;
bStartPreview.IsEnabled = false;
bStopPreview.IsEnabled = true;
}
Implemente un controlador para el evento MediaFailed para que pueda gestionar los errores al renderizar la vista previa.
private void MediaPlayer_MediaFailed(MediaPlayer sender, MediaPlayerFailedEventArgs args)
{
tbStatus.Text = "MediaPlayer error: " + args.ErrorMessage;
}
Detener la vista previa de la cámara
Para detener la vista previa de la cámara, llame a Pause en el objeto MediaPlayer .
private void bStopPreview_Click(object sender, RoutedEventArgs e)
{
// Stop preview
m_mediaPlayer.Pause();
m_isPreviewing = false;
bStartPreview.IsEnabled = true;
bStopPreview.IsEnabled = false;
}
Restablecer la aplicación
Para facilitar la prueba de la aplicación de ejemplo, agregue un método para restablecer el estado de la aplicación. Las aplicaciones de cámara siempre deben desechar la cámara y los recursos asociados cuando la cámara ya no sea necesaria.
private void bReset_Click(object sender, RoutedEventArgs e)
{
if (m_mediaCapture != null)
{
m_mediaCapture.Dispose();
m_mediaCapture = null;
}
if(m_mediaPlayer != null)
{
m_mediaPlayer.Dispose();
m_mediaPlayer = null;
}
m_frameSource = null;
bStartMediaCapture.IsEnabled = false;
bStartPreview.IsEnabled = false;
bStopPreview.IsEnabled = false;
PopulateCameraList();
}