Compartir a través de


Efectos para captura de vídeos

Este tema muestra cómo aplicar efectos a la vista previa de la cámara y a las secuencias de grabación de vídeo, y muestra cómo usar el efecto de estabilización de vídeo.

Nota:

Este artículo se basa en los conceptos y el código analizados en Captura básica de fotos, audio y vídeo con MediaCapture, donde se describen los pasos para implementar la captura básica de fotos y vídeo. Se recomienda que te familiarices con el patrón de captura de multimedia básico de ese artículo antes de pasar a escenarios de captura más avanzados. El código que encontrarás en este artículo se ha agregado suponiendo que la aplicación ya tiene una instancia de MediaCapture inicializada correctamente.

Agregar y quitar efectos de la secuencia de vídeo de la cámara

Para capturar u obtener una vista previa de vídeo desde la cámara del dispositivo, usa el objeto MediaCapture como se describe en Captura básica de fotos, audio y vídeo con MediaCapture. Después de inicializar el objeto MediaCapture, puedes agregar uno o más efectos de vídeo a la secuencia de vista previa o de captura mediante llamando a AddVideoEffectAsync, pasando un objeto IVideoEffectDefinition que representa el efecto que se va a agregar y un miembro de la enumeración MediaStreamType que indica si el efecto debe agregarse a la secuencia de vista previa de la cámara o a la secuencia de grabación.

Nota:

En algunos dispositivos, la secuencia de vista previa y la secuencia de captura son la misma, lo que significa que si especificas MediaStreamType.VideoPreview o MediaStreamType.VideoRecord cuando llames a AddVideoEffectAsync, el efecto se aplicará tanto a las secuencias de vista previa como las de grabación. Puedes determinar si las secuencias de vista previa y de grabación son la misma en el dispositivo actual comprobando la propiedad VideoDeviceCharacteristic de MediaCaptureSettings para el objeto MediaCapture. Si el valor de esta propiedad es VideoDeviceCharacteristic.AllStreamsIdentical o VideoDeviceCharacteristic.PreviewRecordStreamsIdentical, entonces las secuencias son la misma y cualquier efecto que apliques a una afectará a la otra.

El siguiente ejemplo agrega un efecto tanto a la secuencia de vista previa de la cámara como a la secuencia de grabación. Este ejemplo muestra la comprobación para ver si las secuencias de vista previa y de grabación son la misma.

if (mediaCapture.MediaCaptureSettings.VideoDeviceCharacteristic == VideoDeviceCharacteristic.AllStreamsIdentical ||
    mediaCapture.MediaCaptureSettings.VideoDeviceCharacteristic == VideoDeviceCharacteristic.PreviewRecordStreamsIdentical)
{
    // This effect will modify both the preview and the record streams, because they are the same stream.
    myRecordEffect = await mediaCapture.AddVideoEffectAsync(myEffectDefinition, MediaStreamType.VideoRecord);
}
else
{
    myRecordEffect = await mediaCapture.AddVideoEffectAsync(myEffectDefinition, MediaStreamType.VideoRecord);
    myPreviewEffect = await mediaCapture.AddVideoEffectAsync(myEffectDefinition, MediaStreamType.VideoPreview);
}

Ten en cuenta que AddVideoEffectAsync devuelve un objeto que implementa IMediaExtension que representa el efecto de vídeo agregado. Algunos efectos te permiten cambiar la configuración del efecto pasando un PropertySet al método SetProperties.

A partir de Windows 10, versión 1607, también puedes usar el objeto devuelto por AddVideoEffectAsync para quitar el efecto de la canalización de vídeo pasándolo a RemoveEffectAsync. RemoveEffectAsync determina automáticamente si el parámetro del objeto de efecto se ha agregado a la secuencia de vista previa o a la de grabación, por lo que no es necesario especificar el tipo de secuencia al realizar la llamada.

if (myRecordEffect != null)
{
    await mediaCapture.RemoveEffectAsync(myRecordEffect);
}
if(myPreviewEffect != null)
{
    await mediaCapture.RemoveEffectAsync(myPreviewEffect);
}

También puedes quitar todos los efectos de la secuencia de vista previa o de captura llamando a ClearEffectsAsync y especificando la secuencia para la que se deben quitar todos los efectos.

await mediaCapture.ClearEffectsAsync(MediaStreamType.VideoPreview);
await mediaCapture.ClearEffectsAsync(MediaStreamType.VideoRecord);

Efecto de estabilización de vídeo

