Wiedergeben von Audio- und Videoinhalten mit „MediaPlayer“Play audio and video with MediaPlayer

In diesem Artikel erfahren Sie, wie Sie in Ihrer universellen Windows-App mithilfe der MediaPlayer-Klasse Medien wiedergeben.This article shows you how to play media in your Universal Windows app using the MediaPlayer class. Mit Windows 10, Version 1607, wurden bedeutende Verbesserungen an den Medienwiedergabe-APIs vorgenommen, darunter ein vereinfachtes Einzel Prozessdesign für Hintergrund-Audiodaten, die automatische Integration in die System Media Transport-Steuerelemente (System Media Transport Controls, SMTC), die Möglichkeit zum Synchronisieren mehrerer Medien Player, die Möglichkeit zum renderingvideo Frames auf eine Windows. UIWith Windows 10, version 1607, significant improvements were made to the media playback APIs, including a simplified single-process design for background audio, automatic integration with the System Media Transport Controls (SMTC), the ability to synchronize multiple media players, the ability to render video frames to a Windows.UI.Composition surface, and an easy interface for creating and scheduling media breaks in your content. Um diese Verbesserungen optimal zu nutzen, sollten Sie für die Medienwiedergabe anstelle von MediaElement die MediaPlayer-Klasse verwenden.To take advantage of these improvements, the recommended best practice for playing media is to use the MediaPlayer class instead of MediaElement for media playback. Das einfache XAML-Steuerelement MediaPlayerElement wurde eingeführt, damit Sie Medieninhalte auf einer XAML-Seite rendern können.The lightweight XAML control, MediaPlayerElement, has been introduced to allow you render media content in a XAML page. Viele der von MediaElement bereitgestellten Wiedergabesteuerelemente und Status-APIs sind jetzt über das neue MediaPlaybackSession-Objekt verfügbar.Many of the playback control and status APIs provided by MediaElement are now available through the new MediaPlaybackSession object. MediaElement gewährleistet weiterhin die Abwärtskompatibilität. Dieser Klasse werden jedoch keine weiteren Features hinzugefügt.MediaElement continues to function to support backwards compatibility, but no additional features will be added to this class.

Dieser Artikel erläutert die Features von MediaPlayer, die von einer typischen App zur Medienwiedergabe verwendet werden.This article will walk you through the MediaPlayer features that a typical media playback app will use. Beachten Sie, dass MediaPlayer die MediaSource-Klasse als Container für alle Medienelemente verwendet.Note that MediaPlayer uses the MediaSource class as a container for all media items. Diese Klasse ermöglicht Ihnen das Laden und Wiedergeben von Medien aus verschiedenen Quellen – z. B. aus lokalen Dateien, Speicherdatenströmen und Netzwerkquellen – über die gleiche Schnittstelle.This class allows you to load and play media from many different sources, including local files, memory streams, and network sources, all using the same interface. Verschiedene Klassen auf höherer Ebene arbeiten ebenfalls mit MediaSource, z. B. MediaPlaybackItem und MediaPlaybackList. Sie stellen erweiterte Features bereit wie Wiedergabelisten und die Möglichkeit, Medienquellen mit mehreren Audio-, Video- und Metadatentiteln zu verwalten,There are also higher-level classes that work with MediaSource, such as MediaPlaybackItem and MediaPlaybackList, that provide more advanced features like playlists and the ability to manage media sources with multiple audio, video, and metadata tracks. Weitere Informationen zu MediaSource und verwandten APIs finden Sie unter Medienelemente, Wiedergabelisten und Titel.For more information on MediaSource and related APIs, see Media items, playlists, and tracks.

Hinweis

Die Editionen Windows 10 N und Windows 10 kn enthalten nicht die Medien Features, die für die Verwendung von Media Player für die Wiedergabe erforderlich sind.Windows 10 N and Windows 10 KN editions do not include the media features required to use MediaPlayer for playback. Diese Features können manuell installiert werden.These features can be installed manually. Weitere Informationen finden Sie unter Media Feature Pack für die Editionen Windows 10 N und Windows 10 kn.For more information, see Media feature pack for Windows 10 N and Windows 10 KN editions.

Wiedergeben einer Mediendatei mit „MediaPlayer“Play a media file with MediaPlayer

Die grundlegende Medienwiedergabe mit MediaPlayer ist sehr einfach zu implementieren.Basic media playback with MediaPlayer is very simple to implement. Erstellen Sie zunächst eine neue Instanz der MediaPlayer-Klasse.First, create a new instance of the MediaPlayer class. In Ihrer App können mehrere MediaPlayer-Instanzen gleichzeitig aktiv sein.Your app can have multiple MediaPlayer instances active at once. Legen Sie dann für die Source-Eigenschaft des Players ein Objekt fest, welches die IMediaPlaybackSource implementiert, z. B. eine MediaSource, ein MediaPlaybackItem oder eine MediaPlaybackList.Next, set the Source property of the player to an object that implements the IMediaPlaybackSource, such as a MediaSource, a MediaPlaybackItem, or a MediaPlaybackList. In diesem Beispiel wird ein MediaSource-Objekt aus einer Datei im lokalen Speicher der App erstellt. Anschließend wird aus der Quelle ein MediaPlaybackItem-Objekt erstellt und der Source-Eigenschaft des Players zugewiesen.In this example, a MediaSource is created from a file in the app's local storage, and then a MediaPlaybackItem is created from the source and then assigned to the player's Source property.

Anders als MediaElement startet MediaPlayer nicht standardmäßig automatisch mit der Wiedergabe.Unlike MediaElement, MediaPlayer does not automatically begin playback by default. Sie können die Wiedergabe starten, indem Sie Play aufrufen, für die AutoPlay -Eigenschaft „true“ festlegen oder warten, bis der Benutzer die Wiedergabe mit den integrierten Media-Steuerelementen startet.You can start playback by calling Play, by setting the AutoPlay property to true, or waiting for the user to initiate playback with the built-in media controls.

mediaPlayer = new MediaPlayer();
mediaPlayer.Source = MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/example_video.mkv"));
mediaPlayer.Play();

