Эффекты для видеозахватаEffects for video capture

В этом разделе показано, как применять эффекты к предварительному просмотру камеры и потокам видеозаписи, а также как использовать эффект стабилизации видео.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.

Примечание

В этой статье используются понятия и код из статьи Основные принципы фото-, аудио- и видеозахвата с помощью MediaCapture, в которой описаны этапы реализации основных принципов фото- и видеозахвата.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. Мы рекомендуем ознакомиться с базовым шаблоном захвата мультимедиа в этой статье, прежде чем перейти к более сложным сценариям захвата.We recommend that you familiarize yourself with the basic media capture pattern in that article before moving on to more advanced capture scenarios. Код в этой статье подразумевает, что ваше приложение уже содержит экземпляр MediaCapture, инициализированный надлежащим образом.The code in this article assumes that your app already has an instance of MediaCapture that has been properly initialized.

Добавление и удаление эффектов из видеопотока камерыAdding and removing effects from the camera video stream

Для записи или предварительно просмотра видео с камеры устройства используйте объект MediaCapture, как описано в статье Основные принципы фото-, аудио- и видеозахвата с помощью 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. После инициализации объекта MediaCapture можно добавить один или несколько видеоэффектов в поток предварительного просмотра или захвата, вызвав метод AddVideoEffectAsync и передав объект IVideoEffectDefinition, представляющий нужный эффект, и член перечисления MediaStreamType, указывающий, следует ли добавить эффект в потока предварительного просмотра или записи камеры.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.

Примечание

На некоторых устройствах поток предварительного просмотра и поток захвата совпадают, т. е. если указать MediaStreamType.VideoPreview или MediaStreamType.VideoRecord при вызове AddVideoEffectAsync, эффект будет применен к обоим потокам.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. Вы можете определить, совпадают ли потоки предварительного просмотра и записи на текущем устройстве, проверив свойство VideoDeviceCharacteristic в MediaCaptureSettings для объекта 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. Если значение этого свойства равно VideoDeviceCharacteristic.AllStreamsIdentical или VideoDeviceCharacteristic.PreviewRecordStreamsIdentical, то потоки одинаковые, и все эффекты будут применяться к обоим потокам.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.

В следующем примере эффект добавляется в потоки предварительного просмотра и записи камеры.The following example adds an effect to both the camera preview and record streams. В примере показано, как проверить, совпадают ли потоки предварительного просмотра и записи.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);
}

Обратите внимание, что AddVideoEffectAsync возвращает объект, реализующий расширение IMediaExtension, которое представляет добавленный видеоэффект.Note that AddVideoEffectAsync returns an object that implements IMediaExtension that represents the added video effect. Некоторые эффекты позволяют изменить свои параметры, передав PropertySet методу SetProperties.Some effects allow you to change the effect settings by passing a PropertySet into the SetProperties method.

Начиная с Windows 10 версии 1607 можно также использовать объект, возвращенный AddVideoEffectAsync, чтобы удалить эффект из видеоконвейера, передав его в 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 автоматически определяет, был ли параметр объекта эффекта добавлен в поток предварительного просмотра или записи, чтобы вам не нужно было указывать тип потока при вызове.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);
}

Вы также можете удалить все эффекты из потока предварительного просмотра или записи, вызвав метод ClearEffectsAsync и указав поток, из которого необходимо удалить все эффекты.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);

Эффект стабилизации видеоVideo stabilization effect

Эффект стабилизации видео управляет кадрами видеопотока, чтобы минимизировать подергивание, когда вы держите снимающее устройство в руке.The video stabilization effect manipulates the frames of a video stream to minimize shaking caused by holding the capture device in your hand. Поскольку этот метод перемещает пиксели вправо, влево, вверх и вниз и эффект не учитывает содержимое за пределами видеокадра, стабилизированное видео получается несколько обрезанным по сравнению с исходным.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. Имеется служебная функция, которая позволяет настраивать параметры кодирования видео для оптимального управления обрезкой, выполняемой эффектом.A utility function is provided to allow you to adjust your video encoding settings to optimally manage the cropping performed by the effect.

На устройствах с поддержкой функции оптической стабилизации изображений (OIS) видео стабилизируется посредством механического управления записывающим устройством, поэтому нет необходимости обрезать края видеокадров.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. Дополнительные сведения см. в статье Доступ к элементам управления видеозахватом на устройстве.For more information, see Capture device controls for video capture.

Настройка приложения для использования стабилизации видеоSet up your app to use video stabilization

Помимо пространства имен, необходимого для основного захвата мультимедиа, для использования эффекта стабилизации видео нужно следующее пространство имен.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;

Объявите переменную-член для хранения объекта VideoStabilizationEffect.Declare a member variable to store the VideoStabilizationEffect object. В рамках реализации эффекта измените свойства кодирования, применяемые для кодирования захваченного видео.As part of the effect implementation, you will modify the encoding properties that you use to encode the captured video. Объявите две переменные для хранения резервной копии исходных свойств кодирования входного и выходного потока, чтобы их можно было восстановить после отключения эффекта.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. Наконец объявите переменную-член типа MediaEncodingProfile, поскольку этот объект будет доступен из разных мест кода.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;

Для этого сценария следует назначать объект профиля кодирования мультимедиа переменной-члену, чтобы можно было получить к нему доступ позже.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);

Инициализация эффекта стабилизации видеоInitialize the video stabilization effect