El efecto de estabilización de vídeo manipula los marcos de una secuencia de vídeo para minimizar la sacudida causada por sujetar el dispositivo de captura con la mano. Dado que esta técnica hace que los píxeles de desplazamiento se muevan a derecha, izquierda, arriba o abajo, y como el efecto no puede saber cuál es el contenido que queda justo fuera del marco de vídeo, el vídeo estabilizado se recorta ligeramente en relación al vídeo original. Se proporciona una función de utilidad que te permite ajustar la configuración para administrar de forma óptima el corte realizado por el efecto de codificación de vídeo.

En los dispositivos que lo admiten, la estabilización de imagen óptica (OIS) estabiliza el vídeo manipulando mecánicamente el dispositivo de captura y, por lo tanto, no es necesario recortar los bordes de los fotogramas de vídeos. Para obtener más información, consulta Controles de dispositivo de captura para captura de vídeos.

Configurar tu aplicación para usar la estabilización de vídeo

Además de los espacios de nombres necesarios para la captura básica de elementos multimedia, si usas el efecto de estabilización de vídeo necesitarás el siguiente espacio de nombres.

using Windows.Media.Core;
using Windows.Media.MediaProperties;
using Windows.Media.Effects;
using Windows.Media;

Declara una variable de miembro para almacenar el objeto VideoStabilizationEffect. Como parte de la implementación del efecto, tendrás que modificar las propiedades de codificación que uses para codificar el vídeo capturado. Para ello, declara dos variables para almacenar una copia de seguridad tanto de la entrada inicial como de las propiedades de codificación de salida, para que así puedas restaurarlas más adelante cuando se deshabilite el efecto. Por último, declara una variable de miembro de tipo MediaEncodingProfile, ya que se obtendrá acceso a este objeto desde varias ubicaciones dentro del código.

private VideoStabilizationEffect _videoStabilizationEffect;
private VideoEncodingProperties _inputPropertiesBackup;
private VideoEncodingProperties _outputPropertiesBackup;
private MediaEncodingProfile _encodingProfile;

Para este escenario, debes asignar el objeto de perfil de codificación multimedia a una variable de miembro para poder acceder a él más adelante.

_encodingProfile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Auto);

Inicializar el efecto de estabilización de vídeo

Después de inicializar el objeto MediaCapture, puedes crear una nueva instancia del objeto VideoStabilizationEffectDefinition. Llama a MediaCapture.AddVideoEffectAsync para agregar el efecto a la canalización de vídeo y recuperar una instancia de clase VideoStabilizationEffect. Especifica MediaStreamType.VideoRecord para indicar que el efecto debe aplicarse a la secuencia de grabación del vídeo.

Registra un controlador de eventos para el evento EnabledChanged y llama al método auxiliar SetUpVideoStabilizationRecommendationAsync; describiremos ambos más adelante en este artículo. Por último, establece la propiedad Enabled del efecto en "true" para habilitar el efecto.

// Create the effect definition
VideoStabilizationEffectDefinition stabilizerDefinition = new VideoStabilizationEffectDefinition();

// Add the video stabilization effect to media capture
_videoStabilizationEffect =
    (VideoStabilizationEffect)await mediaCapture.AddVideoEffectAsync(stabilizerDefinition, MediaStreamType.VideoRecord);

_videoStabilizationEffect.EnabledChanged += VideoStabilizationEffect_EnabledChanged;

await SetUpVideoStabilizationRecommendationAsync();

_videoStabilizationEffect.Enabled = true;

Tal como se explicó anteriormente en este artículo, la técnica que el efecto de estabilización del vídeo usa, hace que el vídeo estabilizado se recorte ligeramente en relación al vídeo de origen. Define la siguiente función auxiliar en el código para ajustar las propiedades de codificación de vídeo para controlar esta limitación del efecto de forma óptima. Este paso no es necesario para poder usar el efecto de estabilización de vídeo, pero si lo no realizas, el vídeo resultante se escalará un poco verticalmente y, por lo tanto, la fidelidad visual será un poco más baja.

Llama al método GetRecommendedStreamConfiguration que se encuentra en la instancia del efecto de estabilización de vídeo y pasa el objeto VideoDeviceController (el cual informará al efecto sobre las propiedades de codificación de secuencia) y la clase MediaEncodingProfile (la cual permite al efecto conocer las propiedades de codificación de salida actuales). Este método devuelve un objeto VideoStreamConfiguration que contiene nuevas propiedades recomendadas de codificación de la secuencia de entrada y salida.

Una propiedad de codificación de entrada recomendada es, en caso de ser compatible con el dispositivo, una resolución más alta que la configuración inicial que proporcionaste; gracias a ella, habrá una pérdida mínima en la resolución después de aplicar la opción de recorte del efecto.