Wenn Ihre App die Verwendung eines MediaPlayers beendet hat, sollten Sie die MethodeClose aufrufen (Dispose-Methode in C#), um die vom Player verwendeten Ressourcen zu bereinigen.When your app is done using a MediaPlayer, you should call the Close method (projected to Dispose in C#) to clean up the resources used by the player.

mediaPlayer.Dispose();

Rendern von Videos in XAML mit MediaPlayerElementUse MediaPlayerElement to render video in XAML

Sie können Medien in einem MediaPlayer wiedergeben, ohne sie in XAML anzuzeigen. Viele Medienwiedergabe-Apps versuchen jedoch, die Medien auf einer XAML-Seite zu rendern.You can play media in a MediaPlayer without displaying it in XAML, but many media playback apps will want to render the media in a XAML page. Verwenden Sie hierfür das einfache MediaPlayerElement-Steuerelement.To do this, use the lightweight MediaPlayerElement control. Wie mit MediaElement können Sie mit MediaPlayerElement festlegen, ob die integrierten Transport-Steuerelemente angezeigt werden sollen.Like MediaElement, MediaPlayerElement allows you to specify whether the built-in transport controls should be shown.

<MediaPlayerElement x:Name="_mediaPlayerElement" AreTransportControlsEnabled="False" HorizontalAlignment="Stretch"  Grid.Row="0"/>

Sie können die MediaPlayer -Instanz festlegen, an die das Element gebunden ist, indem Sie SetMediaPlayer aufrufen.You can set the MediaPlayer instance that the element is bound to by calling SetMediaPlayer.

_mediaPlayerElement.SetMediaPlayer(mediaPlayer);

Sie können für das MediaPlayerElement auch die Wiedergabequelle festlegen. Das Element erstellt dann automatisch eine neue MediaPlayer-Instanz, auf die Sie mithilfe der MediaPlayer-Eigenschaft zugreifen können.You can also set the playback source on the MediaPlayerElement and the element will automatically create a new MediaPlayer instance that you can access using the MediaPlayer property.

_mediaPlayerElement.Source = MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/example_video.mkv"));
mediaPlayer = _mediaPlayerElement.MediaPlayer;
mediaPlayer.Play();

Hinweis

Wenn Sie MediaPlaybackCommandManager für MediaPlayer deaktivieren, indem Sie IsEnabled auf „false“ festlegen, wird die von MediaPlayerElement bereitgestellte Verknüpfung zwischen MediaPlayer und TransportControls getrennt, sodass die integrierten Transportsteuerelemente nicht mehr automatisch die Wiedergabe des Players steuern.If you disable the MediaPlaybackCommandManager of the MediaPlayer by setting IsEnabled to false, it will break the link between the MediaPlayer the TransportControls provided by the MediaPlayerElement, so the built-in transport controls will no longer automatically control the playback of the player. Stattdessen müssen Sie Ihre eigenen Steuerelemente zum Steuern des MediaPlayers implementieren.Instead, you must implement your own controls to control the MediaPlayer.

Allgemeine MediaPlayer-AufgabenCommon MediaPlayer tasks

In diesem Abschnitt erfahren Sie, wie Sie verschiedene Features des MediaPlayers verwenden.This section shows you how to use some of the features of the MediaPlayer.

Festlegen der AudioCategory-EigenschaftSet the audio category

Legen Sie für die Audiocategory-Eigenschaft eines MediaPlayers einen der Werte der MediaPlayerAudioCategory-Enumeration fest, um dem System mitzuteilen, welche Art von Medien Sie wiedergeben.Set the AudioCategory property of a MediaPlayer to one of the values of the MediaPlayerAudioCategory enumeration to let the system know what kind of media you are playing. Spiele sollten als Kategorie ihrer Musikdatenströme GameMedia angeben, sodass die Musik des Spiels automatisch auf stumm geschaltet wird, wenn eine andere Anwendung im Hintergrund Musik wiedergibt.Games should categorize their music streams as GameMedia so that game music mutes automatically if another application plays music in the background. Musik- oder Video-Apps sollten als Kategorien für ihre Datenströme Media oder Movie angeben, sodass ihnen gegenüber GameMedia-Datenströmen Priorität eingeräumt wird.Music or video applications should categorize their streams as Media or Movie so they will take priority over GameMedia streams.

mediaPlayer.AudioCategory = MediaPlayerAudioCategory.Media;

Ausgabe an einen bestimmten Audio-EndpunktOutput to a specific audio endpoint

Die Audioausgabe eines MediaPlayers wird standardmäßig zum Standard-Audio-Endpunkt des Systems geleitet. Sie können jedoch auch einen bestimmten Audio-Endpunkt als Ausgabe für den MediaPlayer festlegen.By default, the audio output from a MediaPlayer is routed to the default audio endpoint for the system, but you can specify a specific audio endpoint that the MediaPlayer should use for output. Im folgenden Beispiel gibt MediaDevice.GetAudioRenderSelector eine Zeichenfolge zur eindeutigen Identifizierung der Audiorendering-Kategorie von Geräten zurück.In the example below, MediaDevice.GetAudioRenderSelector returns a string that uniquely idenfies the audio render category of devices. Als Nächstes wird die DeviceInformation-Methode FindAllAsync aufgerufen, um eine Liste aller verfügbaren Geräte des ausgewählten Typs zu erstellen.Next, the DeviceInformation method FindAllAsync is called to get a list of all available devices of the selected type. Sie können programmgesteuert festlegen, welches Gerät Sie verwenden möchten, oder die zurückgegebenen Geräte zu einer ComboBox hinzufügen, damit der Benutzer ein Gerät auswählen kann.You may programmatically determine which device you want to use or add the returned devices to a ComboBox to allow the user to select a device.

string audioSelector = MediaDevice.GetAudioRenderSelector();
var outputDevices = await DeviceInformation.FindAllAsync(audioSelector);
foreach (var device in outputDevices)
{
    var deviceItem = new ComboBoxItem();
    deviceItem.Content = device.Name;
    deviceItem.Tag = device;
    _audioDeviceComboBox.Items.Add(deviceItem);
}

Im SelectionChanged-Ereignis für das Geräte-Kombinationsfeld wird die AudioDevice-Eigenschaft des MediaPlayers auf das ausgewählte Gerät festgelegt, die in der Tag-Eigenschaft des ComboBoxItem gespeichert wurde.In the SelectionChanged event for the devices combo box, the AudioDevice property of the MediaPlayer is set to the selected device, which was stored in the Tag property of the ComboBoxItem.

private void _audioDeviceComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    DeviceInformation selectedDevice = (DeviceInformation)((ComboBoxItem)_audioDeviceComboBox.SelectedItem).Tag;
    if (selectedDevice != null)
    {
        mediaPlayer.AudioDevice = selectedDevice;
    }
}

WiedergabesitzungPlayback session

Wie zuvor in diesem Artikel beschrieben, wurden viele der von der MediaElement-Klasse verfügbar gemachten Funktionen in die MediaPlaybackSession-Klasse verschoben.As described previously in this article, many of the functions that are exposed by the MediaElement class have been moved to the MediaPlaybackSession class. Dazu gehören Informationen über den Wiedergabestatus des Players, z. B. die aktuelle Wiedergabeposition, ob der Player Medien wiedergibt bzw. angehalten wurde sowie die aktuelle Wiedergabegeschwindigkeit.This includes information about the playback state of the player, such as the current playback position, whether the player is paused or playing, and the current playback speed. MediaPlaybackSession stellt außerdem einige Ereignisse bereit, um Sie bei Statusänderungen zu benachrichtigen. Dazu gehören der aktuelle Puffer- und Download-Status der wiedergegebenen Inhalte sowie die natürliche Größe und das Seitenverhältnis des aktuell wiedergegebenen Videoinhalts.MediaPlaybackSession also provides several events to notify you when the state changes, including the current buffering and download status of content being played and the natural size and aspect ratio of the currently playing video content.

Das folgende Beispiel zeigt, wie Sie einen Klickhandler für Schaltflächen implementieren können, der bei der Medienwiedergabe 10 Sekunden überspringt.The following example shows you how to implement a button click handler that skips 10 seconds forward in the content. Zuerst wird das MediaPlaybackSession-Objekt für den Player mit der PlaybackSession-Eigenschaft abgerufen.First, the MediaPlaybackSession object for the player is retrieved with the PlaybackSession property. Als Nächstes wird die Position-Eigenschaft auf die aktuelle Wiedergabeposition plus 10 Sekunden festgelegt.Next the Position property is set to the current playback position plus 10 seconds.

private void _skipForwardButton_Click(object sender, RoutedEventArgs e)
{
    var session = mediaPlayer.PlaybackSession;
    session.Position = session.Position + TimeSpan.FromSeconds(10);
}

Das nächste Beispiel zeigt, wie durch Einstellen der PlaybackRate-Eigenschaft der Sitzung mithilfe einer Schaltfläche zwischen der normalen Wiedergabegeschwindigkeit und zweifacher Geschwindigkeit gewechselt werden kann.The next example illustrates using a toggle button to toggle between normal playback speed and 2X speed by setting the PlaybackRate property of the session.

private void _speedToggleButton_Checked(object sender, RoutedEventArgs e)
{
    mediaPlayer.PlaybackSession.PlaybackRate = 2.0;
}
private void _speedToggleButton_Unchecked(object sender, RoutedEventArgs e)
{
    mediaPlayer.PlaybackSession.PlaybackRate = 1.0;
}

Ab Windows 10, Version 1803, können Sie die Drehung festlegen, mit der das Video in Media Player in Schritten von 90 Grad dargestellt wird.Starting with Windows 10, version 1803, you can set the rotation with which video is presented in the MediaPlayer in increments of 90 degrees.

mediaPlayer.PlaybackSession.PlaybackRotation = MediaRotation.Clockwise90Degrees;

Erwartete und unerwartete Pufferung erkennenDetect expected and unexpected buffering

Das im vorherigen Abschnitt beschriebene mediaplaybacksession -Objekt enthält zwei Ereignisse, die erkennen, wann die aktuell wiedergegebene Mediendatei beginnt und endet, BufferingStarted und BufferingEnded.The MediaPlaybackSession object described in the previous section provides two events for detecting when the currently playing media file begins and ends buffering, BufferingStarted and BufferingEnded. Auf diese Weise können Sie die Benutzeroberfläche aktualisieren, um den Benutzer anzuzeigen, dass eine Pufferung stattfindet.This allows you to update your UI to show the user that buffering is occurring. Die anfängliche Pufferung wird erwartet, wenn eine Mediendatei zum ersten Mal geöffnet wird oder wenn der Benutzer zu einem neuen Element in einer Wiedergabeliste wechselt.Initial buffering is expected when a media file is first opened or when the user switches to a new item in a playlist. Unerwartete Pufferung kann auftreten, wenn die Netzwerkgeschwindigkeit beeinträchtigt wird oder wenn das Inhalts Verwaltungssystem, das den Inhalt bereitstellt, technische Probleme hat.Unexpected buffering can occur when the network speed degrades or if the content management system providing the content experiences technical issues. Beginnend mit RS3 können Sie mit dem BufferingStarted -Ereignis ermitteln, ob das Puffer Ereignis erwartet wird, oder ob es unerwartet ist, und die Wiedergabe wird unterbrochen.Starting with RS3, you can use the BufferingStarted event to determine if the buffering event is expected or if it is unexpected and interrupting playback. Sie können diese Informationen als Telemetriedaten für Ihre APP oder den Media Delivery Service verwenden.You can use this information as telemetry data for your app or media delivery service.

Registrieren von Handlern für die BufferingStarted -und BufferingEnded -Ereignisse, um Puffer Zustands Benachrichtigungen zu empfangen.Register handlers for the BufferingStarted and BufferingEnded events to receive buffering state notifications.

