ビデオ キャプチャの効果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 オブジェクトを初期化した後、プレビュー ストリームやキャプチャ ストリームに 1 つまたは複数のビデオ効果を追加できます。そのためには、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.

注意

一部のデバイスでは、プレビュー ストリームとキャプチャ ストリームが同じである場合があります。これは、AddVideoEffectAsync を呼び出すときに MediaStreamType.VideoPreview または MediaStreamType.VideoRecord を指定すると、プレビュー ストリームとレコード ストリームの両方に効果が適用されることを意味します。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. 現在のデバイスでプレビュー ストリームとレコード ストリームが同じであるかどうかを確認するには、MediaCapture オブジェクトの MediaCaptureSettingsVideoDeviceCharacteristic プロパティを調べます。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. 一部の効果では、PropertySetSetProperties メソッドに渡すことによって、効果の設定を変更できます。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.

デバイス側でサポートされていれば、Optical Image Stabilization (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. 後で効果が無効にされたときに入出力のエンコード プロパティを復元できるよう、初期状態のバックアップ コピーを格納するための 2 つの変数を宣言します。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. 効果をビデオ パイプラインに追加し、VideoStabilizationEffect クラスのインスタンスを取得するには、MediaCapture.AddVideoEffectAsync を呼び出します。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.

VideoStabilizationEffect のインスタンスの 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.

MediaEncodingProfile オブジェクトの Video プロパティを設定します。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. 最新の効果の状態 (有効または無効) は、sender パラメーターに格納された VideoStabilizationEffect のインスタンスによって知ることができます。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.

通常、このイベントを使ってアプリの UI を調整し、ビデオ手ブレ補正の現在の状態を示します。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;