Llama a VideoDeviceController.SetMediaStreamPropertiesAsync para establecer las nuevas propiedades de codificación. Antes de establecer las propiedades nuevas, usa la variable de miembro para almacenar las propiedades iniciales de codificación y que así puedas cambiar la configuración cuando se desactive el efecto.

Si el efecto de estabilización de vídeo debe recortar el vídeo de salida, la codificación de propiedades de salida recomendada será del tamaño del vídeo recortado. Esto significa que la resolución de salida coincidirá con el tamaño del vídeo recortado. Si no usas las propiedades de salida recomendadas, el vídeo se escalará verticalmente para que coincida con el tamaño de salida inicial, lo que provocará una pérdida de fidelidad visual.

Establece la propiedad Video del objeto MediaEncodingProfile. Antes de establecer las propiedades nuevas, usa la variable de miembro para almacenar las propiedades iniciales de codificación y que así puedas cambiar la configuración cuando se desactive el efecto.

private async Task SetUpVideoStabilizationRecommendationAsync()
{

    // Get the recommendation from the effect based on our current input and output configuration
    var recommendation = _videoStabilizationEffect.GetRecommendedStreamConfiguration(mediaCapture.VideoDeviceController, _encodingProfile.Video);

    // Handle the recommendation for the input into the effect, which can contain a larger resolution than currently configured, so cropping is minimized
    if (recommendation.InputProperties != null)
    {
        // Back up the current input properties from before VS was activated
        _inputPropertiesBackup = mediaCapture.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.VideoRecord) as VideoEncodingProperties;

        // Set the recommendation from the effect (a resolution higher than the current one to allow for cropping) on the input
        await mediaCapture.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.VideoRecord, recommendation.InputProperties);
        await mediaCapture.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.VideoPreview, recommendation.InputProperties);
    }

    // Handle the recommendations for the output from the effect
    if (recommendation.OutputProperties != null)
    {
        // Back up the current output properties from before VS was activated
        _outputPropertiesBackup = _encodingProfile.Video;

        // Apply the recommended encoding profile for the output
        _encodingProfile.Video = recommendation.OutputProperties;
    }
}

Controlar el efecto de estabilización de vídeo que se va a deshabilitar

El sistema puede deshabilitar automáticamente el efecto de estabilización de vídeo si el rendimiento de píxeles es demasiado alto para que el efecto pueda controlarlo, o si detecta que el efecto se está ejecutando lentamente. Si esto ocurre, se genera el evento EnabledChanged. La instancia VideoStabilizationEffect del parámetro sender indica el nuevo estado del efecto: habilitado o deshabilitado. La clase VideoStabilizationEffectEnabledChangedEventArgs tiene un valor VideoStabilizationEffectEnabledChangedReason que indica por qué se habilitó o deshabilitó el efecto. Ten en cuenta que este evento también se genera, si mediante programación, habilitas o deshabilitas el efecto; en tal caso, el motivo será Programmatic.

Por lo general, deberías usar este evento para ajustar la interfaz de usuario de la aplicación para indicar el estado actual de la estabilización de vídeo.

private async void VideoStabilizationEffect_EnabledChanged(VideoStabilizationEffect sender, VideoStabilizationEffectEnabledChangedEventArgs args)
{
    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
        // Update your UI to reflect the change in status
        ShowMessageToUser("video stabilization status: " + sender.Enabled + ". Reason: " + args.Reason);
    });
}

Limpiar el efecto de estabilización de vídeo

Para limpiar el efecto de estabilización de vídeo, llama al método RemoveEffectAsync para quitar el efecto de la canalización de vídeo. Si las variables de miembro que contienen las propiedades de codificación iniciales no son nulas, úsalas para restaurar las propiedades de codificación. Por último, quita el controlador de eventos EnabledChanged y define el efecto como "null".

// Clear all effects in the pipeline
await mediaCapture.RemoveEffectAsync(_videoStabilizationEffect);

// If backed up settings (stream properties and encoding profile) exist, restore them and clear the backups
if (_inputPropertiesBackup != null)
{
    await mediaCapture.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.VideoRecord, _inputPropertiesBackup);
    _inputPropertiesBackup = null;
}

if (_outputPropertiesBackup != null)
{
    _encodingProfile.Video = _outputPropertiesBackup;
    _outputPropertiesBackup = null;
}

_videoStabilizationEffect.EnabledChanged -= VideoStabilizationEffect_EnabledChanged;

_videoStabilizationEffect = null;