mediaPlayer.PlaybackSession.BufferingStarted += MediaPlaybackSession_BufferingStarted;
mediaPlayer.PlaybackSession.BufferingEnded += MediaPlaybackSession_BufferingEnded;

Wandeln Sie im BufferingStarted -Ereignishandler die an das-Ereignis übergebenen Ereignis Argumente in ein mediaplaybacksessionbufferingstartedeventargs -Objekt um, und überprüfen Sie die isplaybackresolution -Eigenschaft.In the BufferingStarted event handler, cast the event args passed into the event to a MediaPlaybackSessionBufferingStartedEventArgs object and check the IsPlaybackInterruption property. Wenn dieser Wert true ist, ist die Pufferung, die das Ereignis ausgelöst hat, unerwartet und unterbricht die Wiedergabe.If this value is true, the buffering that triggered the event is unexpected and interrupting playback. Andernfalls wird die anfängliche Pufferung erwartet.Otherwise, it is expected initial buffering.

private void MediaPlaybackSession_BufferingStarted(MediaPlaybackSession sender, object args)
{
    MediaPlaybackSessionBufferingStartedEventArgs bufferingStartedEventArgs = args as MediaPlaybackSessionBufferingStartedEventArgs;
    if (bufferingStartedEventArgs != null && bufferingStartedEventArgs.IsPlaybackInterruption)
    {
        // update the playback quality telemetry report to indicate that
        // playback was interrupted
    }

    // update the UI to indicate that playback is buffering
}
private void MediaPlaybackSession_BufferingEnded(MediaPlaybackSession sender, object args)
{
    // update the UI to indicate that playback is no longer buffering
}

Zwei-Finger-Zoomen von VideoPinch and zoom video

MediaPlayer ermöglicht Ihnen, im Videoinhalt das zu rendernde Quellrechteck festzulegen und so in das Video hineinzuzoomen.MediaPlayer allows you to specify the source rectangle within video content that should be rendered, effectively allowing you to zoom into video. Das angegebene Rechteck bezieht sich auf ein normalisiertes Rechteck (0,0,1,1) wobei 0,0 der oberen linken Ecke des Frames entspricht und 1,1 die volle Breite und Höhe des Frames angibt.The rectangle you specify is relative to a normalized rectangle (0,0,1,1) where 0,0 is the upper left hand of the frame and 1,1 specifies the full width and height of the frame. Um beispielsweise das Zoomrechteck so festzulegen, dass der obere rechte Quadrant des Videos gerendert wird, müssten Sie das Rechteck wie folgt angeben: (.5,0,.5,.5).So, for example, to set the zoom rectangle so that the top-right quadrant of the video is rendered, you would specify the rectangle (.5,0,.5,.5). Es ist wichtig, die Werte zu überprüfen, um sicherzustellen, dass Ihr Quellrechteck sich innerhalb des normalisierten Rechtecks (0,0,1,1) befindet.It is important that you check your values to make sure that your source rectangle is within the (0,0,1,1) normalized rectangle. Durch den Versuch, einen Wert außerhalb dieses Bereichs festzulegen, wird eine Ausnahme ausgelöst.Attempting to set a value outside of this range will cause an exception to be thrown.

Um den Zwei-Finger-Zoom mithilfe von Multitouchbewegungen zu implementieren, müssen Sie zunächst angeben, welche Gesten unterstützt werden sollen.To implement pinch and zoom using multi-touch gestures, you must first specify which gestures you want to support. In diesem Beispiel wurden Gesten zum Skalieren und Übersetzen angefordert.In this example, scale and translate gestures are requested. Das ManipulationDelta-Ereignis wird ausgelöst, wenn eine der abonnierten Gesten auftritt.The ManipulationDelta event is raised when one of the subscribed gestures occurs. Das DoubleTapped-Ereignis wird verwendet, um den Zoom auf den vollständigen Frame zurückzusetzen.The DoubleTapped event will be used to reset the zoom to the full frame.

_mediaPlayerElement.ManipulationMode = ManipulationModes.Scale | ManipulationModes.TranslateX | ManipulationModes.TranslateY;
_mediaPlayerElement.ManipulationDelta += _mediaPlayerElement_ManipulationDelta;
_mediaPlayerElement.DoubleTapped += _mediaPlayerElement_DoubleTapped;

Deklarieren Sie als Nächstes ein Rect-Objekt, welches das aktuelle Zoom-Quellrechteck speichert.Next, declare a Rect object that will store the current zoom source rectangle.

Rect _sourceRect = new Rect(0, 0, 1, 1);

Der ManipulationDelta-Handler passt die Skalierung oder die Übersetzung des Zoom-Rechtecks an.The ManipulationDelta handler adjusts either the scale or the translation of the zoom rectangle. Ist der Deltawert für die Skalierung nicht 1, bedeutet dies, dass der Benutzer eine Zwei-Finger-Zoom-Geste ausgeführt hat.If the delta scale value is not 1, it means that the user performed a pinch gesture. Wenn der Wert größer als 1 ist, muss das Quellrechteck verkleinert werden, um den Inhalt zu vergrößern.If the value is greater than 1, the source rectangle should be made smaller to zoom into the content. Wenn der Wert kleiner als 1 ist, sollte das Quell Rechteck vergrößert werden, um verkleinert zu werden. Vor dem Festlegen der neuen Skalierungs Werte wird das resultierende Rechteck geprüft, um sicherzustellen, dass es vollständig innerhalb der Grenzwerte (0, 0, 1, 1) liegt.If the value is less than 1, then the source rectangle should be made bigger to zoom out. Before setting the new scale values, the resulting rectangle is checked to make sure it lies entirely within the (0,0,1,1) limits.

Wenn der Skalierungswert 1 ist, wird die Übersetzungsgeste behandelt.If the scale value is 1, then the translation gesture is handled. Das Rechteck wird wie folgt übersetzt: Anzahl der Pixel in der Geste geteilt durch die Breite und Höhe des Steuerelements.The rectangle is simply translated by the number of pixels in gesture divided by the width and height of the control. Wieder wird das resultierende Rechteck überprüft, um sicherzustellen, dass es innerhalb der Grenzen von (0,0,1,1) liegt.Again, the resulting rectangle is checked to make sure it lies within the (0,0,1,1) bounds.

Schließlich wird die NormalizedSourceRect-Eigenschaft der MediaPlaybackSession auf das neu angepasste Rechteck festgelegt. Dabei wird der Bereich innerhalb des Video-Frames angegeben, der gerendert werden soll.Finally, the NormalizedSourceRect of the MediaPlaybackSession is set to the newly adjusted rectangle, specifying the area within the video frame that should be rendered.

private void _mediaPlayerElement_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{

    if (e.Delta.Scale != 1)
    {
        var halfWidth = _sourceRect.Width / 2;
        var halfHeight = _sourceRect.Height / 2;

        var centerX = _sourceRect.X + halfWidth;
        var centerY = _sourceRect.Y + halfHeight;

        var scale = e.Delta.Scale;
        var newHalfWidth = (_sourceRect.Width * e.Delta.Scale) / 2;
        var newHalfHeight = (_sourceRect.Height * e.Delta.Scale) / 2;

        if (centerX - newHalfWidth > 0 && centerX + newHalfWidth <= 1.0 &&
            centerY - newHalfHeight > 0 && centerY + newHalfHeight <= 1.0)
        {
            _sourceRect.X = centerX - newHalfWidth;
            _sourceRect.Y = centerY - newHalfHeight;
            _sourceRect.Width *= e.Delta.Scale;
            _sourceRect.Height *= e.Delta.Scale;
        }
    }
    else
    {
        var translateX = -1 * e.Delta.Translation.X / _mediaPlayerElement.ActualWidth;
        var translateY = -1 * e.Delta.Translation.Y / _mediaPlayerElement.ActualHeight;

        if (_sourceRect.X + translateX >= 0 && _sourceRect.X + _sourceRect.Width + translateX <= 1.0 &&
            _sourceRect.Y + translateY >= 0 && _sourceRect.Y + _sourceRect.Height + translateY <= 1.0)
        {
            _sourceRect.X += translateX;
            _sourceRect.Y += translateY;
        }
    }

    mediaPlayer.PlaybackSession.NormalizedSourceRect = _sourceRect;
}

Im DoubleTapped-Ereignishandler wird das Quellrechteck wieder auf (0,0,1,1) festgelegt, damit der gesamte Videoframe gerendert wird.In the DoubleTapped event handler, the source rectangle is set back to (0,0,1,1) to cause the entire video frame to be rendered.

private void _mediaPlayerElement_DoubleTapped(object sender, DoubleTappedRoutedEventArgs e)
{
    _sourceRect = new Rect(0, 0, 1, 1);
    mediaPlayer.PlaybackSession.NormalizedSourceRect = _sourceRect;
}

Hinweis In diesem Abschnitt werden Berührungs Eingaben beschrieben.NOTE This section describes touch input. Touchpad sendet Zeiger Ereignisse und sendet keine Bearbeitungs Ereignisse.Touchpad sends pointer events and will not send Manipulation events.

