Wiedergeben von Audio- und Videoinhalten mit „MediaPlayer“
In diesem Artikel erfahren Sie, wie Sie Medien in Ihrer universellen Windows-App mit der MediaPlayer-Klasse wiedergeben. Mit Windows 10, Version 1607, wurden erhebliche Verbesserungen an den Medienwiedergabe-APIs vorgenommen, darunter ein vereinfachtes Einzelprozessdesign für Hintergrundaudio, die automatische Integration in die Steuerelemente für den Systemmedientransport (System Media Transport Controls, SMTC), die Möglichkeit, mehrere Media Player zu synchronisieren, die Möglichkeit zum Rendern von Videoframes auf einer Windows.UI.Composition-Oberfläche und eine einfache Schnittstelle zum Erstellen und Planen von Medienunterbrechungen in Ihren Inhalten. Um diese Verbesserungen zu nutzen, empfiehlt es sich, die MediaPlayer-Klasse anstelle von MediaElement für die Medienwiedergabe zu verwenden. Das einfache XAML-Steuerelement MediaPlayerElement wurde eingeführt, damit Sie Medieninhalte auf einer XAML-Seite rendern können. Viele der von MediaElement bereitgestellten Wiedergabesteuerelement- und Status-APIs sind jetzt über das neue MediaPlaybackSession-Objekt verfügbar. MediaElement funktioniert weiterhin, um abwärtskompatibilität zu unterstützen, aber dieser Klasse werden keine zusätzlichen Features hinzugefügt.
In diesem Artikel werden Sie durch die MediaPlayer-Features geführt, die von einer typischen Medienwiedergabe-App verwendet werden. Beachten Sie, dass MediaPlayer die MediaSource-Klasse als Container für alle Medienelemente verwendet. Mit dieser Klasse können Sie Medien aus vielen verschiedenen Quellen laden und wiedergeben, einschließlich lokaler Dateien, Speicherdatenströme und Netzwerkquellen, die alle dieselbe Schnittstelle verwenden. Es gibt auch Klassen auf höherer Ebene, die mit MediaSource arbeiten, z. B. MediaPlaybackItem und MediaPlaybackList, die erweiterte Features wie Wiedergabelisten und die Möglichkeit bieten, Medienquellen mit mehreren Audio-, Video- und Metadatentiteln zu verwalten. Weitere Informationen zu MediaSource und verwandten APIs finden Sie unter Medienelemente, Wiedergabelisten und Titel.
Hinweis
Windows 10 N- und Windows 10 KN-Editionen enthalten nicht die Medienfeatures, die für die Verwendung von MediaPlayer für die Wiedergabe erforderlich sind. Diese Features können manuell installiert werden. Weitere Informationen finden Sie unter Media Feature Pack für Windows 10 N- und Windows 10 KN-Editionen.
Wiedergeben einer Mediendatei mit MediaPlayer
Einfache Medienwiedergabe mit MediaPlayer ist sehr einfach zu implementieren. Erstellen Sie zunächst eine neue Instanz der MediaPlayer-Klasse . Ihre App kann mehrere MediaPlayer-Instanzen gleichzeitig aktiv haben. Legen Sie als Nächstes die Source-Eigenschaft des Players auf ein Objekt fest, das die IMediaPlaybackSource implementiert, z. B. eine MediaSource, ein MediaPlaybackItem oder eine MediaPlaybackList. In diesem Beispiel wird eine MediaSource aus einer Datei im lokalen Speicher der App erstellt, und dann wird ein MediaPlaybackItem aus der Quelle erstellt und dann der Source-Eigenschaft des Players zugewiesen.
Im Gegensatz zu MediaElement beginnt MediaPlayer nicht automatisch mit der Wiedergabe. Sie können mit der Wiedergabe beginnen, indem Sie die Wiedergabe aufrufen, indem Sie die Eigenschaft "Automatische Wiedergabe" auf "true" festlegen oder darauf warten, dass der Benutzer die Wiedergabe mit den integrierten Mediensteuerelementen initiiert.
mediaPlayer = new MediaPlayer();
mediaPlayer.Source = MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/example_video.mkv"));
mediaPlayer.Play();
Wenn Ihre App mit einem MediaPlayer fertig ist, sollten Sie die Close-Methode (projiziert auf Dispose in C#) aufrufen, um die vom Player verwendeten Ressourcen zu bereinigen.
mediaPlayer.Dispose();
Verwenden von MediaPlayerElement zum Rendern von Videos in XAML
Sie können Medien in einem MediaPlayer wiedergeben, ohne sie in XAML anzuzeigen, aber viele Medienwiedergabe-Apps möchten die Medien auf einer XAML-Seite rendern. Verwenden Sie dazu das einfache MediaPlayerElement-Steuerelement. Wie MediaElement können Sie mit MediaPlayerElement angeben, ob die integrierten Transportsteuerelemente angezeigt werden sollen.
<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.
_mediaPlayerElement.SetMediaPlayer(mediaPlayer);
Sie können auch die Wiedergabequelle für das MediaPlayerElement festlegen, und das Element erstellt automatisch eine neue MediaPlayer-Instanz, auf die Sie mithilfe der MediaPlayer-Eigenschaft zugreifen können.
Hinweis
Durch Festlegen von MediaPlayerElement-Eigenschaften werden die entsprechenden Eigenschaften für den zugrunde liegenden MediaPlayer festgelegt. Sie haben die Möglichkeit, den zugrunde liegenden MediaPlayer direkt anstelle von MediaPlayerElement-Eigenschaften zu verwenden. Beachten Sie, dass die direkte Verwendung von MediaPlayer , bei denen eine entsprechende MediaPlayerElement-Eigenschaft verwendet werden könnte, zu unerwartetem Verhalten führen kann. Dies liegt daran, dass das MediaPlayerElement nicht über alles informiert ist, was mit dem zugrunde liegenden MediaPlayer geschieht. Wenn Sie beispielsweise die Quelle direkt auf MediaPlayer festlegen, spiegelt die MediaPlayerElement Source-Eigenschaft die Änderung nicht wider. Aus diesem Grund müssen Sie in der Verwendung von MediaPlayerElement-Eigenschaften oder direkt mit dem zugrunde liegenden MediaPlayer konsistent sein.
_mediaPlayerElement.Source = MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/example_video.mkv"));
mediaPlayer = _mediaPlayerElement.MediaPlayer;
mediaPlayer.Play();
Hinweis
Wenn Sie den MediaPlaybackCommandManager des MediaPlayers deaktivieren, indem Sie "IsEnabled" auf "false" festlegen, wird die Verknüpfung zwischen dem MediaPlayer der vom MediaPlayerElement bereitgestellten TransportControls abgebrochen, sodass die integrierten Transportsteuerelemente die Wiedergabe des Players nicht mehr automatisch steuern. Stattdessen müssen Sie ihre eigenen Steuerelemente implementieren, um den MediaPlayer zu steuern.
Der MediaPlayer wird vom MediaPlayerElement getrennt, wenn das MediaPlayerElement zerstört wird oder ein neuer MediaPlayer mit SetMediaPlayer festgelegt wird. Wenn es getrennt wird, behandelt MediaPlayerElement den zugrunde liegenden MediaPlayer unterschiedlich, je nachdem, ob es von MediaPlayerElement erstellt oder mit SetMediaPlayer festgelegt wurde.
Wenn der MediaPlayer von MediaPlayerElement erstellt wurde, wird der MediaPlayer ordnungsgemäß geschlossen. Wenn der MediaPlayer für "MediaPlayerElement " mit SetMediaPlayer festgelegt wurde, müssen Sie sicherstellen, dass der MediaPlayer ordnungsgemäß geschlossen ist. Andernfalls kann dies zu schwerwiegenden Wiedergabefehlern in MediaPlayer führen. Der folgende Codeausschnitt zeigt, wie Sie den Code ordnungsgemäß trennen und schließen.
// Get a reference to the current media source.
IMediaPlaybackSource _mediaPlayerElement = _mediaPlayerElement.Source;
// Pause playback if able.
if (mediaPlayer.PlaybackSession.CanPause)
{
mediaPlayer.Pause();
}
// Disconnect the MediaPlayer from its source. This can be done by setting
// the MediaPlayerElement Source property to null or by directly setting the
// source to null on the underlying MediaPlayer.
_mediaPlayerElement.Source = null;
// Disconnect the MediaPlayer from MediaPlayerElement.
_mediaPlayerElement.SetMediaPlayer(null);
// Dispose of the MediaPlayer or Source if they're no longer needed.
if (source is MediaSource mediaSource)
{
mediaSource.Dispose();
}
mediaPlayer.Dispose();
Allgemeine MediaPlayer-Aufgaben
In diesem Abschnitt erfahren Sie, wie Sie einige der Features des MediaPlayers verwenden.
Festlegen der Audiokategorie
Legen Sie die AudioCategory-Eigenschaft eines MediaPlayers auf einen der Werte der MediaPlayerAudioCategory-Aufzählung fest, um dem System mitzuteilen, welche Art von Medien Sie wiedergeben. Spiele sollten ihre Musikstreams als GameMedia kategorisieren, damit Spielmusik automatisch stummgeschaltet wird, wenn eine andere Anwendung Musik im Hintergrund wiedergibt. Musik- oder Videoanwendungen sollten ihre Datenströme als Medien - oder Filmdatenströme kategorisieren, sodass sie Vorrang vor GameMedia-Streams haben.
mediaPlayer.AudioCategory = MediaPlayerAudioCategory.Media;
Ausgabe an einen bestimmten Audioendpunkt
Standardmäßig wird die Audioausgabe eines MediaPlayers an den Standardaudioendpunkt für das System weitergeleitet, Sie können jedoch einen bestimmten Audioendpunkt angeben, den der MediaPlayer für die Ausgabe verwenden soll. Im folgenden Beispiel gibt MediaDevice.GetAudioRenderSelector eine Zeichenfolge zurück, die die Audiowiedergabekategorie von Geräten eindeutig identifiziert. Als Nächstes wird die DeviceInformation-Methode FindAllAsync aufgerufen, um eine Liste aller verfügbaren Geräte des ausgewählten Typs abzurufen. Sie können programmgesteuert bestimmen, welches Gerät Sie verwenden möchten, oder fügen Sie die zurückgegebenen Geräte zu einem ComboBox-Steuerelement hinzu, damit der Benutzer ein Gerät auswählen kann.
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, das in der Tag-Eigenschaft des ComboBoxItem gespeichert wurde.
private void _audioDeviceComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
DeviceInformation selectedDevice = (DeviceInformation)((ComboBoxItem)_audioDeviceComboBox.SelectedItem).Tag;
if (selectedDevice != null)
{
mediaPlayer.AudioDevice = selectedDevice;
}
}
Wiedergabesitzung
Wie bereits in diesem Artikel beschrieben, wurden viele der Funktionen, die von der MediaElement-Klasse verfügbar gemacht werden, in die MediaPlaybackSession-Klasse verschoben. Dazu gehören Informationen zum Wiedergabestatus des Players, z. B. die aktuelle Wiedergabeposition, ob der Spieler angehalten oder wiedergegeben wird, und die aktuelle Wiedergabegeschwindigkeit. MediaPlaybackSession bietet außerdem mehrere Ereignisse, die Sie benachrichtigen können, wenn sich der Zustand ändert, einschließlich des aktuellen Puffers und des Downloadstatus der wiedergegebenen Inhalte sowie die natürliche Größe und das Seitenverhältnis der aktuell wiedergegebenen Videoinhalte.
Das folgende Beispiel zeigt, wie Sie einen Klickhandler für Schaltflächen implementieren, der im Inhalt 10 Sekunden vorwärts überspringt. Zuerst wird das MediaPlaybackSession-Objekt für den Player mit der PlaybackSession-Eigenschaft abgerufen. Als Nächstes wird die Position-Eigenschaft auf die aktuelle Wiedergabeposition plus 10 Sekunden festgelegt.
private void _skipForwardButton_Click(object sender, RoutedEventArgs e)
{
var session = mediaPlayer.PlaybackSession;
session.Position = session.Position + TimeSpan.FromSeconds(10);
}
Das nächste Beispiel veranschaulicht die Verwendung einer Umschaltfläche zum Umschalten zwischen normaler Wiedergabegeschwindigkeit und 2X-Geschwindigkeit, indem die PlaybackRate-Eigenschaft der Sitzung festgelegt wird.
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 im MediaPlayer in Schritten von 90 Grad präsentiert wird.
mediaPlayer.PlaybackSession.PlaybackRotation = MediaRotation.Clockwise90Degrees;
Erkennen erwarteter und unerwarteter Pufferung
Das im vorherigen Abschnitt beschriebene MediaPlaybackSession-Objekt bietet zwei Ereignisse zum Erkennen, wann die aktuell wiedergegebene Mediendatei beginnt und beendet puffert, BufferingStarted und BufferingEnded. Auf diese Weise können Sie die Benutzeroberfläche aktualisieren, um dem Benutzer anzuzeigen, dass die Pufferung erfolgt. 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. Unerwartete Pufferung kann auftreten, wenn die Netzwerkgeschwindigkeit beeinträchtigt wird oder wenn das Content Management System technische Probleme mit Inhalten bereitstellt. Ab RS3 können Sie mit dem BufferingStarted-Ereignis ermitteln, ob das Pufferereignis erwartet wird oder ob es unerwartet ist und die Wiedergabe unterbrochen wird. Sie können diese Informationen als Telemetriedaten für Ihren App- oder Medienübermittlungsdienst verwenden.
Registrieren Sie Handler für die Ereignisse BufferingStarted und BufferingEnded , um Pufferstatusbenachrichtigungen zu empfangen.
mediaPlayer.PlaybackSession.BufferingStarted += MediaPlaybackSession_BufferingStarted;
mediaPlayer.PlaybackSession.BufferingEnded += MediaPlaybackSession_BufferingEnded;
Wandeln Sie im BufferingStarted-Ereignishandler die Ereignisargumente, die in das Ereignis übergeben wurden, in ein MediaPlaybackSessionBufferingStartedEventArgs-Objekt um, und überprüfen Sie die IsPlaybackInterruption-Eigenschaft. Wenn dieser Wert "true" ist, ist die Pufferung, die das Ereignis ausgelöst hat, unerwartet und unterbricht die Wiedergabe. Andernfalls wird die anfängliche Pufferung erwartet.
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
}
Zusammendrücken und Zoomen von Videos
Mit MediaPlayer können Sie das Quellrechteck innerhalb von Videoinhalten angeben, die gerendert werden sollen. So können Sie das Video effektiv vergrößern. Das angegebene Rechteck ist relativ zu einem normalisierten Rechteck (0,0,1,1), wobei 0,0 die obere linke Hand des Frames ist und 1,1 die volle Breite und Höhe des Frames angibt. Wenn Sie beispielsweise das Zoomrechteck so festlegen möchten, dass der obere rechte Quadrant des Videos gerendert wird, würden Sie das Rechteck (.5,0,.5,.5) angeben. Es ist wichtig, dass Sie Ihre Werte überprüfen, um sicherzustellen, dass sich ihr Quellrechteck innerhalb des normalisierten Rechtecks (0,0,1,1) befindet. Wenn Sie versuchen, einen Wert außerhalb dieses Bereichs festzulegen, wird eine Ausnahme ausgelöst.
Zum Implementieren von Zusammendrücken und Zoomen mit Multitouchgesten müssen Sie zuerst angeben, welche Gesten unterstützt werden sollen. In diesem Beispiel werden Gesten zum Skalieren und Übersetzen angefordert. Das ManipulationDelta-Ereignis wird ausgelöst, wenn eine der abonnierten Gesten auftritt. Das DoubleTapped-Ereignis wird verwendet, um den Zoom auf den vollständigen Frame zurückzusetzen.
_mediaPlayerElement.ManipulationMode = ManipulationModes.Scale | ManipulationModes.TranslateX | ManipulationModes.TranslateY;
_mediaPlayerElement.ManipulationDelta += _mediaPlayerElement_ManipulationDelta;
_mediaPlayerElement.DoubleTapped += _mediaPlayerElement_DoubleTapped;
Deklarieren Sie als Nächstes ein Rect-Objekt , das das aktuelle Zoomquellenrechteck speichert.
Rect _sourceRect = new Rect(0, 0, 1, 1);
Der ManipulationDelta-Handler passt entweder die Skalierung oder die Übersetzung des Zoomrechtecks an. Wenn der Delta-Skalierungswert nicht 1 ist, bedeutet dies, dass der Benutzer eine Zusammendrückbewegung ausgeführt hat. Wenn der Wert größer als 1 ist, sollte das Quellrechteck verkleinert werden, um den Inhalt zu vergrößern. Wenn der Wert kleiner als 1 ist, sollte das Quellrechteck vergrößert werden, um zu verkleineren. Vor dem Festlegen der neuen Skalierungswerte wird das resultierende Rechteck überprüft, um sicherzustellen, dass es vollständig innerhalb der Grenzwerte (0,0,1,1) liegt.
Wenn der Skalierungswert 1 ist, wird die Übersetzungsgeste behandelt. Das Rechteck wird einfach durch die Anzahl der Pixel in der Geste übersetzt, dividiert durch die Breite und Höhe des Steuerelements. Auch hier wird das resultierende Rechteck überprüft, um sicherzustellen, dass es innerhalb der Grenzen (0,0,1,1) liegt.
Schließlich wird die NormalizedSourceRect der MediaPlaybackSession auf das neu angepasste Rechteck festgelegt, wobei der Bereich innerhalb des Videoframes angegeben wird, der gerendert werden soll.
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 auf (0,0,1,1) zurückgesetzt, damit der gesamte Videoframe gerendert wird.
private void _mediaPlayerElement_DoubleTapped(object sender, DoubleTappedRoutedEventArgs e)
{
_sourceRect = new Rect(0, 0, 1, 1);
mediaPlayer.PlaybackSession.NormalizedSourceRect = _sourceRect;
}
HINWEIS In diesem Abschnitt wird die Toucheingabe beschrieben. Touchpad sendet Zeigerereignisse und sendet keine Manipulationsereignisse.
Behandeln von richtlinienbasierten Wiedergabebeeinträchtigungen
Unter bestimmten Umständen kann das System die Wiedergabe eines Medienelements beeinträchtigen, z. B. die Auflösung (Einschränkung), basierend auf einer Richtlinie und nicht auf einem Leistungsproblem. Beispielsweise kann das Video vom System beeinträchtigt werden, wenn es mit einem nicht signierten Videotreiber wiedergegeben wird. Sie können MediaPlaybackSession.GetOutputDegradationPolicyState aufrufen, um zu ermitteln, ob und warum diese richtlinienbasierte Beeinträchtigung auftritt, und den Benutzer benachrichtigen oder den Grund für Telemetriezwecke aufzeichnen.
Das folgende Beispiel zeigt eine Implementierung eines Handlers für das MediaPlayer.MediaOpened-Ereignis , das ausgelöst wird, wenn der Player ein neues Medienelement öffnet. GetOutputDegradationPolicyState wird für den an den Handler übergebenen MediaPlayer aufgerufen. Der Wert von VideoConstrictionReason gibt den Richtliniengrund an, warum das Video eingeschränkt ist. Wenn der Wert nicht " None" lautet, protokolliert dieses Beispiel den Beeinträchtigungsgrund für Telemetriezwecke. Dieses Beispiel zeigt auch das Festlegen der Bitrate der adaptiveMediaSource, die derzeit auf die niedrigste Bandbreite wiedergegeben wird, um die Datennutzung zu sparen, da das Video eingeschränkt ist und trotzdem nicht mit hoher Auflösung angezeigt wird. Weitere Informationen zur Verwendung von AdaptiveMediaSource finden Sie unter Adaptives 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);
}
}
Verwenden von MediaPlayerSurface zum Rendern von Videos auf einer Windows.UI.Composition-Oberfläche
Ab Windows 10, Version 1607, können Sie MediaPlayer verwenden, um Video in einer ICompositionSurface zu rendern, wodurch der Player mit den APIs im Windows.UI.Composition-Namespace interoperieren kann. Mit dem Kompositionsframework können Sie mit Grafiken auf der visuellen Ebene zwischen XAML und den DirectX-Grafik-APIs auf niedriger Ebene arbeiten. Dies ermöglicht Szenarien wie das Rendern von Video in einem beliebigen XAML-Steuerelement. Weitere Informationen zur Verwendung der Kompositions-APIs finden Sie unter Visual Layer.
Das folgende Beispiel veranschaulicht, wie Videoplayerinhalte in einem Canvas-Steuerelement gerendert werden. Die media playerspezifischen Aufrufe in diesem Beispiel sind SetSurfaceSize und GetSurface. SetSurfaceSize teilt dem System die Größe des Puffers mit, die für das Rendern von Inhalten zugewiesen werden sollen. GetSurface verwendet einen Kompositor als Argument und ruft eine Instanz der MediaPlayerSurface-Klasse ab. Diese Klasse bietet Zugriff auf den MediaPlayer und Compositor , der zum Erstellen der Oberfläche verwendet wird, und macht die Oberfläche selbst über die CompositionSurface-Eigenschaft verfügbar.
Im restlichen Code in diesem Beispiel wird ein SpriteVisual-Element erstellt, auf das das Video gerendert wird, und legt die Größe auf die Größe des Canvaselements fest, das das visuelle Element anzeigt. Als Nächstes wird ein CompositionBrush aus dem MediaPlayerSurface erstellt und der Brush-Eigenschaft des visuellen Elements zugewiesen. Als Nächstes wird ein ContainerVisual erstellt, und das SpriteVisual wird oben in der visuellen Struktur eingefügt. Schließlich wird SetElementChildVisual aufgerufen, um dem Canvas-Element das containervisual zuzuweisen.
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);
Verwenden Sie MediaTimelineController, um Inhalte über mehrere Player hinweg zu synchronisieren.
Wie bereits in diesem Artikel beschrieben, kann Ihre App mehrere MediaPlayer-Objekte gleichzeitig aktiv haben. Standardmäßig wird jeder von Ihnen erstellte MediaPlayer unabhängig voneinander betrieben. Für einige Szenarien, z. B. die Synchronisierung eines Kommentartitels mit einem Video, können Sie den Spielerzustand, die Wiedergabeposition und die Wiedergabegeschwindigkeit mehrerer Spieler synchronisieren. Ab Windows 10, Version 1607, können Sie dieses Verhalten mithilfe der MediaTimelineController-Klasse implementieren.
Implementieren von Wiedergabesteuerelementen
Das folgende Beispiel zeigt, wie Sie einen MediaTimelineController verwenden, um zwei Instanzen von MediaPlayer zu steuern. Zunächst wird jede Instanz des MediaPlayers instanziiert, und die Quelle wird auf eine Mediendatei festgelegt. Als Nächstes wird ein neuer MediaTimelineController erstellt. Für jeden MediaPlayer wird der mit jedem Player verknüpfte MediaPlaybackCommandManager deaktiviert, indem die IsEnabled-Eigenschaft auf "false" festgelegt wird. Anschließend wird die TimelineController-Eigenschaft auf das Zeitachsencontrollerobjekt festgelegt.
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: MediaPlaybackCommandManager bietet automatische Integration zwischen MediaPlayer und system Media Transport Controls (SMTC), diese automatische Integration kann jedoch nicht mit Media Playern verwendet werden, die mit einem MediaTimelineController gesteuert werden. Daher müssen Sie den Befehls-Manager für den Media Player deaktivieren, bevor Sie den Zeitachsencontroller des Players festlegen. Andernfalls wird eine Ausnahme ausgelöst, die mit der folgenden Meldung ausgelöst wird: "Das Anfügen des Medienzeitachsencontrollers wird aufgrund des aktuellen Zustands des Objekts blockiert." Weitere Informationen zur Media Player-Integration in smTC finden Sie unter Integration in die Steuerelemente für den Systemmedientransport. Wenn Sie einen MediaTimelineController verwenden, können Sie den SMTC weiterhin manuell steuern. Weitere Informationen finden Sie unter Manuelle Steuerung der Steuerelemente für den Systemmedientransport.
Nachdem Sie einen MediaTimelineController an einen oder mehrere Media Player angefügt haben, können Sie den Wiedergabezustand mithilfe der vom Controller verfügbar gemachten Methoden steuern. Im folgenden Beispiel wird "Start" aufgerufen, um mit der Wiedergabe aller zugehörigen Media Player am Anfang des Mediums zu beginnen.
private void PlayButton_Click(object sender, RoutedEventArgs e)
{
_mediaTimelineController.Start();
}
In diesem Beispiel wird das Anhalten und Fortsetzen aller angefügten Media Player veranschaulicht.
private void PauseButton_Click(object sender, RoutedEventArgs e)
{
if(_mediaTimelineController.State == MediaTimelineControllerState.Running)
{
_mediaTimelineController.Pause();
_pauseButton.Content = "Resume";
}
else
{
_mediaTimelineController.Resume();
_pauseButton.Content = "Pause";
}
}
Wenn Sie alle verbundenen MediaPlayer schnell weiterleiten möchten, legen Sie die Wiedergabegeschwindigkeit auf einen Wert fest, der größer als 1 ist.
private void FastForwardButton_Click(object sender, RoutedEventArgs e)
{
_mediaTimelineController.ClockRate = 2.0;
}
Das nächste Beispiel zeigt, wie Sie ein Schieberegler-Steuerelement verwenden, um die aktuelle Wiedergabeposition des Zeitachsencontrollers relativ zur Dauer des Inhalts eines der verbundenen Media Player anzuzeigen. Zunächst wird eine neue MediaSource erstellt und ein Handler für openOperationCompleted der Medienquelle registriert.
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 wird als Möglichkeit verwendet, die Dauer des Medienquelleninhalts zu ermitteln. Nachdem die Dauer bestimmt wurde, wird der Maximalwert des Schieberegler-Steuerelements auf die Gesamtanzahl der Sekunden des Medienelements festgelegt. Der Wert wird innerhalb eines Aufrufs von RunAsync festgelegt, um sicherzustellen, dass er im UI-Thread ausgeführt wird.
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. Dies wird in regelmäßigen Abständen vom System aufgerufen, etwa 4 Mal pro Sekunde.
_mediaTimelineController.PositionChanged += _mediaTimelineController_PositionChanged;
Im Handler für PositionChanged wird der Schiebereglerwert aktualisiert, um die aktuelle Position des Zeitachsencontrollers widerzuspiegeln.
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;
});
}
}
Verschieben der Wiedergabeposition von der Zeitachsenposition
In einigen Fällen möchten Sie möglicherweise, dass die Wiedergabeposition eines oder mehrerer Media Player, die einem Zeitachsencontroller zugeordnet sind, von den anderen Spielern versetzt werden soll. Sie können dies tun, indem Sie die TimelineControllerPositionOffset-Eigenschaft des MediaPlayer-Objekts festlegen, das Sie offseten möchten. Im folgenden Beispiel werden die Dauer des Inhalts von zwei Media Playern verwendet, um die Mindest- und Höchstwerte von zwei Schiebereglersteuerelementen auf plus und minus die Länge des Elements festzulegen.
_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 für jeden Schieberegler wird der TimelineControllerPositionOffset für jeden Spieler auf den entsprechenden Wert festgelegt.
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, dass der Offsetwert eines Players einer negativen Wiedergabeposition zugeordnet wird, der Clip angehalten bleibt, bis der Offset null erreicht und die Wiedergabe beginnt. Wenn der Offsetwert einer Wiedergabeposition zugeordnet ist, die größer als die Dauer des Medienelements ist, wird der endgültige Frame genauso angezeigt, wie es der Fall ist, wenn ein einzelner Media Player das Ende des Inhalts erreicht hat.
Wiedergeben von sphärischen Videos mit MediaPlayer
Ab Windows 10, Version 1703, unterstützt MediaPlayer die äquirectangulare Projektion für die sphärische Videowiedergabe. Sphärische Videoinhalte unterscheiden sich nicht von normalen Flachvideos, in denen MediaPlayer das Video rendert, solange die Videocodierung unterstützt wird. Bei sphärischen Videos, die ein Metadatentag enthalten, das angibt, dass das Video die äquirectangulare Projektion verwendet, kann MediaPlayer das Video mit einer angegebenen Ansichts- und Ansichtsausrichtung rendern. Dies ermöglicht Szenarien wie die Wiedergabe von Virtual Reality-Videos mit einer kopfmontierten Anzeige oder einfach das Verschieben innerhalb von kugelförmigen Videoinhalten mithilfe der Maus- oder Tastatureingabe.
Um sphärische Videos wiederzugeben, führen Sie die Schritte zum Wiedergeben von Videoinhalten aus, die zuvor in diesem Artikel beschrieben wurden. Der einzige zusätzliche Schritt besteht darin, einen Handler für das MediaPlayer.MediaOpened-Ereignis zu registrieren. Dieses Ereignis bietet Ihnen die Möglichkeit, die Parameter der sphärischen Videowiedergabe zu aktivieren und zu steuern.
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 zunächst im MediaOpened-Handler das Frameformat des neu geöffneten Medienelements, indem Sie die PlaybackSession.SphericalVideoProjection.FrameFormat-Eigenschaft überprüfen. Wenn dieser Wert SphericaVideoFrameFormat.Equirectangular ist, kann das System den Videoinhalt automatisch projizieren. Legen Sie zunächst die PlaybackSession.SphericalVideoProjection.IsEnabled-Eigenschaft auf "true" fest. Sie können auch Eigenschaften anpassen, z. B. die Ansichtsausrichtung und das Ansichtsfeld, das der Media Player zum Projizieren des Videoinhalts verwendet. In diesem Beispiel wird das Ansichtsfeld auf einen breiten Wert von 120 Grad festgelegt, indem die HorizontalFieldOfViewInDegrees-Eigenschaft festgelegt wird.
Wenn der Videoinhalt sphärische Inhalte ist, sich aber in einem anderen Format als equirectangular befindet, können Sie ihren eigenen Projektionsalgorithmus mithilfe des Frameservermodus des Media Players implementieren, um einzelne Frames zu empfangen und zu verarbeiten.
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
}
}
Im folgenden Beispielcode wird veranschaulicht, wie Sie die Ausrichtung der sphärischen Videoansicht mithilfe der NACH-LINKS- und NACH-RECHTS-TASTE anpassen.
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, sollten Sie Wiedergabeelemente identifizieren, die sphärische Videos in der Benutzeroberfläche enthalten. Medienwiedergabelisten werden im Artikel, Medienelemente, Wiedergabelisten und Titel ausführlich erläutert. Das folgende Beispiel zeigt das Erstellen einer neuen Wiedergabeliste, das Hinzufügen eines Elements und das Registrieren eines Handlers für das MediaPlaybackItem.VideoTracksChanged-Ereignis , das auftritt, wenn die Videospuren für ein Medienelement aufgelöst werden.
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 VideoTracksChanged-Ereignishandler die Codierungseigenschaften für alle hinzugefügten Videotitel ab, indem Sie VideoTrack.GetEncodingProperties aufrufen. Wenn die SphericalVideoFrameFormat-Eigenschaft der Codierungseigenschaften ein anderer Wert als SphericaVideoFrameFormat.None ist, enthält der Videotitel sphärische Videos, und Sie können die Benutzeroberfläche bei Auswahl entsprechend aktualisieren.
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 MediaPlayer im Frameservermodus
Ab Windows 10, Version 1703, können Sie MediaPlayer im Frameservermodus verwenden. In diesem Modus rendert der MediaPlayer keine Frames automatisch in einem zugeordneten MediaPlayerElement. Stattdessen kopiert Ihre App den aktuellen Frame vom MediaPlayer in ein Objekt, das IDirect3DSurface implementiert. Das primäre Szenario dieses Features ermöglicht die Verwendung von Pixelshadern zum Verarbeiten von Videoframes, die vom MediaPlayer bereitgestellt werden. Ihre App ist für die Anzeige der einzelnen Frames nach der Verarbeitung verantwortlich, z. B. durch Anzeigen des Frames in einem XAML-Bildsteuerelement.
Im folgenden Beispiel wird ein neuer MediaPlayer initialisiert und Videoinhalte geladen. Als Nächstes wird ein Handler für VideoFrameAvailable registriert. Der Frameservermodus wird aktiviert, indem die IsVideoFrameServerEnabled-Eigenschaft des MediaPlayer-Objekts auf "true" festgelegt wird. Schließlich wird die Medienwiedergabe mit einem Aufruf der Wiedergabe gestartet.
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-Bildsteuerelement anzuzeigen.
Wenn der VideoFrameAvailable-Handler aufgerufen wird, wird die CopyFrameToVideoSurface-Methode verwendet, um den Inhalt des Frames in eine IDirect3DSurface zu kopieren. Sie können auch CopyFrameToStereoscopicVideoSurfaces verwenden, um 3D-Inhalte in zwei Oberflächen zu kopieren, um den linken Und rechten Augeninhalt separat zu verarbeiten. Zum Abrufen eines Objekts, das IDirect3DSurface implementiert, wird in diesem Beispiel eine SoftwareBitmap erstellt und dann dieses Objekt verwendet, um eine Win2D CanvasBitmap zu erstellen, die die erforderliche Schnittstelle implementiert. Eine CanvasImageSource ist ein Win2D-Objekt, das als Quelle für ein Image-Steuerelement verwendet werden kann, sodass eine neue erstellt und als Quelle für das Bild festgelegt wird, in dem der Inhalt angezeigt wird. Als Nächstes wird eine CanvasDrawingSession erstellt. Dies wird von Win2D verwendet, um den Weichzeichnereffekt zu rendern.
Nachdem alle erforderlichen Objekte instanziiert wurden, wird CopyFrameToVideoSurface aufgerufen, wodurch der aktuelle Frame aus dem MediaPlayer in die CanvasBitmap kopiert wird. Als Nächstes wird ein Win2D GaussianBlurEffect erstellt, wobei die CanvasBitmap als Quelle des Vorgangs festgelegt ist. Schließlich wird CanvasDrawingSession.DrawImage aufgerufen, um das Quellbild mit dem angewendeten Weichzeichnereffekt in die CanvasImageSource zu zeichnen, die mit dem Bildsteuerelement verknüpft wurde, was dazu führt, dass es in der Benutzeroberfläche gezeichnet wird.
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. Um den oben gezeigten Beispielcode auszuprobieren, müssen Sie dem Projekt das Win2D NuGet-Paket mit den folgenden Anweisungen hinzufügen.
So fügen Sie das Win2D NuGet-Paket zu Ihrem Effektprojekt hinzu
- Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, und wählen Sie NuGet-Pakete verwalten aus.
- Wählen Sie oben im Fenster die Registerkarte "Durchsuchen " aus.
- Geben Sie im Suchfeld Win2D ein.
- Wählen Sie "Win2D.uwp" und dann im rechten Bereich " Installieren" aus.
- Im Dialogfeld "Änderungen überprüfen" wird das zu installierende Paket angezeigt. Klicken Sie auf OK.
- Akzeptieren Sie die Paketlizenz.
Erkennen und Reagieren auf Audiopegeländerungen durch das System
Ab Windows 10, Version 1803, kann Ihre App erkennen, wann das System den Audiopegel eines aktuell wiedergegebenen MediaPlayers verringert oder stummschaltet. Das System kann z. B. die Audiowiedergabe verringern oder "enten", wenn ein Alarm klingelt. Das System schaltet Ihre App stumm, wenn sie in den Hintergrund wechselt, wenn Ihre App die backgroundMediaPlayback-Funktion nicht im App-Manifest deklariert hat. Mit der Klasse AudioStateMonitor können Sie sich registrieren, um ein Ereignis zu erhalten, wenn das System die Lautstärke eines Audiostroms ändert. Greifen Sie auf die AudioStateMonitor-Eigenschaft eines MediaPlayers zu, und registrieren Sie einen Handler für das SoundLevelChanged-Ereignis, um benachrichtigt zu werden, wenn die Audioebene für diesen MediaPlayer vom System geändert wird.
mediaPlayer.AudioStateMonitor.SoundLevelChanged += AudioStateMonitor_SoundLevelChanged;
Bei der Behandlung des SoundLevelChanged-Ereignisses können Sie je nach Art des wiedergegebenen Inhalts unterschiedliche Aktionen ausführen. Wenn Sie derzeit Musik wiedergeben, können Sie die Musik weiterhin wiedergeben lassen, während die Lautstärke entent wird. Wenn Sie jedoch einen Podcast wiedergeben, möchten Sie wahrscheinlich die Wiedergabe anhalten, während die Audiowiedergabe entent wird, damit der Benutzer keinen Inhalt verpasst.
In diesem Beispiel wird eine Variable deklariert, um nachzuverfolgen, ob der aktuell wiedergegebene Inhalt ein Podcast ist, es wird davon ausgegangen, dass Sie diese auf den entsprechenden Wert festlegen, wenn Sie den Inhalt für den MediaPlayer auswählen. Außerdem erstellen wir eine Klassenvariable, um nachzuverfolgen, wann die Wiedergabe programmgesteuert angehalten wird, wenn sich die Audioebene ändert.
bool isPodcast;
bool isPausedDueToAudioStateMonitor;
Überprüfen Sie im SoundLevelChanged-Ereignishandler die SoundLevel-Eigenschaft des Absenders "AudioStateMonitor", um die neue Soundebene zu ermitteln. In diesem Beispiel wird überprüft, ob die neue Lautstärke voll ist, d. h., das System hat das Stummschalten oder Enten der Lautstärke beendet, oder wenn der Soundpegel verringert wurde, aber Nicht-Podcast-Inhalte wiedergegeben wird. Wenn eines dieser Eigenschaften zutrifft und der Inhalt zuvor programmgesteuert angehalten wurde, wird die Wiedergabe fortgesetzt. Wenn die neue Soundebene stummgeschaltet ist oder der aktuelle Inhalt ein Podcast ist und die Soundebene niedrig ist, wird die Wiedergabe angehalten, und die Variable wird so festgelegt, dass die Pause programmgesteuert initiiert wurde.
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 entscheiden, dass er die Wiedergabe anhalten oder fortsetzen möchte, auch wenn die Audiodaten vom System entent werden. Dieses Beispiel zeigt Ereignishandler für eine Wiedergabe und eine Pausenschaltfläche. Wenn die Wiedergabe programmgesteuert angehalten wurde, wird der Klickhandler für die Pausenschaltfläche angehalten, und die Variable wird aktualisiert, um anzugeben, dass der Benutzer den Inhalt angehalten hat. Im Klickhandler der Wiedergabeschaltfläche setzen wir die Wiedergabe fort und löschen unsere 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();
}
Zugehörige Themen
- Medienwiedergabe
- Medienelemente, Wiedergabelisten und Titel
- Integration in die Steuerelemente für den Systemmedientransport
- Erstellen, Planen und Verwalten von Medienunterbrechungen
- Wiedergeben von Medien im Hintergrund