Efeitos para captura de vídeo
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.
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. 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. O código neste artigo presume que seu aplicativo já tenha uma instância de MediaCapture inicializada corretamente.
Adicionando e removendo efeitos do fluxo de vídeo da câmera
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. 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.
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. 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. 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.
O exemplo a seguir adiciona um efeito aos fluxos de visualização e gravação da câmera. Esse exemplo ilustra a verificação de se os fluxos de visualização e gravação são os mesmos.
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. Alguns efeitos permitem que você altere as configurações de efeito transmitindo um PropertySet para o método SetProperties.
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. 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.
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.
await mediaCapture.ClearEffectsAsync(MediaStreamType.VideoPreview);
await mediaCapture.ClearEffectsAsync(MediaStreamType.VideoRecord);
Efeito de estabilização de vídeo
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. 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. 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.
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. Para obter mais informações, consulte Controles de captura do dispositivo para a captura de vídeo.
Configurar seu aplicativo para usar estabilização de vídeo
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.
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. Como parte da implementação do efeito, você modificará as propriedades de codificação que usa para codificar o vídeo capturado. 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. Por fim, declare uma variável membro do tipo MediaEncodingProfile, pois esse objeto será acessado em vários locais dentro do seu código.
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.
_encodingProfile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Auto);
Inicializar o efeito de estabilização de vídeo
Após a inicialização do seu objeto MediaCapture, crie uma nova instância do objeto VideoStabilizationEffectDefinition. Chame MediaCapture.AddVideoEffectAsync para adicionar o efeito ao pipeline de vídeo e recuperar uma instância da classe VideoStabilizationEffect. Especifique MediaStreamType.VideoRecord para indicar que o efeito deve ser aplicado ao fluxo de gravação de vídeo.
Registre um manipulador de eventos para o evento EnabledChanged e chame o método auxiliar SetUpVideoStabilizationRecommendationAsync, ambos discutidos mais adiante neste artigo. Por fim, defina a propriedade Enabled do efeito como "true" para habilitá-lo.
// 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;
Usar as propriedades de codificação recomendadas
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. 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. 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.
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. Esse método retorna um objeto VideoStreamConfiguration contendo novas propriedades de codificação de fluxo de entrada e saída recomendadas.
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.
Chame VideoDeviceController.SetMediaStreamPropertiesAsync para definir as novas propriedades de codificação. 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.
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. Isso significa que a resolução de saída corresponderá ao tamanho do vídeo cortado. 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.
Defina a propriedade Video do objeto MediaEncodingProfile. 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.
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 desabilitado
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. Se isso ocorrer, o evento EnabledChanged será gerado. A instância VideoStabilizationEffect no parâmetro sender indica o novo estado do efeito, habilitado ou desabilitado. O VideoStabilizationEffectEnabledChangedEventArgs tem um valor VideoStabilizationEffectEnabledChangedReason que indica por que o efeito foi habilitado ou desabilitado. Observe que esse evento também será gerado se você habilitá-lo ou desabilitá-lo o efeito programaticamente, nesse caso, o motivo será 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.
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ídeo
Para limpar o efeito de estabilização de vídeo, chame RemoveEffectAsync para remover o efeito do pipeline do vídeo. 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. Por fim, remova o manipulador de eventos EnabledChanged e defina o efeito 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;
Tópicos relacionados