Behandeln der Beeinträchtigung der Richtlinien basierten WiedergabeHandling policy-based playback degradation

In einigen Fällen kann das System die Wiedergabe eines Medien Elements beeinträchtigen, wie z. b. das Reduzieren der Auflösung (durch strierung), basierend auf einer Richtlinie und nicht mit einem Leistungsproblem.In some circumstances the system may degrade the playback of a media item, such as reducing the resolution (constriction), based on a policy rather than a performance issue. Beispielsweise kann das Video durch das System beeinträchtigt werden, wenn es mit einem nicht signierten Videotreiber wiedergegeben wird.For example, video may be degraded by the system if it is being played using an unsigned video driver. Sie können mediaplaybacksession. getoutputdegradationpolicystate aufrufen, um zu bestimmen, ob und warum diese Richtlinien basierte einer auftritt, und den Benutzer zu benachrichtigen oder den Grund für Telemetriezwecke aufzuzeichnen.You can call MediaPlaybackSession.GetOutputDegradationPolicyState to determine if and why this policy-based degredation is occurring and alert the user or record the reason for telemetry purposes.

Das folgende Beispiel zeigt eine Implementierung eines Handlers für das Media Player. mediageöffnete -Ereignis, das ausgelöst wird, wenn der Spieler ein neues Medien Element öffnet.The following example shows an implementation of a handler for the MediaPlayer.MediaOpened event that is raised when the player opens a new media item. Getoutputdegradationpolicystate wird für den Media Player aufgerufen, der an den-Handler weitergeleitet wird.GetOutputDegradationPolicyState is called on the MediaPlayer passed into the handler. Der Wert von videomenstrictionreason gibt den Grund für die Ursache des Videos an.The value of VideoConstrictionReason indicates the policy reason that the video is constricted. Wenn der Wert nicht " None" ist, protokolliert dieses Beispiel den Grund für die Herabstufung der Telemetrie.If the value isn't None, this example logs the degradation reason for telemetry purposes. Außerdem wird in diesem Beispiel gezeigt, wie die Bitrate der adaptivemediasource , die zurzeit wiedergegeben wird, auf die niedrigste Bandbreite festgelegt wird, um die Datennutzung zu sparen, da das Video verstrichen ist und trotzdem nicht mit hoher Auflösung angezeigt wird.This example also shows setting the bitrate of the AdaptiveMediaSource currently being played to the lowest bandwidth to save data usage, since the video is constricted and won't be displayed at high resolution anyway. Weitere Informationen zur Verwendung von adaptivemediasourcefinden Sie unter Adaptive Streaming.For more information on using AdaptiveMediaSource, see Adaptive streaming.

private void MediaPlayer_MediaOpened(MediaPlayer sender, object args)
{
    MediaPlaybackSessionOutputDegradationPolicyState info = sender.PlaybackSession.GetOutputDegradationPolicyState();

    if (info.VideoConstrictionReason != MediaPlaybackSessionVideoConstrictionReason.None)
    {
        // Switch to lowest bitrate to save bandwidth
        adaptiveMediaSource.DesiredMaxBitrate = adaptiveMediaSource.AvailableBitrates[0];

        // Log the degradation reason or show a message to the user
        System.Diagnostics.Debug.WriteLine("Logging constriction reason: " + info.VideoConstrictionReason);
    }
}

Rendern von Videos auf einer Windows.UI.Composition-Oberfläche mit MediaPlayerSurfaceUse MediaPlayerSurface to render video to a Windows.UI.Composition surface

Ab Windows 10, Version 1607, können Sie mit MediaPlayer Videos auf einer ICompositionSurface rendern. Dadurch kann der Player mit den APIs im Windows.UI.Composition-Namespace verwendet werden.Starting with Windows 10, version 1607, you can use MediaPlayer to render video to an to render video to an ICompositionSurface, which allows the player to interoperate with the APIs in the Windows.UI.Composition namespace. Das Kompositions-Framework ermöglicht Ihnen, auf der visuellen Ebene zwischen XAML und den DirectX-Grafik-APIs auf niedriger Ebene Grafiken zu verwenden.The composition framework allows you to work with graphics in the visual layer between XAML and the low-level DirectX graphics APIs. Dies ermöglicht Szenarien wie das Rendering von Videos in alle XAML-Steuerelemente.This enables scenarios like rendering video into any XAML control. Weitere Informationen zur Verwendung der Composition-APIs finden Sie unter visuelle Ebene.For more information on using the composition APIs, see Visual Layer.

Das folgende Beispiel veranschaulicht das Rendern von Inhalten des Videoplayers auf ein Canvas-Steuerelement.The following example illustrates how to render video player content onto a Canvas control. Die mediaplayerspezifischen Aufrufe in diesem Beispiel sind SetSurfaceSize und GetSurface.The media player-specific calls in this example are SetSurfaceSize and GetSurface. SetSurfaceSize teilt dem System die Größe des Puffers mit, der für das Rendern von Inhalten zugeordnet werden muss.SetSurfaceSize tells the system the size of the buffer that should be allocated for rendering content. GetSurface verwendet einen Compositor als Argument und ruft eine Instanz der MediaPlayerSurface-Klasse ab.GetSurface takes a Compositor as an arguemnt and retreives an instance of the MediaPlayerSurface class. Diese Klasse ermöglicht den Zugriff auf den MediaPlayer und den Compositor, mit denen die Oberfläche erstellt wird. Die Klasse macht außerdem die Oberfläche selbst über die CompositionSurface-Eigenschaft verfügbar.This class provides access to the MediaPlayer and Compositor used to create the surface and exposes the surface itself through the CompositionSurface property.

Der restliche Code in diesem Beispiel erstellt ein SpriteVisual-Element, in den das Video gerendert wird, und legt als Größe die Größe des Canvas-Elements fest, das das Visual anzeigt.The rest of the code in this example creates a SpriteVisual to which the video is rendered and sets the size to the size of the canvas element that will display the visual. Als Nächstes wird ein CompositionBrush aus der MediaPlayerSurface erstellt und der Brush-Eigenschaft des Visuals zugeordnet.Next a CompositionBrush is created from the MediaPlayerSurface and assigned to the Brush property of the visual. Dann wird ein ContainerVisual erstellt, und das SpriteVisual wird auf der oberen Ebene der visuellen Struktur eingefügt.Next a ContainerVisual is created and the SpriteVisual is inserted at the top of its visual tree. Schließlich wird SetElementChildVisual aufgerufen, um das Container-Visual dem Canvas zuzuordnen.Finally, SetElementChildVisual is called to assign the container visual to the Canvas.

mediaPlayer.SetSurfaceSize(new Size(_compositionCanvas.ActualWidth, _compositionCanvas.ActualHeight));

var compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
MediaPlayerSurface surface = mediaPlayer.GetSurface(compositor);

SpriteVisual spriteVisual = compositor.CreateSpriteVisual();
spriteVisual.Size =
    new System.Numerics.Vector2((float)_compositionCanvas.ActualWidth, (float)_compositionCanvas.ActualHeight);

CompositionBrush brush = compositor.CreateSurfaceBrush(surface.CompositionSurface);
spriteVisual.Brush = brush;

ContainerVisual container = compositor.CreateContainerVisual();
container.Children.InsertAtTop(spriteVisual);

ElementCompositionPreview.SetElementChildVisual(_compositionCanvas, container);

Synchronisieren von Inhalten zwischen mehreren Playern mit MediaTimelineControllerUse MediaTimelineController to synchronize content across multiple players.

Wie in diesem Artikel bereits erläutert, können in Ihrer App mehrere MediaPlayer-Objekte gleichzeitig aktiv sein.As discussed previously in this article, your app can have several MediaPlayer objects active at a time. Standardmäßig funktioniert jeder von Ihnen erstellte MediaPlayer unabhängig.By default, each MediaPlayer you create operates independently. In einigen Szenarien, z. B. beim Synchronisieren einer Kommentarspur mit einem Video, müssen möglicherweise der Status des Players, die Wiedergabeposition und die Wiedergabegeschwindigkeit von mehreren Playern synchronisiert werden.For some scenarios, such as synchronizing a commentary track to a video, you may want to synchronize the player state, playback position, and playback speed of multiple players. Ab Windows 10, Version 1607, können Sie dieses Verhalten mithilfe der MediaTimelineController-Klasse implementieren.Starting with Windows 10, version 1607, you can implement this behavior by using the MediaTimelineController class.

Implementieren der Wiedergabe-SteuerelementeImplement playback controls

