Freigeben über


Effekte für die Videoaufnahme

In diesem Thema erfahren Sie, wie Sie Effekte auf die Kameravorschau und auf Videoaufnahmedatenströme anwenden und wie Sie den Videostabilisierungseffekt verwenden.

Hinweis

Dieser Artikel baut auf Konzepten und Code auf, die unter Allgemeine Foto-, Video- und Audioaufnahme mit „MediaCapture“ erläutert werden. Dort werden die Schritte für die Implementierung einer grundlegenden Foto- und Videoaufnahme beschrieben. Wir empfehlen Ihnen, sich mit dem grundlegenden Medienaufnahmemuster in diesem Artikel vertraut zu machen, bevor Sie sich komplexeren Aufnahmeszenarien zuwenden. Der Code in diesem Artikel setzt voraus, dass Ihre App bereits über eine korrekt initialisierte MediaCapture-Instanz verfügt.

Hinzufügen und Entfernen von Effekten im Kameravideodatenstrom

Um Videos mithilfe der Gerätekamera aufzunehmen oder in der Vorschau anzuzeigen, verwenden Sie das MediaCapture-Objekt, wie unter Allgemeine Foto-, Video- und Audioaufnahme mit „MediaCapture“ beschrieben. Nachdem Sie das MediaCapture-Objekt initialisiert haben, können Sie dem Vorschau- oder Aufnahmedatenstrom einen oder mehrere Videoeffekte hinzufügen, indem Sie AddVideoEffectAsync aufrufen, ein IVideoEffectDefinition-Objekt übergeben, das den hinzuzufügenden Effekt darstellt, und einen Member der MediaStreamType-Enumeration übergeben, der angibt, ob der Effekt dem Vorschaudatenstrom oder Aufnahmedatenstrom der Kamera hinzugefügt werden soll.

Hinweis

Auf einigen Geräten sind der Vorschaudatenstrom und Aufnahmedatenstrom identisch. Wenn Sie MediaStreamType.VideoPreview oder MediaStreamType.VideoRecord angeben und AddVideoEffectAsync aufrufen, wird der Effekt folglich sowohl auf den Vorschaudatenstrom als auch auf den Aufnahmedatenstrom angewendet. Sie können bestimmen, ob der Vorschaudatenstrom und Aufnahmedatenstrom auf dem aktuellen Gerät identisch sind, indem Sie die VideoDeviceCharacteristic-Eigenschaft von MediaCaptureSettings auf das MediaCapture-Objekt überprüfen. Wenn der Wert dieser Eigenschaft VideoDeviceCharacteristic.AllStreamsIdentical oder VideoDeviceCharacteristic.PreviewRecordStreamsIdentical lautet, sind die Datenströme identisch, und alle auf einen Datenstrom angewendeten Effekte wirken sich auch auf den anderen aus.

Im folgenden Beispiel wird sowohl dem Vorschaudatenstrom als auch dem Aufnahmedatenstrom der Kamera ein Effekt hinzugefügt. Dieses Beispiel veranschaulicht, wie Sie überprüfen, ob der Aufnahme- und Vorschaudatenstrom identisch sind.

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

Beachten Sie, dass AddVideoEffectAsync ein Objekt zurückgibt, das die IMediaExtension-Schnittstelle implementiert, die den hinzugefügten Videoeffekt darstellt. Bei einigen Effekten können die Effekteinstellungen geändert werden, indem Sie PropertySet an die SetProperties-Methode übergeben.

Ab Windows 10, Version 1607, können Sie auch das von AddVideoEffectAsync zurückgegebene Objekt verwenden, um den Effekt aus der Videopipeline zu entfernen, indem Sie es an RemoveEffectAsync übergeben. RemoveEffectAsync ermittelt automatisch, ob der Effektobjektparameter dem Vorschau- oder Aufnahmedatenstrom hinzugefügt wurde. Auf diese Weise müssen Sie beim Aufrufen keinen Datenstromtyp angeben.

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

