Efeitos para captura de vídeoEffects for video capture

Este tópico mostra como aplicar efeitos à visualização de câmera e fluxos de gravação de vídeo e mostra como usar o efeito de estabilização de vídeo.This topic shows you how to apply effects to the camera preview and recording video streams and shows you how to use the video stabilization effect.

Observação

Este artigo se baseia em conceitos e códigos discutidos em Captura básica de fotos, áudio e vídeo com o MediaCapture, que descreve as etapas para implementar uma captura básica de fotos e vídeos.This article builds on concepts and code discussed in Basic photo, video, and audio capture with MediaCapture, which describes the steps for implementing basic photo and video capture. Recomendamos que você se familiarize com o padrão de captura de mídia básica neste artigo antes de passar para cenários de captura mais avançados.We recommend that you familiarize yourself with the basic media capture pattern in that article before moving on to more advanced capture scenarios. O código neste artigo presume que seu aplicativo já tenha uma instância de MediaCapture inicializada corretamente.The code in this article assumes that your app already has an instance of MediaCapture that has been properly initialized.

Adicionando e removendo efeitos do fluxo de vídeo da câmeraAdding and removing effects from the camera video stream

Para capturar ou visualizar vídeos da câmera do dispositivo, use o objeto MediaCapture conforme descrito em Captura básica de fotos, áudio e vídeo com MediaCapture.To capture or preview video from the device's camera, you use the MediaCapture object as described in Basic photo, video, and audio capture with MediaCapture. Após ter inicializado o objeto MediaCapture, você pode adicionar um ou mais efeitos de vídeo ao fluxo de visualização ou captura chamando AddVideoEffectAsync, transmitindo um objeto IVideoEffectDefinition que representa o efeito a ser adicionado e um membro da enumeração MediaStreamType que indica se o efeito deve ser adicionado ao fluxo de visualização da câmera ou ao fluxo de registro.After you have initialized the MediaCapture object, you can add one or more video effects to the preview or capture stream by calling AddVideoEffectAsync, passing in an IVideoEffectDefinition object representing the effect to be added, and a member of the MediaStreamType enumeration indicating whether the effect should be added to the camera's preview stream or the record stream.

Observação

Em alguns dispositivos, o fluxo de visualização e o fluxo de captura são os mesmos, o que significa que, se você especificar MediaStreamType.VideoPreview ou MediaStreamType.VideoRecord ao chamar AddVideoEffectAsync, o efeito será aplicado aos fluxos de visualização e gravação.On some devices, the preview stream and the capture stream are the same, which means that if you specify MediaStreamType.VideoPreview or MediaStreamType.VideoRecord when you call AddVideoEffectAsync, the effect will be applied to both preview and record streams. Você pode determinar se os fluxos de visualização e gravação são os mesmos no dispositivo atual verificando a propriedade VideoDeviceCharacteristic do objeto MediaCaptureSettings para o MediaCapture.You can determine whether the preview and record streams are the same on the current device by checking the VideoDeviceCharacteristic property of the MediaCaptureSettings for the MediaCapture object. Se o valor dessa propriedade for VideoDeviceCharacteristic.AllStreamsIdentical ou VideoDeviceCharacteristic.PreviewRecordStreamsIdentical, os fluxos são os mesmos e qualquer efeito que se aplica a um afeta o outro.If the value of this property is VideoDeviceCharacteristic.AllStreamsIdentical or VideoDeviceCharacteristic.PreviewRecordStreamsIdentical, then the streams are the same and any effect you apply to one will affect the other.

O exemplo a seguir adiciona um efeito aos fluxos de visualização e gravação da câmera.The following example adds an effect to both the camera preview and record streams. Esse exemplo ilustra a verificação de se os fluxos de visualização e gravação são os mesmos.This example illustrates checking to see if the record and preview streams are the same.

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);
}

Observe que AddVideoEffectAsync retorna um objeto que implementa IMediaExtension que representa o efeito de vídeo adicionado.Note that AddVideoEffectAsync returns an object that implements IMediaExtension that represents the added video effect. Alguns efeitos permitem que você altere as configurações de efeito transmitindo um PropertySet para o método SetProperties.Some effects allow you to change the effect settings by passing a PropertySet into the SetProperties method.

A partir do Windows 10, versão 1607, você também pode usar o objeto retornado por AddVideoEffectAsync para remover o efeito do pipeline do vídeo transmitindo-o para RemoveEffectAsync.Starting with Windows 10, version 1607, you can also use the object returned by AddVideoEffectAsync to remove the effect from the video pipeline by passing it into RemoveEffectAsync. RemoveEffectAsync determina automaticamente se o parâmetro de objeto de efeito foi adicionado ao fluxo de visualização ou gravação. Portanto, você não precisa especificar o tipo de fluxo ao fazer a chamada.RemoveEffectAsync automatically determines whether the effect object parameter was added to the preview or record stream, so you don't need to specify the stream type when making the call.

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