Das folgende Beispiel zeigt, wie Sie mit einem MediaTimelineController zwei Instanzen des MediaPlayers steuern können.The following example shows how to use a MediaTimelineController to control two instances of MediaPlayer. Zuerst werden alle Instanzen des MediaPlayers instanziiert und eine Mediendatei als Source festgelegt.First, each instance of the MediaPlayer is instantiated and the Source is set to a media file. Als Nächstes wird eine neue MediaTimelineController-Klasse erstellt.Next, a new MediaTimelineController is created. Bei jedem MediaPlayer wird der mit den einzelnen Playern verknüpfte MediaPlaybackCommandManager deaktiviert, indem die IsEnabled-Eigenschaft auf „false“ festgelegt wird.For each MediaPlayer, the MediaPlaybackCommandManager associated with each player is disabled by setting the IsEnabled property to false. Und dann wird die timelinecontroller -Eigenschaft auf das Timeline Controller-Objekt festgelegt.And then the TimelineController property is set to the timeline controller object.

MediaTimelineController _mediaTimelineController;
mediaPlayer = new MediaPlayer();
mediaPlayer.Source = MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/example_video.mkv"));
_mediaPlayerElement.SetMediaPlayer(mediaPlayer);


_mediaPlayer2 = new MediaPlayer();
_mediaPlayer2.Source = MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/example_video_2.mkv"));
_mediaPlayerElement2.SetMediaPlayer(_mediaPlayer2);

_mediaTimelineController = new MediaTimelineController();

mediaPlayer.CommandManager.IsEnabled = false;
mediaPlayer.TimelineController = _mediaTimelineController;

_mediaPlayer2.CommandManager.IsEnabled = false;
_mediaPlayer2.TimelineController = _mediaTimelineController;

Achtung Die MediaPlaybackCommandManager-Klasse stellt eine automatische Integration zwischen MediaPlayer und den Steuerelementen für den Systemmedientransport (System Media Transport Controls, SMTC) bereit. Diese automatische Integration kann jedoch nicht für Media Player verwendet werden, die über eine MediaTimelineController-Klasse gesteuert werden.Caution The MediaPlaybackCommandManager provides automatic integration between MediaPlayer and the System Media Transport Controls (SMTC), but this automatic integration can't be used with media players that are controlled with a MediaTimelineController. Daher müssen Sie vor dem Festlegen des Zeitachsencontrollers des Players den Befehlsmanager des Media Players deaktivieren.Therefore you must disable the command manager for the media player before setting the player's timeline controller. Andernfalls wird eine Ausnahme mit der Benachrichtigung ausgelöst, dass das Anfügen des Medienzeitachsencontrollers im aktuellen Objektzustand blockiert wird.Failure to do so will result in an exception being thrown with the following message: "Attaching Media Timeline Controller is blocked because of the current state of the object." Weitere Informationen zur Integration des Media Players in die SMTC finden Sie unter Integration in die Steuerelemente für den Systemmedientransport.For more information on media player integration with the SMTC, see Integrate with the System Media Transport Controls. Auch wenn Sie eine MediaTimelineController-Klasse verwenden, können Sie die SMTC weiterhin manuell steuern.If you are using a MediaTimelineController you can still control the SMTC manually. Weitere Informationen finden Sie unter Manuelle Steuerung der Steuerelemente für den Systemmedientransport.For more information, see Manual control of the System Media Transport Controls.

Nachdem Sie eine MediaTimelineController-Klasse einem oder mehreren Media Player zugewiesen haben, können Sie den Wiedergabestatus mit den vom Controller bereitgestellten Methoden steuern.Once you have attached a MediaTimelineController to one or more media players, you can control the playback state by using the methods exposed by the controller. Im folgenden Beispiel wird Start aufgerufen, um die Wiedergabe aller zugeordneten Media Player zu Beginn des Mediums zu starten.The following example calls Start to begin playback of all associated media players at the beginning of the media.

private void PlayButton_Click(object sender, RoutedEventArgs e)
{
    _mediaTimelineController.Start();
}

Dieses Beispiel veranschaulicht das Anhalten und Fortsetzen aller zugeordneten Media Player.This example illustrates pausing and resuming all of the attached media players.

private void PauseButton_Click(object sender, RoutedEventArgs e)
{
    if(_mediaTimelineController.State == MediaTimelineControllerState.Running)
    {
        _mediaTimelineController.Pause();
        _pauseButton.Content = "Resume";
    }
    else
    {
        _mediaTimelineController.Resume();
        _pauseButton.Content = "Pause";
    }
}

Für den schnellen Vorlauf aller verbundenen Media Player muss die Wiedergabegeschwindigkeit auf einen Wert größer als 1 festgelegt werden.To fast-forward all connected media players, set the playback speed to a value greater that 1.

private void FastForwardButton_Click(object sender, RoutedEventArgs e)
{
    _mediaTimelineController.ClockRate = 2.0;
}

Das nächste Beispiel zeigt die Verwendung eines Slider-Steuerelements, um die aktuelle Wiedergabeposition des Zeitachsencontrollers in Relation zum Inhalt eines der verbundenen Media Player anzuzeigen.The next example shows how to use a Slider control to show the current playback position of the timeline controller relative to the duration of the content of one of the connected media players. Zunächst wird eine neue MediaSource erstellt und ein Handler für das OpenOperationCompleted-Ereignis der Medienquelle registriert.First, a new MediaSource is created and a handler for the OpenOperationCompleted of the media source is registered.

var mediaSource = MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/example_video.mkv"));
mediaSource.OpenOperationCompleted += MediaSource_OpenOperationCompleted;
mediaPlayer.Source = mediaSource;
_mediaPlayerElement.SetMediaPlayer(mediaPlayer);

Der OpenOperationCompleted-Handler bietet eine Möglichkeit, um die Dauer des Inhalts der Medienquelle festzustellen.The OpenOperationCompleted handler is used as an opportunity to discover the duration of the media source content. Sobald die Dauer bestimmt ist, wird der Höchstwert des Slider-Steuerelements auf die Gesamtzahl der Sekunden des Medienelements festgelegt.Once the duration is determined, the maximum value of the Slider control is set to the total number of seconds of the media item. Der Wert wird innerhalb eines Aufrufs von RunAsync festgelegt, um sicherzustellen, dass es im UI-Thread ausgeführt wird.The value is set inside a call to RunAsync to make sure it is run on the UI thread.

TimeSpan _duration;
private async void MediaSource_OpenOperationCompleted(MediaSource sender, MediaSourceOpenOperationCompletedEventArgs args)
{
    _duration = sender.Duration.GetValueOrDefault();

    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        _positionSlider.Minimum = 0;
        _positionSlider.Maximum = _duration.TotalSeconds;
        _positionSlider.StepFrequency = 1;
    }); 
}

Als Nächstes wird ein Handler für das PositionChanged-Ereignis des Zeitachsencontrollers registriert.Next, a handler for the timeline controller's PositionChanged event is registered. Dieses wird in regelmäßigen Abständen durch das System aufgerufen, ungefähr viermal pro Sekunde.This is called periodically by the system, approximately 4 times per second.

_mediaTimelineController.PositionChanged += _mediaTimelineController_PositionChanged;

Im Handler für PositionChanged wird der Schiebereglerwert aktualisiert, sodass er die aktuelle Position des Zeitachsencontrollers wiedergibt.In the handler for PositionChanged, the slider value is updated to reflect the current position of the timeline controller.

private async void _mediaTimelineController_PositionChanged(MediaTimelineController sender, object args)
{
    if (_duration != TimeSpan.Zero)
    {
        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            _positionSlider.Value = sender.Position.TotalSeconds / (float)_duration.TotalSeconds;
        });
    }
}

Versetzen der Wiedergabeposition in Relation zur ZeitachsenpositionOffset the playback position from the timeline position

In einigen Fällen soll möglicherweise die Wiedergabeposition eines oder mehrerer mit einem Zeitachsencontroller verknüpften Media Player in Relation zu den anderen Playern versetzt werden.In some cases you may want the playback position of one or more media players associated with a timeline controller to be offset from the other players. Dafür können Sie die TimelineControllerPositionOffset-Eigenschaft des MediaPlayer-Objekts festlegen, welches versetzt werden soll.You can do this by setting the TimelineControllerPositionOffset property of the MediaPlayer object you want to be offset. Im folgenden Beispiel wird anhand der jeweiligen Dauer des Inhalts von zwei Media Playern der Minimal- und Maximalwert von zwei Schieberegler-Steuerelementen festgelegt, um die Länge des Elements zu verkürzen bzw. zu verlängern.The following example uses the durations of the content of two media players to set the minimum and maximum values of two slider control to plus and minus the length of the item.

_timelineOffsetSlider1.Minimum = -1 * _duration.TotalSeconds;
_timelineOffsetSlider1.Maximum = _duration.TotalSeconds;
_timelineOffsetSlider1.StepFrequency = 1;

_timelineOffsetSlider2.Minimum = -1 * _duration2.TotalSeconds;
_timelineOffsetSlider2.Maximum = _duration2.TotalSeconds;
_timelineOffsetSlider2.StepFrequency = 1;

Im ValueChanged-Ereignis jedes Schiebereglers wird TimelineControllerPositionOffset für jeden Player auf den entsprechenden Wert festgelegt.In the ValueChanged event for each slider, the TimelineControllerPositionOffset for each player is set to the corresponding value.