Sie können auch alle Effekte aus dem Vorschau- oder Aufnahmedatenstrom entfernen, indem Sie ClearEffectsAsync aufrufen und den Datenstrom angeben, für den alle Effekte entfernt werden sollen.

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

Videostabilisierungseffekt

Der Videostabilisierungseffekt ändert die Frames eines Videodatenstroms, um das Wackeln durch das Halten des Aufnahmegeräts mit der Hand zu minimieren. Da durch diese Technik Pixel nach rechts, links, oben und unten verschoben werden und der Effekt den Inhalt außerhalb des Videoframes nicht kennen kann, wird das stabilisierte Video im Vergleich zum Originalvideo leicht zugeschnitten. Eine Hilfsfunktion wird bereitgestellt, damit Sie Ihre Videocodierungseinstellungen zum optimalen Verwalten der durch den Effekt vorgenommenen Zuschneidung anpassen können.

Auf Geräten, die dies unterstützen, stabilisiert OIS (Optical Image Stabilization) das Video durch mechanisches Manipulieren das Aufnahmegeräts, sodass die Kanten der Videoframes nicht zugeschnitten werden müssen. Weitere Informationen finden Sie unter Steuerelemente des Aufnahmegeräts für Videoaufnahmen.

Einrichten der App für die Verwendung der Videostabilisierung

Neben den Namespaces, die für die grundlegende Medienaufnahme erforderlich sind, erfordert die Verwendung des Videostabilisierungseffekts den folgenden Namespace.

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

Deklarieren Sie eine Membervariable zum Speichern des VideoStabilizationEffect-Objekts. Im Rahmen der Effektimplementierung ändern Sie die Codierungseigenschaften, die Sie für das Codieren des aufgezeichneten Videos verwenden. Deklarieren Sie zwei Variablen zum Speichern einer Sicherungskopie der ursprünglichen Eingabe- und Ausgabecodierungseigenschaften, sodass Sie diese später wiederherstellen können, wenn der Effekt deaktiviert ist. Deklarieren Sie abschließend eine Membervariable vom Typ MediaEncodingProfile, da auf dieses Objekt von mehreren Positionen innerhalb des Codes aus zugegriffen wird.

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

Für dieses Szenario sollten Sie einer Membervariablen das Profilobjekt für die Mediencodierung zuweisen, damit Sie später darauf zugreifen können.

_encodingProfile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Auto);

Initialisieren des Videostabilisierungseffekts

Erstellen Sie nach dem Initialisieren des MediaCapture-Objekts eine neue Instanz des VideoStabilizationEffectDefinition-Objekts. Rufen Sie MediaCapture.AddVideoEffectAsync auf, um den Effekt der Videopipeline hinzuzufügen und eine Instanz der VideoStabilizationEffect-Klasse abzurufen. Geben Sie MediaStreamType.VideoRecord an, um anzuzeigen, dass der Effekt auf den Videoaufnahmedatenstrom angewendet werden soll.

Registrieren Sie einen Ereignishandler für das Ereignis EnabledChanged, und rufen Sie die Hilfsmethode SetUpVideoStabilizationRecommendationAsync auf. Beide werden später in diesem Artikel erläutert. Legen Sie abschließend die Enabled-Eigenschaft des Effekts auf „true“ fest, um den Effekt zu aktivieren.

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

Wie weiter oben in diesem Artikel beschrieben wurde, verursacht die Technik, die der Videostabilisierungseffekt verwendet, eine geringe Zuschneidung des stabilisierten Videos im Vergleich zum Quellvideo. Definieren Sie die folgende Hilfsfunktion in Ihrem Code, um die Videocodierungseigenschaften anzupassen und diese Beschränkung des Effekts optimal zu verarbeiten. Dieser Schritt ist nicht erforderlich, um den Videostabilisierungseffekt zu verwenden. Wenn Sie diesen Schritt jedoch nicht ausführen, wird das resultierende Video leicht hochskaliert und hat dadurch eine etwas niedrigere Bildqualität.