После инициализации объекта MediaCapture создайте новый экземпляр объекта VideoStabilizationEffectDefinition.After your MediaCapture object has been initialized, create a new instance of the VideoStabilizationEffectDefinition object. Вызовите MediaCapture.AddVideoEffectAsync для добавления эффекта к видеоконвейеру и получения экземпляра класса VideoStabilizationEffect.Call MediaCapture.AddVideoEffectAsync to add the effect to the video pipeline and retrieve an instance of the VideoStabilizationEffect class. Определите MediaStreamType.VideoRecord, чтобы указать, что эффект должен применяться к потоку видеозаписи.Specify MediaStreamType.VideoRecord to indicate that the effect should be applied to the video record stream.

Зарегистрируйте обработчик для события EnabledChanged и вызовите вспомогательный метод SetUpVideoStabilizationRecommendationAsync, которые рассматриваются ниже в этой статье.Register an event handler for the EnabledChanged event and call the helper method SetUpVideoStabilizationRecommendationAsync, both of which are discussed later in this article. В заключение установите для свойства Enabled значение true, чтобы включить эффект.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;

Как было сказано выше в этой статье, метод, используемый для эффекта стабилизации видео, неизбежно приводит к небольшой обрезке исходного видео.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. Определите следующую вспомогательную функцию в коде, чтобы настроить свойства кодирования видео и перекрыть это ограничение эффекта наилучшим образом.Define the following helper function in your code in order to adjust the video encoding properties to optimally handle this limitation of the effect. Эффект стабилизации видео можно использовать и без этого этапа, но если вы его пропустите, полученное видео будет слегка растянутым, то есть его визуальное качество будет несколько ниже.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.

Вызовите GetRecommendedStreamConfiguration для экземпляра эффекта стабилизации видео, передавая объект VideoDeviceController, который сообщает эффекту информацию о текущих свойствах кодирования входного потока и вашем профиле MediaEncodingProfile, благодаря чему эффект получает информацию о текущих свойствах кодирования на выходе.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. Этот метод возвращает объект VideoStreamConfiguration, содержащий новые рекомендуемые свойства кодирования входящего и выходящего потоков.This method returns a VideoStreamConfiguration object containing new recommended input and output stream encoding properties.

Рекомендуемые свойства кодирования входящего потока обеспечивают более высокое разрешение (если такая возможность поддерживается устройством) по сравнению с заданными исходными параметрами, чтобы минимизировать потери разрешения из-за обрезки в результате применения эффекта.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.

Вызовите VideoDeviceController.SetMediaStreamPropertiesAsync для установки новых свойств кодирования.Call VideoDeviceController.SetMediaStreamPropertiesAsync to set the new encoding properties. Перед установкой новых свойств используйте переменную-член для хранения исходных свойств кодирования, чтобы иметь возможность вернуть настройки при отключении эффекта.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.

Если эффект стабилизации должен обрезать выходящее видео, то рекомендуемые свойства кодирования выходящего потока будут обеспечивать размер обрезанного видео.If the video stabilization effect must crop the output video, the recommended output encoding properties will be the size of the cropped video. Это означает, что выходящее разрешение будет соответствовать размеру обрезанного видео.This means that the output resolution will match the cropped video size. Если не использовать рекомендованные свойства выходного потока, видео будет растянуто для соответствия исходному размеру выходного потока, что приведет к потере визуального качества.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.

Задайте свойство Video объекта MediaEncodingProfile.Set the Video property of the MediaEncodingProfile object. Перед установкой новых свойств используйте переменную-член для хранения исходных свойств кодирования, чтобы иметь возможность вернуть настройки при отключении эффекта.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;
    }
}

Обработка отключения эффекта стабилизации видеоHandle the video stabilization effect being disabled

Система может автоматически отключать эффект стабилизации видео, если поток пикселей слишком высок и эффект не может с ним справиться либо работает медленно.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. В этом случае вызывается событие EnabledChanged.If this occurs, the EnabledChanged event is raised. Экземпляр VideoStabilizationEffect в параметре sender показывает новое состояние эффекта: включен или выключен.The VideoStabilizationEffect instance in the sender parameter indicates the new state of the effect, enabled or disabled. VideoStabilizationEffectEnabledChangedEventArgs имеет значение VideoStabilizationEffectEnabledChangedReason, показывающее, по какой причине включен или выключен эффект.The VideoStabilizationEffectEnabledChangedEventArgs has a VideoStabilizationEffectEnabledChangedReason value indicating why the effect was enabled or disabled. Обратите внимание, что это событие также вызывается при включении или выключении эффекта программным способом. В этом случае причина будет указана как Programmatic.Note that this event is also raised if you programmatically enable or disable the effect, in which case the reason will be Programmatic.

Как правило, это событие используется для того, чтобы настроить в пользовательском интерфейсе приложения отображение текущего состояния стабилизации видео.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);
    });
}

Удаление эффекта стабилизации видеоClean up the video stabilization effect

Для удаления эффекта стабилизации видео вызовите RemoveEffectAsync, чтобы удалить эффект из видеоконвейера.To clean up the video stabilization effect, call RemoveEffectAsync to remove the effect from the video pipeline. Если значения переменных-членов, содержащих начальные свойства кодирования, не равны null, используйте их для восстановления свойств кодирования.If the member variables containing the initial encoding properties are not null, use them to restore the encoding properties. Наконец удалите обработчик событий EnabledChanged и установите для эффекта значение 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;