private void _timelineOffsetSlider1_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
{
    mediaPlayer.TimelineControllerPositionOffset = TimeSpan.FromSeconds(_timelineOffsetSlider1.Value);
}

private void _timelineOffsetSlider2_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
{
    _mediaPlayer2.TimelineControllerPositionOffset = TimeSpan.FromSeconds(_timelineOffsetSlider2.Value);
}

Beachten Sie: Wird der Offsetwert eines Players einer negativen Wiedergabeposition zugeordnet, wird der Clip angehalten, bis der Offset den Wert Null erreicht. Anschließend beginnt die Wiedergabe.Note that if the offset value of a player maps to a negative playback position, the clip will remain paused until the offset reaches zero and then playback will begin. Wenn der Offsetwert einer Wiedergabeposition zugeordnet ist, welche die Dauer des Medientitels überschreitet, wird entsprechend das letzte Bild angezeigt. Dies entspricht dem Vorgehen, wenn ein einzelner Media Player das Ende der Inhaltswiedergabe erreicht.Likewise, if the offset value maps to a playback position greater than the duration of the media item, the final frame will be shown, just as it does when a single media player reached the end of its content.

Abspielen von sphärischen Videos mit Media PlayerPlay spherical video with MediaPlayer

Ab Windows 10, Version 1703, unterstützt Media Player die equirecht eckige Projektion für die Wiedergabe von kugelförmigen Videos.Starting with Windows 10, version 1703, MediaPlayer supports equirectangular projection for spherical video playback. Der Inhalt von kugelförmigen Videos unterscheidet sich nicht von regulärem, flatvideo, da Media Player das Video so lange Rendering wird, wie die Videocodierung unterstützt wird.Spherical video content is no different from regular, flat video in that MediaPlayer will render the video as long as the video encoding is supported. Bei einem sphärischen Video, das ein Metadatentag enthält, das angibt, dass das Video eine equirecht eckige Projektion verwendet, kann Media Player das Video mithilfe eines angegebenen Felds von Ansicht und Anzeige Ausrichtung Rendering.For spherical video that contains a metadata tag that specifies that the video uses equirectangular projection, MediaPlayer can render the video using a specified field-of-view and view orientation. Dies ermöglicht Szenarien wie die Videowiedergabe von Virtual Reality mit einer am Anfang eingebundenen Anzeige oder die einfache Navigation innerhalb von sphärischen Videoinhalten mithilfe der Maus-oder Tastatureingaben.This enables scenarios such as virtual reality video playback with a head-mounted display or simply allowing the user to pan around within spherical video content using the mouse or keyboard input.

Zum Wiedergeben von sphärischen Videos führen Sie die Schritte zum Wiedergeben von Videoinhalten aus, die zuvor in diesem Artikel beschrieben wurden.To play back spherical video, use the steps for playing back video content described previously in this article. Der einzige zusätzliche Schritt ist die Registrierung eines Handlers für das Media Player. mediageöffnete -Ereignis.The one additional step is to register a handler for the MediaPlayer.MediaOpened event. Dieses Ereignis bietet Ihnen die Möglichkeit, die Parameter für die sphärischen Videowiedergabe zu aktivieren und zu steuern.This event gives you an opportunity to enable and control the spherical video playback parameters.

mediaPlayer = new MediaPlayer();
mediaPlayer.MediaOpened += _mediaPlayer_MediaOpened;
mediaPlayer.Source = MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/example_video_spherical.mp4"));
_mediaPlayerElement.SetMediaPlayer(mediaPlayer);
mediaPlayer.Play();

Überprüfen Sie im mediageöffneten -Handler zuerst das Frame Format des neu geöffneten Medien Elements, indem Sie die Eigenschaft playbacksession. sphericalvideoprojection. frameformat überprüfen.In the MediaOpened handler, first check the frame format of the newly opened media item by checking the PlaybackSession.SphericalVideoProjection.FrameFormat property. Wenn dieser Wert sphericavideoframeformat. equirecht eckigist, kann das System den Videoinhalt automatisch projizieren.If this value is SphericaVideoFrameFormat.Equirectangular, then the system can automatically project the video content. Legen Sie zunächst die Eigenschaft playbacksession. sphericalvideoprojection. isaktiviauf truefest.First, set the PlaybackSession.SphericalVideoProjection.IsEnabled property to true. Sie können auch Eigenschaften anpassen, z. b. die Ansichts Ausrichtung und das Sichtfeld, die der Media Player zum Projizieren des Video Inhalts verwendet.You can also adjust properties such as the view orientation and field of view that the media player will use to project the video content. In diesem Beispiel wird das Feld der Ansicht auf einen Breitenwert von 120 Grad festgelegt, indem die horizontalfieldofviewindegrees -Eigenschaft festgelegt wird.In this example, the field of view is set to a wide value of 120 degrees by setting the HorizontalFieldOfViewInDegrees property.

Wenn der Videoinhalt kugelförmig ist, aber in einem anderen Format als equirecht eckig vorliegt, können Sie mit dem Frame Server Modus von Media Player einen eigenen Projektions Algorithmus implementieren, um einzelne Frames zu empfangen und zu verarbeiten.If the video content is spherical, but is in a format other than equirectangular, you can implement your own projection algorithm using the media player's frame server mode to receive and process individual frames.

private void _mediaPlayer_MediaOpened(MediaPlayer sender, object args)
{
    if (sender.PlaybackSession.SphericalVideoProjection.FrameFormat == SphericalVideoFrameFormat.Equirectangular)
    {
        sender.PlaybackSession.SphericalVideoProjection.IsEnabled = true;
        sender.PlaybackSession.SphericalVideoProjection.HorizontalFieldOfViewInDegrees = 120;

    }
    else if (sender.PlaybackSession.SphericalVideoProjection.FrameFormat == SphericalVideoFrameFormat.Unsupported)
    {
        // If the spherical format is unsupported, you can use frame server mode to implement a custom projection
    }
}

Der folgende Beispielcode veranschaulicht, wie die Ausrichtung der kugelförmigen Videoansicht mithilfe der nach-links-und nach-rechts-Taste angepasst wird.The following example code illustrates how to adjust the spherical video view orientation using the left and right arrow keys.

protected override void OnKeyDown(KeyRoutedEventArgs e)
{
    if (mediaPlayer.PlaybackSession.SphericalVideoProjection.FrameFormat != SphericalVideoFrameFormat.Equirectangular)
    {
        return;
    }

    switch (e.Key)
    {
        case Windows.System.VirtualKey.Right:
            mediaPlayer.PlaybackSession.SphericalVideoProjection.ViewOrientation *= Quaternion.CreateFromYawPitchRoll(.1f, 0, 0);
            break;
        case Windows.System.VirtualKey.Left:
            mediaPlayer.PlaybackSession.SphericalVideoProjection.ViewOrientation *= Quaternion.CreateFromYawPitchRoll(-.1f, 0, 0);
            break;
    }
}

Wenn Ihre APP Wiedergabelisten von Videos unterstützt, möchten Sie möglicherweise Wiedergabe Elemente identifizieren, die das sphärischen Video in der Benutzeroberfläche enthalten.If your app supports playlists of video, you may want to identify playback items that contain spherical video in your UI. Medienwiedergabe Listen werden im Artikel Medienelemente, Wiedergabelisten und Spurenausführlich erläutert.Media playlists are discussed in detail in the article, Media items, playlists, and tracks. Das folgende Beispiel zeigt das Erstellen einer neuen Wiedergabeliste, das Hinzufügen eines Elements und das Registrieren eines Handlers für das mediaplaybackitem. videotrackschangi- Ereignis, das auftritt, wenn die Videotitel für ein Medien Element aufgelöst werden.The following example shows creating a new playlist, adding an item, and registering a handler for the MediaPlaybackItem.VideoTracksChanged event, which occurs when the video tracks for a media item are resolved.