Rufen Sie GetRecommendedStreamConfiguration für die Instanz des Videostabilisierungseffekts auf, übergeben Sie das VideoDeviceController-Objekt, das den Effekt über Ihre aktuellen Eingabedatenstrom-Codierungseigenschaften informiert, und Ihr MediaEncodingProfile, sodass der Effekt Ihre aktuellen Ausgabecodierungseigenschaften kennt. Diese Methode gibt ein VideoStreamConfiguration-Objekt zurück, das neue empfohlene Eingabe- und Ausgabedatenstrom-Codierungseigenschaften enthält.

Die empfohlenen Eingabecodierungseigenschaften bieten, sofern vom Gerät unterstützt, eine höhere Auflösung als die ursprünglichen Einstellungen, die Sie bereitgestellt haben, sodass es einen minimalen Datenverlust bei der Auflösung nach dem Anwenden der Zuschneidung des Effekts gibt.

Rufen Sie VideoDeviceController.SetMediaStreamPropertiesAsync auf, um die neuen Codierungseigenschaften festzulegen. Verwenden Sie vor dem Festlegen der neuen Eigenschaften die Membervariable, um die ursprünglichen Codierungseigenschaften zu speichern, damit Sie die Einstellungen wieder zurückändern können, wenn Sie den Effekt deaktivieren.

Wenn der Videostabilisierungseffekt das Ausgabevideo zuschneiden muss, entsprechen die empfohlenen Ausgabecodierungseigenschaften der Größe des zugeschnittenen Videos. Das bedeutet, dass die Ausgabeauflösung mit der Größe des zugeschnittenen Videos übereinstimmt. Wenn Sie die empfohlenen Ausgabeeigenschaften nicht verwenden, wird das Video hochskaliert, um der anfänglichen Ausgabegröße zu entsprechen, was zu einem Verlust an Bildqualität führt.

Legen Sie die Video-Eigenschaft des MediaEncodingProfile-Objekts fest. Verwenden Sie vor dem Festlegen der neuen Eigenschaften die Membervariable, um die ursprünglichen Codierungseigenschaften zu speichern, damit Sie die Einstellungen wieder zurückändern können, wenn Sie den Effekt deaktivieren.

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

Behandeln des Deaktivierens des Videostabilisierungseffekts

Das System kann den Videostabilisierungseffekt automatisch deaktivieren, wenn Sie der Pixeldurchsatz zu groß für die Verarbeitung durch den Effekt ist oder wenn erkannt wird, dass der Effekt langsam ausgeführt wird. In diesem Fall wird das „EnabledChanged“-Ereignis ausgelöst. Die VideoStabilizationEffect-Instanz im Parameter sender gibt den neuen Zustand des Effekts (aktiviert oder deaktiviert) an. VideoStabilizationEffectEnabledChangedEventArgs hat einen VideoStabilizationEffectEnabledChangedReason-Wert, der angibt, warum der Effekt aktiviert oder deaktiviert wurde. Beachten Sie, dass dieses Ereignis auch ausgelöst wird, wenn Sie den Effekt programmgesteuert aktivieren oder deaktivieren. In diesem Fall ist der Grund Programmatic.

In der Regel verwenden Sie dieses Ereignis zum Anpassen der Benutzeroberfläche Ihrer App, um den aktuellen Status der Videostabilisierung anzugeben.

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

Bereinigen des Videostabilisierungseffekts

Rufen Sie zum Bereinigen des Videostabilisierungseffekts RemoveEffectAsync auf, um den Effekt aus der Videopipeline zu entfernen. Wenn die Membervariablen mit den ursprünglichen Codierungseigenschaften nicht NULL sind, verwenden Sie diese zum Wiederherstellen der Codierungseigenschaften. Entfernen Sie schließlich den Ereignishandler EnabledChanged, und legen Sie den Effekt auf Null fest.

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