Você também pode remover todos os efeitos do fluxo de visualização ou captura chamando ClearEffectsAsync e especificando o fluxo para o qual todos os efeitos devem ser removidos.You can also remove all effects from the preview or capture stream by calling ClearEffectsAsync and specifying the stream for which all effects should be removed.

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

Efeito de estabilização de vídeoVideo stabilization effect

O efeito de estabilização de vídeo manipula os quadros de um fluxo de vídeo para minimizar a vibração causada por segurar o dispositivo de captura em sua mão.The video stabilization effect manipulates the frames of a video stream to minimize shaking caused by holding the capture device in your hand. Como essa técnica faz com que os pixels sejam deslocados para a direita, para a esquerda, para cima e para baixo, e como o efeito identifica o conteúdo fora do quadro de vídeo, o vídeo estabilizado é cortado ligeiramente do vídeo original.Because this technique causes the pixels to be shifted right, left, up, and down, and because the effect can't know what the content just outside the video frame is, the stabilized video is cropped slightly from the original video. Uma função utilitária é fornecida para permitir que você ajuste suas configurações de codificação para gerenciar de forma ideal o corte realizado pelo efeito.A utility function is provided to allow you to adjust your video encoding settings to optimally manage the cropping performed by the effect.

Nos dispositivos com suporte para isso, a OIS (estabilização de imagem ótica) estabiliza o vídeo manipulando mecanicamente o dispositivo de captura e, portanto, não precisa cortar as bordas dos quadros do vídeo.On devices that support it, Optical Image Stabilization (OIS) stabilizes video by mechanically manipulating the capture device and, therefore, does not need to crop the edges of the video frames. Para obter mais informações, consulte Controles de captura do dispositivo para a captura de vídeo.For more information, see Capture device controls for video capture.

Configurar seu aplicativo para usar estabilização de vídeoSet up your app to use video stabilization

Além dos namespaces necessários para captura de mídia básica, o uso do efeito de estabilização de vídeo exige o namespace a seguir.In addition to the namespaces required for basic media capture, using the video stabilization effect requires the following namespace.

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

Declare uma variável membro para armazenar o objeto VideoStabilizationEffect.Declare a member variable to store the VideoStabilizationEffect object. Como parte da implementação do efeito, você modificará as propriedades de codificação que usa para codificar o vídeo capturado.As part of the effect implementation, you will modify the encoding properties that you use to encode the captured video. Declare duas variáveis para armazenar uma cópia de backup das propriedades de codificação de entrada e saída para poder restaurá-las mais tarde, quando o efeito estiver desabilitado.Declare two variables to store a backup copy of the initial input and output encoding properties so that you can restore them later when the effect is disabled. Por fim, declare uma variável membro do tipo MediaEncodingProfile, pois esse objeto será acessado em vários locais dentro do seu código.Finally, declare a member variable of type MediaEncodingProfile because this object will be accessed from multiple locations within your code.

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

Para esse cenário, você deve atribuir o objeto de perfil de codificação de mídia a uma variável membro para poder acessá-lo posteriormente.For this scenario, you should assign the media encoding profile object to a member variable so that you can access it later.

_encodingProfile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Auto);

Inicializar o efeito de estabilização de vídeoInitialize the video stabilization effect

Após a inicialização do seu objeto MediaCapture, crie uma nova instância do objeto VideoStabilizationEffectDefinition.After your MediaCapture object has been initialized, create a new instance of the VideoStabilizationEffectDefinition object. Chame MediaCapture.AddVideoEffectAsync para adicionar o efeito ao pipeline de vídeo e recuperar uma instância da classe VideoStabilizationEffect.Call MediaCapture.AddVideoEffectAsync to add the effect to the video pipeline and retrieve an instance of the VideoStabilizationEffect class. Especifique MediaStreamType.VideoRecord para indicar que o efeito deve ser aplicado ao fluxo de gravação de vídeo.Specify MediaStreamType.VideoRecord to indicate that the effect should be applied to the video record stream.

Registre um manipulador de eventos para o evento EnabledChanged e chame o método auxiliar SetUpVideoStabilizationRecommendationAsync, ambos discutidos mais adiante neste artigo.Register an event handler for the EnabledChanged event and call the helper method SetUpVideoStabilizationRecommendationAsync, both of which are discussed later in this article. Por fim, defina a propriedade Enabled do efeito como "true" para habilitá-lo.Finally, set the Enabled property of the effect to true to enable the effect.

// 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;

Conforme discutido anteriormente neste artigo, a técnica usada pelo efeito de estabilização de vídeo faz inevitavelmente com que o vídeo estabilizado seja cortado em uma certa medida da fonte de vídeo.As discussed earlier in this article, the technique that the video stabilization effect uses necessarily causes the stabilized video to be cropped slightly from the source video. Defina a função de auxiliar a seguir em seu código para ajustar as propriedades de codificação de vídeo para lidar do modo ideal com essa limitação do efeito.Define the following helper function in your code in order to adjust the video encoding properties to optimally handle this limitation of the effect. Esta etapa não é necessária para usar o efeito de estabilização de vídeo, mas, se você não executá-la, o vídeo resultante será ampliado um pouco e, portanto, terá uma fidelidade visual um pouco menor.This step is not required in order to use the video stabilization effect, but if you don't perform this step, the resulting video will be upscaled slightly and therefore have slightly lower visual fidelity.