var playbackList = new MediaPlaybackList();
var item = new MediaPlaybackItem(MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/RIFTCOASTER HD_injected.mp4")));
item.VideoTracksChanged += Item_VideoTracksChanged;
playbackList.Items.Add(item);
mediaPlayer.Source = playbackList;

Rufen Sie im videotrackschge -Ereignishandler die Codierungs Eigenschaften für alle hinzugefügten Videotitel durch Aufrufen von Videotrack. getencodingpropertiesab.In the VideoTracksChanged event handler, get the encoding properties for any added video tracks by calling VideoTrack.GetEncodingProperties. Wenn die sphericalvideoframeformat -Eigenschaft der Codierungs Eigenschaften ein anderer Wert als sphericavideoframeformat. Noneist, enthält die Videospur das sphärischen Video, und Sie können die Benutzeroberfläche entsprechend aktualisieren.If the SphericalVideoFrameFormat property of the encoding properties is a value other than SphericaVideoFrameFormat.None, then the video track contains spherical video and you can update your UI accordingly if you choose.

private void Item_VideoTracksChanged(MediaPlaybackItem sender, IVectorChangedEventArgs args)
{
    if (args.CollectionChange != CollectionChange.ItemInserted)
    {
        return;
    }
    foreach (var videoTrack in sender.VideoTracks)
    {
        if (videoTrack.GetEncodingProperties().SphericalVideoFrameFormat != SphericalVideoFrameFormat.None)
        {
            // Optionally indicate in the UI that this item contains spherical video
        }
    }
}

Verwenden von Media Player im Frame Server ModusUse MediaPlayer in frame server mode

Ab Windows 10, Version 1703, können Sie Media Player im Frame Server Modus verwenden.Starting with Windows 10, version 1703, you can use MediaPlayer in frame server mode. In diesem Modus renbt Media Player keine Frames automatisch zu einem zugeordneten mediaplayerelement.In this mode, the MediaPlayer does not automatically render frames to an associated MediaPlayerElement. Stattdessen kopiert Ihre APP den aktuellen Frame vom Media Player in ein Objekt, das IDirect3DSurfaceimplementiert.Instead, your app copies the current frame from the MediaPlayer to an object that implements IDirect3DSurface. Das primäre Szenario, das diese Funktion ermöglicht, besteht in der Verwendung von Pixel-Shadern, um von Media Playerbereitgestellte Video Frames zu verarbeitenThe primary scenario this feature enables is using pixel shaders to process video frames provided by the MediaPlayer. Ihre APP ist für die Anzeige der einzelnen Frames nach der Verarbeitung zuständig, z. b. durch Anzeigen des Frames in einem XAML- Bild -Steuerelement.Your app is responsible for displaying each frame after processing, such as by showing the frame in a XAML Image control.

Im folgenden Beispiel wird ein neuer Media Player initialisiert, und Videoinhalt wird geladen.In the following example, a new MediaPlayer is initialized and video content is loaded. Als nächstes wird ein Handler für videoframeavailable registriert.Next, a handler for VideoFrameAvailable is registered. Der Frame Server Modus wird aktiviert, indem die isvideoframeserveraktivierte Eigenschaft des Media Player -Objekts auf " true" festgelegt wird.Frame server mode is enabled by setting the MediaPlayer object's IsVideoFrameServerEnabled property to true. Zum Schluss wird die Medienwiedergabe mit einem Play-Befehl gestartet.Finally, media playback is started with a call to Play.

mediaPlayer = new MediaPlayer();
mediaPlayer.Source = MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/example_video.mkv"));
mediaPlayer.VideoFrameAvailable += mediaPlayer_VideoFrameAvailable;
mediaPlayer.IsVideoFrameServerEnabled = true;
mediaPlayer.Play();

Das nächste Beispiel zeigt einen Handler für videoframeavailable , der Win2D verwendet, um jedem Frame eines Videos einen einfachen Weichzeichnereffekt hinzuzufügen, und dann die verarbeiteten Frames in einem XAML- Bild Steuerelement anzeigt.The next example shows a handler for VideoFrameAvailable that uses Win2D to add a simple blur effect to each frame of a video and then displays the processed frames in a XAML Image control.

Wenn der videoframeavailable -Handler aufgerufen wird, wird die copyframetovideosurface -Methode verwendet, um den Inhalt des Frames in ein IDirect3DSurfacezu kopieren.Whenever the VideoFrameAvailable handler is called, the CopyFrameToVideoSurface method is used to copy the contents of the frame to an IDirect3DSurface. Sie können auch copyframedestereoscopicvideo-Oberflächen verwenden, um 3D-Inhalte in zwei Oberflächen zu kopieren, um den linken und den rechten Inhalt separat zu verarbeiten.You can also use CopyFrameToStereoscopicVideoSurfaces to copy 3D content into two surfaces, for processing the left eye and right eye content separately. Um ein Objekt zu erhalten, das implementiert IDirect3DSurface in diesem Beispiel wird eine softwardaemmap erstellt. Anschließend wird dieses Objekt verwendet, um eine Win2D canvasbitmapzu erstellen, die die erforderliche Schnittstelle implementiert.To get an object that implements IDirect3DSurface this example creates a SoftwareBitmap and then uses that object to create a Win2D CanvasBitmap, which implements the necessary interface. Eine canvasimagesource ist ein Win2D-Objekt, das als Quelle für ein Image -Steuerelement verwendet werden kann, sodass ein neues erstellt und als Quelle für das Bild festgelegt wird, in dem der Inhalt angezeigt wird.A CanvasImageSource is a Win2D object that can be used as the source for an Image control, so a new one is created and set as the source for the Image in which the content will be displayed. Als nächstes wird eine canvasdrawingsession erstellt.Next, a CanvasDrawingSession is created. Diese wird von Win2D verwendet, um den Weichzeichnereffekt zu erzeugen.This is used by Win2D to render the blur effect.

Nachdem alle erforderlichen Objekte instanziiert wurden, wird copyframeumvideosurface aufgerufen, das den aktuellen Frame aus Media Player in die canvasbitmapkopiert.Once all of the necessary objects have been instantiated, CopyFrameToVideoSurface is called, which copies the current frame from the MediaPlayer into the CanvasBitmap. Als nächstes wird ein Win2D gausianblureffect erstellt, wobei die canvasbitmap als Quelle des Vorgangs festgelegt ist.Next, a Win2D GaussianBlurEffect is created, with the CanvasBitmap set as the source of the operation. Schließlich wird " canvasdrawingsession. DrawImage " aufgerufen, um das Quell Bild, bei dem der weich Zieh Effekt angewendet wurde, in " canvasimagesource " zu zeichnen, das dem Image -Steuerelement zugeordnet ist, was dazu führt, dass es in der Benutzeroberfläche gezeichnet wird.Finally, CanvasDrawingSession.DrawImage is called to draw the source image, with the blur effect applied, into the CanvasImageSource that has been associated with Image control, causing it to be drawn in the UI.

private async void mediaPlayer_VideoFrameAvailable(MediaPlayer sender, object args)
{
    CanvasDevice canvasDevice = CanvasDevice.GetSharedDevice();

    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        if(frameServerDest == null)
        {
            // FrameServerImage in this example is a XAML image control
            frameServerDest = new SoftwareBitmap(BitmapPixelFormat.Rgba8, (int)FrameServerImage.Width, (int)FrameServerImage.Height, BitmapAlphaMode.Ignore);
        }
        if(canvasImageSource == null)
        {
            canvasImageSource = new CanvasImageSource(canvasDevice, (int)FrameServerImage.Width, (int)FrameServerImage.Height, DisplayInformation.GetForCurrentView().LogicalDpi);//96); 
            FrameServerImage.Source = canvasImageSource;
        }

        using (CanvasBitmap inputBitmap = CanvasBitmap.CreateFromSoftwareBitmap(canvasDevice, frameServerDest))
        using (CanvasDrawingSession ds = canvasImageSource.CreateDrawingSession(Windows.UI.Colors.Black))
        {

            mediaPlayer.CopyFrameToVideoSurface(inputBitmap);

            var gaussianBlurEffect = new GaussianBlurEffect
            {
                Source = inputBitmap,
                BlurAmount = 5f,
                Optimization = EffectOptimization.Speed
            };

            ds.DrawImage(gaussianBlurEffect);

        }
    });
}

private void FrameServerSubtitlesButton_Click(object sender, RoutedEventArgs e)
{

    mediaPlayer = new MediaPlayer();
    var source = MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/example_video.mkv"));
    var item = new MediaPlaybackItem(source);

    item.TimedMetadataTracksChanged += Item_TimedMetadataTracksChanged;


    mediaPlayer.Source = item;
    mediaPlayer.VideoFrameAvailable += mediaPlayer_VideoFrameAvailable_Subtitle;
    mediaPlayer.IsVideoFrameServerEnabled = true;
    mediaPlayer.Play();

    mediaPlayer.IsMuted = true;

}

private void Item_TimedMetadataTracksChanged(MediaPlaybackItem sender, IVectorChangedEventArgs args)
{
    if(sender.TimedMetadataTracks.Count > 0)
    {
        sender.TimedMetadataTracks.SetPresentationMode(0, TimedMetadataTrackPresentationMode.PlatformPresented);
    }
}

private async void mediaPlayer_VideoFrameAvailable_Subtitle(MediaPlayer sender, object args)
{
    CanvasDevice canvasDevice = CanvasDevice.GetSharedDevice();

    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        if (frameServerDest == null)
        {
            // FrameServerImage in this example is a XAML image control
            frameServerDest = new SoftwareBitmap(BitmapPixelFormat.Rgba8, (int)FrameServerImage.Width, (int)FrameServerImage.Height, BitmapAlphaMode.Ignore);
        }
        if (canvasImageSource == null)
        {
            canvasImageSource = new CanvasImageSource(canvasDevice, (int)FrameServerImage.Width, (int)FrameServerImage.Height, DisplayInformation.GetForCurrentView().LogicalDpi);//96); 
            FrameServerImage.Source = canvasImageSource;
        }

        using (CanvasBitmap inputBitmap = CanvasBitmap.CreateFromSoftwareBitmap(canvasDevice, frameServerDest))
        {
            using (CanvasDrawingSession ds = canvasImageSource.CreateDrawingSession(Windows.UI.Colors.Black))
            {

                mediaPlayer.CopyFrameToVideoSurface(inputBitmap);

                //Rect subtitleTargetRect = new Rect(0, 0, inputBitmap.Bounds.Width, inputBitmap.Bounds.Bottom * .1);
                Rect subtitleTargetRect = new Rect(0, 0, 100, 100);

                mediaPlayer.RenderSubtitlesToSurface(inputBitmap);//, subtitleTargetRect);

                //var gaussianBlurEffect = new GaussianBlurEffect
                //{
                //    Source = inputBitmap,
                //    BlurAmount = 5f,
                //    Optimization = EffectOptimization.Speed
                //};

                //ds.DrawImage(gaussianBlurEffect);

                ds.DrawImage(inputBitmap);
            }
        }
    });
}

Weitere Informationen zu Win2D finden Sie im Win2D GitHub-Repository.For more information on Win2D, see the Win2D GitHub repository. Wenn Sie den oben gezeigten Beispielcode ausprobieren möchten, müssen Sie das nuget-Paket Win2D mit den folgenden Anweisungen zu Ihrem Projekt hinzufügen.To try out the sample code shown above, you will need to add the Win2D NuGet package to your project with the following instructions.

So fügen Sie das Win2D-NuGet-Paket zum Effektprojekt hinzuTo add the Win2D NuGet package to your effect project

  1. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, und wählen Sie NuGet-Pakete verwalten aus.In Solution Explorer, right-click your project and select Manage NuGet Packages.
  2. Wählen Sie oben im Fenster die Registerkarte Durchsuchen aus.At the top of the window, select the Browse tab.
  3. Geben Sie im Suchfeld Win2D ein.In the search box, enter Win2D.
  4. Wählen Sie Win2D.uwp und anschließend im rechten Bereich Installieren aus.Select Win2D.uwp, and then select Install in the right pane.
  5. Im Dialogfeld Änderungen überprüfen wird das zu installierende Paket angezeigt.The Review Changes dialog shows you the package to be installed. Klicken Sie auf OK.Click OK.
  6. Akzeptieren Sie die Paketlizenz.Accept the package license.

Erkennen und reagieren auf audioleveländerungen durch das SystemDetect and respond to audio level changes by the system

Ab Windows 10, Version 1803, kann Ihre APP erkennen, wenn das System die Audioebene eines gerade wiedergegebenen Media Player-oder-Mutes absinkt.Starting with Windows 10, version 1803, your app can detect when the system lowers or mutes the audio level of a currently playing MediaPlayer. Beispielsweise kann das System die Audiowiedergabe Ebene verringern oder "Enten", wenn ein Alarm klingelt.For example, the system may lower, or "duck", the audio playback level when an alarm is ringing. Das System wird Ihre APP stumm schalten, wenn Sie in den Hintergrund wechselt, wenn Ihre APP die backgroundmediaplayback -Funktion nicht im App-Manifest deklariert hat.The system will mute your app when it goes into the background if your app has not declared the backgroundMediaPlayback capability in the app manifest. Die audiostatuemonitor -Klasse ermöglicht es Ihnen, sich für den Empfang eines Ereignisses zu registrieren, wenn das System das Volume eines Audiodatenstroms ändert.The AudioStateMonitor class allows you to register to receive an event when the system modifies the volume of an audio stream. Greifen Sie auf die audiostatuemonitor -Eigenschaft eines Media Player zu, und registrieren Sie einen Handler für das soundlevelchanged -Ereignis, um benachrichtigt zu werden, wenn die Audioebene für den Media Player vom System geändert wird.Access the AudioStateMonitor property of a MediaPlayer and register a handler for the SoundLevelChanged event to be notified when the audio level for that MediaPlayer is changed by the system.

mediaPlayer.AudioStateMonitor.SoundLevelChanged += AudioStateMonitor_SoundLevelChanged;

Wenn Sie das Sound levelchanged -Ereignis verarbeiten, können Sie je nach Art der wiedergegebenen Inhalte verschiedene Aktionen ausführen.When handling the SoundLevelChanged event, you may take different actions depending on the type of content being played. Wenn Sie derzeit Musik spielen, sollten Sie die Musik wiedergeben lassen, während das Volume geduckt ist.If you are currently playing music, then you may want to let the music continue to play while the volume is ducked. Wenn Sie jedoch einen Podcast spielen, möchten Sie die Wiedergabe wahrscheinlich anhalten, während das Audiogerät geduckt wird, damit der Benutzer den Inhalt nicht verpasst.If you are playing a podcast, however, you likely want to pause playback while the audio is ducked so the user doesn't miss any of the content.

In diesem Beispiel wird eine Variable deklariert, um zu verfolgen, ob es sich bei dem aktuell wiedergegebenen Inhalt um einen Podcast handelt. es wird davon ausgegangen, dass Sie diesen Wert beim Auswählen des Media Player-Inhalts auf den entsprechenden Wert festlegenThis example declares a variable to track whether the currently playing content is a podcast, it is assumed that you set this to the appropriate value when selecting the content for the MediaPlayer. Außerdem wird eine Klassen Variable erstellt, die nachverfolgt werden soll, wenn die Wiedergabe beim Ändern der Audioebene Programm gesteuert angehalten wird.We also create a class variable to track when we pause playback programmatically when the audio level changes.

bool isPodcast;
bool isPausedDueToAudioStateMonitor;

Überprüfen Sie im Ereignishandler von soundlevelchanged die Eigenschaft Sound Level des Absenders Audiostatus-itor , um die neue Audioebene zu bestimmen.In the SoundLevelChanged event handler, check the SoundLevel property of the AudioStateMonitor sender to determine the new sound level. In diesem Beispiel wird überprüft, ob die neue Audioebene ein vollständiges Volume ist, d. h., das System hat das Volume beendet oder das Volume duckt, oder ob die Audiostufe gesenkt wurde, aber nicht-Podcast-Inhalte wieder gibt.This example checks to see if the new sound level is full volume, meaning the system has stopped muting or ducking the volume, or if the sound level has been lowered but is playing non-podcast content. Wenn eine der beiden Optionen true ist und der Inhalt zuvor Programm gesteuert angehalten wurde, wird die Wiedergabe fortgesetzt.If either of these are true and the content was previously paused programmatically, playback is resumed. Wenn die neue Audioebene stumm geschaltet wird oder wenn es sich bei dem aktuellen Inhalt um einen Podcast handelt und die Audioebene niedrig ist, wird die Wiedergabe angehalten, und die Variable wird festgelegt, um zu verfolgen, ob die Pause Programm gesteuert initiiert wurde.If the new sound level is muted or if the current content is a podcast and the sound level is low, playback is paused, and the variable is set to track that the pause was initiated programatically.

private void AudioStateMonitor_SoundLevelChanged(Windows.Media.Audio.AudioStateMonitor sender, object args)
{
    if ((sender.SoundLevel == SoundLevel.Full) || (sender.SoundLevel == SoundLevel.Low && !isPodcast))
    {
        if (isPausedDueToAudioStateMonitor)
        {
            mediaPlayer.Play();
            isPausedDueToAudioStateMonitor = false;
        }
    }
    else if ((sender.SoundLevel == SoundLevel.Muted) ||
         (sender.SoundLevel == SoundLevel.Low && isPodcast))
    {
        if (mediaPlayer.PlaybackSession.PlaybackState == MediaPlaybackState.Playing)
        {
            mediaPlayer.Pause();
            isPausedDueToAudioStateMonitor = true;
        }
    }

}

Der Benutzer kann festlegen, dass die Wiedergabe angehalten oder fortgesetzt werden soll, auch wenn das Audiogerät vom System geduckt ist.The user may decide that they want to pause or continue playback, even if the audio is ducked by the system. In diesem Beispiel werden Ereignishandler für eine Wiedergabe-und eine Pause-Schaltfläche angezeigt.This example shows event handlers for a play and a pause button. Klicken Sie in der Schaltfläche Anhalten auf angehalten, wenn die Wiedergabe bereits Programm gesteuert angehalten wurde, und aktualisieren Sie die Variable, um anzugeben, dass der Inhalt vom Benutzer angehalten wurde.In the pause button click handler is paused, if playback had already been paused programmatically, then we update the variable to indicate that the user has paused the content. Im Click-Handler der Wiedergabe Taste setzen wir die Wiedergabe fort und löschen die nach Verfolgungs Variable.In the play button click handler, we resume playback and clear our tracking variable.

private void PauseButton_User_Click(object sender, RoutedEventArgs e)
{
    if (isPausedDueToAudioStateMonitor)
    {
        isPausedDueToAudioStateMonitor = false;
    }
    else
    {
        mediaPlayer.Pause();
    }
}

public void PlayButton_User_Click()
{
    isPausedDueToAudioStateMonitor = false;
    mediaPlayer.Play();
}