Chame GetRecommendedStreamConfiguration na sua instância de efeito de estabilização de vídeo, transmitindo o objeto VideoDeviceController, que informa o efeito sobre as suas propriedades de codificação de fluxo de entrada atuais, e seu MediaEncodingProfile, que faz com que o evento conheça as suas propriedades de codificação de saída atuais.Call GetRecommendedStreamConfiguration on your video stabilization effect instance, passing in the VideoDeviceController object, which informs the effect about your current input stream encoding properties, and your MediaEncodingProfile which lets the effect know your current output encoding properties. Esse método retorna um objeto VideoStreamConfiguration contendo novas propriedades de codificação de fluxo de entrada e saída recomendadas.This method returns a VideoStreamConfiguration object containing new recommended input and output stream encoding properties.

As propriedades recomendadas de codificação de entrada apresentam, caso o dispositivo ofereça suporte, uma resolução mais alta do que as configurações iniciais que você forneceu, para que haja o mínimo de perda na resolução após a aplicação do efeito de corte.The recommended input encoding properties are, if it is supported by the device, a higher resolution that the initial settings you provided so that there is minimal loss in resolution after the effect's cropping is applied.

Chame VideoDeviceController.SetMediaStreamPropertiesAsync para definir as novas propriedades de codificação.Call VideoDeviceController.SetMediaStreamPropertiesAsync to set the new encoding properties. Antes de definir as novas propriedades, use a variável membro para armazenar as propriedades de codificação iniciais para que você possa modificar as configurações de novo quando desabilitar o efeito.Before setting the new properties, use the member variable to store the initial encoding properties so that you can change the settings back when you disable the effect.

Se o efeito de estabilização de vídeo precisar cortar o vídeo de saída, as propriedades de codificação de saída recomendadas serão do tamanho do vídeo cortado.If the video stabilization effect must crop the output video, the recommended output encoding properties will be the size of the cropped video. Isso significa que a resolução de saída corresponderá ao tamanho do vídeo cortado.This means that the output resolution will match the cropped video size. Se você não usar as propriedades de saída recomendadas, o vídeo será dimensionado para corresponder ao tamanho de saída inicial, o que resultará em uma perda de fidelidade visual.If you do not use the recommended output properties, the video will be scaled up to match the initial output size, which will result in a loss of visual fidelity.

Defina a propriedade Video do objeto MediaEncodingProfile.Set the Video property of the MediaEncodingProfile object. Antes de definir as novas propriedades, use a variável membro para armazenar as propriedades de codificação iniciais para que você possa modificar as configurações de novo quando desabilitar o efeito.Before setting the new properties, use the member variable to store the initial encoding properties so that you can change the settings back when you disable the effect.

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;
    }
}

Manipular o efeito de estabilização de vídeo sendo desabilitadoHandle the video stabilization effect being disabled

O sistema poderá desabilitar automaticamente o efeito de estabilização de vídeo se a taxa de transferência de pixel for muito alta para o efeito ou se detectar que o efeito está sendo executado lentamente.The system may automatically disable the video stabilization effect if the pixel throughput is too high for the effect to handle or if it detects that the effect is running slowly. Se isso ocorrer, o evento EnabledChanged será gerado.If this occurs, the EnabledChanged event is raised. A instância VideoStabilizationEffect no parâmetro sender indica o novo estado do efeito, habilitado ou desabilitado.The VideoStabilizationEffect instance in the sender parameter indicates the new state of the effect, enabled or disabled. O VideoStabilizationEffectEnabledChangedEventArgs tem um valor VideoStabilizationEffectEnabledChangedReason que indica por que o efeito foi habilitado ou desabilitado.The VideoStabilizationEffectEnabledChangedEventArgs has a VideoStabilizationEffectEnabledChangedReason value indicating why the effect was enabled or disabled. Observe que esse evento também será gerado se você habilitá-lo ou desabilitá-lo o efeito programaticamente, nesse caso, o motivo será Programmatic.Note that this event is also raised if you programmatically enable or disable the effect, in which case the reason will be Programmatic.

Normalmente, você usaria esse evento para ajustar a interface do usuário do seu aplicativo para indicar o status atual de estabilização de vídeo.Typically, you would use this event to adjust your app's UI to indicate the current status of video stabilization.

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);
    });
}

Limpar o efeito de estabilização de vídeoClean up the video stabilization effect

Para limpar o efeito de estabilização de vídeo, chame RemoveEffectAsync para remover o efeito do pipeline do vídeo.To clean up the video stabilization effect, call RemoveEffectAsync to remove the effect from the video pipeline. Se as variáveis membro que contêm as propriedades de codificação iniciais não forem nulas, use-as para restaurar as propriedades de codificação.If the member variables containing the initial encoding properties are not null, use them to restore the encoding properties. Por fim, remova o manipulador de eventos EnabledChanged e defina o efeito como "null".Finally, remove the EnabledChanged event handler and set the effect to 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;