Freigeben über


Medienelemente, Wiedergabelisten und Titel

In diesem Artikel wird gezeigt, wie Sie die MediaSource-Klasse verwenden, die eine gemeinsame Möglichkeit zum Verweisen und Wiedergeben von Medien aus verschiedenen Quellen wie lokalen oder Remotedateien bietet und ein gemeinsames Modell für den Zugriff auf Mediendaten verfügbar macht, unabhängig vom zugrunde liegenden Medienformat. Die MediaPlaybackItem-Klasse erweitert die Funktionalität von MediaSource, sodass Sie mehrere Audio-, Video- und Metadatentitel in einem Medienelement verwalten und auswählen können. Mit MediaPlaybackList können Sie Wiedergabelisten aus einem oder mehreren Medienwiedergabeelementen erstellen.

Erstellen und Abspielen einer MediaSource

Erstellen Sie eine neue Instanz von MediaSource , indem Sie eine der Factorymethoden aufrufen, die von der Klasse verfügbar gemacht werden:

Nachdem Sie eine MediaSource erstellt haben, können Sie sie mit einem MediaPlayer wiedergeben, indem Sie die Source-Eigenschaft festlegen. Sie können einem MediaPlayerElement einen MediaPlayer zuweisen, indem Sie SetMediaPlayer aufrufen, um den Media Player-Inhalt auf einer XAML-Seite zu rendern. Dies ist die gegenüber MediaElement bevorzugte Methode. Weitere Informationen zur Verwendung von MediaPlayer finden Sie unter Wiedergeben von Audio und Video mit MediaPlayer.

Das folgende Beispiel zeigt, wie eine vom Benutzer ausgewählte Mediendatei in einem MediaPlayer mithilfe von MediaSource wiedergegeben wird. Verwenden Sie einen FileOpenPicker, um dem Benutzer die Auswahl einer Mediendatei zur Wiedergabe zu ermöglichen. Erstellen Sie eine Instanz von StorageFile aus dem Pfad, der von der PickSingleFileAsync-Methode des Pickers zurückgegeben wird, und initialisieren Sie ein neues MediaSource-Objekt durch Aufrufen von MediaSource.CreateFromStorageFile. Legen Sie schließlich die Medienquelle als Wiedergabequelle für den MediaPlayer fest, indem Sie die SetPlaybackSource-Eigenschaft festlegen.

<MediaPlayerElement x:Name="mediaPlayerElement"/>
MediaSource? mediaSource;
MediaPlayer? mediaPlayer;
//Create a new picker
var filePicker = new Microsoft.Windows.Storage.Pickers.FileOpenPicker(this.AppWindow.Id)
{
    SuggestedStartLocation = PickerLocationId.VideosLibrary,
    FileTypeFilter = { ".wmv", ".mp4", ".mkv" },
};

//Retrieve file from picker
var result = await filePicker.PickSingleFileAsync();

if (result is not null)
{
    var storageFile = await Windows.Storage.StorageFile.GetFileFromPathAsync(result.Path);
    mediaSource = MediaSource.CreateFromStorageFile(storageFile);
    mediaPlayer = new MediaPlayer();
    mediaPlayer.Source = mediaSource;
    mediaPlayerElement.SetMediaPlayer(mediaPlayer);
}

Standardmäßig beginnt der MediaPlayer nicht automatisch mit der Wiedergabe, wenn die Medienquelle festgelegt ist. Sie können mit der Wiedergabe manuell beginnen, indem Sie "Wiedergabe" aufrufen.

mediaPlayer.Play();

Sie können auch die Eigenschaft " Automatische Wiedergabe " des MediaPlayers auf "true" festlegen, um dem Player mitzuteilen, dass er mit der Wiedergabe beginnt, sobald die Medienquelle festgelegt ist.

mediaPlayer.AutoPlay = true;

Behandeln mehrerer Audio-, Video- und Metadatentitel mit MediaPlaybackItem

Die Verwendung einer MediaSource für die Wiedergabe ist praktisch, da sie eine gängige Möglichkeit zum Wiedergeben von Medien aus verschiedenen Quellen bietet, aber auf ein erweitertes Verhalten kann durch Erstellen eines MediaPlaybackItem aus mediaSource zugegriffen werden. Dies umfasst die Möglichkeit, auf mehrere Audio-, Video- und Datenspuren für ein Medienelement zuzugreifen und diese zu verwalten.

Erstellen Sie ein MediaPlaybackItem-Objekt , indem Sie den Konstruktor aufrufen und ein initialisiertes MediaSource-Objekt übergeben. Wenn Ihre App mehrere Audio-, Video- oder Datenspuren in einem Medienwiedergabeelement unterstützt, registrieren Sie Ereignishandler für die Ereignisse AudioTracksChanged, VideoTracksChanged oder TimedMetadataTracksChanged . Legen Sie schließlich die Wiedergabequelle des MediaElement - oder MediaPlayers auf Ihr MediaPlaybackItem-Element fest.

MediaPlaybackItem mediaPlaybackItem;
mediaSource = MediaSource.CreateFromStorageFile(storageFile);
mediaPlaybackItem = new MediaPlaybackItem(mediaSource);

mediaPlaybackItem.AudioTracksChanged += MediaPlaybackItem_AudioTracksChanged;
mediaPlaybackItem.VideoTracksChanged += MediaPlaybackItem_VideoTracksChanged;
mediaPlaybackItem.TimedMetadataTracksChanged += MediaPlaybackItem_TimedMetadataTracksChanged;

mediaPlayer = new MediaPlayer();
mediaPlayer.Source = mediaPlaybackItem;
mediaPlayerElement.SetMediaPlayer(mediaPlayer);

Hinweis

Eine MediaSource kann nur einem einzelnen MediaPlaybackItem zugeordnet werden. Nach dem Erstellen eines MediaPlaybackItem aus einer Quelle führt der Versuch, ein anderes Wiedergabeelement aus derselben Quelle zu erstellen, zu einem Fehler. Außerdem können Sie nach dem Erstellen eines MediaPlaybackItem aus einer Medienquelle das MediaSource-Objekt nicht direkt als Quelle für einen MediaPlayer festlegen, sondern stattdessen das MediaPlaybackItem verwenden.

Das VideoTracksChanged-Ereignis wird ausgelöst, nachdem ein MediaPlaybackItem mit mehreren Videotiteln als Wiedergabequelle zugewiesen wurde und erneut ausgelöst werden kann, wenn sich die Liste der Videotitel für das Element ändert. Der Handler für dieses Ereignis bietet Ihnen die Möglichkeit, die Benutzeroberfläche zu aktualisieren, damit der Benutzer zwischen den verfügbaren Titeln wechseln kann. In diesem Beispiel wird ein ComboBox-Steuerelement verwendet, um die verfügbaren Videotitel anzuzeigen.

<ComboBox x:Name="videoTracksComboBox" SelectionChanged="VideoTracksComboBox_SelectionChanged"/>

Durchlaufen Sie im VideoTracksChanged-Handler alle Titel in der VideoTracks-Liste des Wiedergabeelements . Für jeden Titel wird ein neues ComboBoxItem-Objekt erstellt. Wenn der Titel noch nicht über eine Bezeichnung verfügt, wird eine Bezeichnung aus dem Titelindex generiert. Die Tag-Eigenschaft des ComboBox-Elements wird auf den Track-Index festgelegt, damit es später identifiziert werden kann. Schließlich wird das Element dem Kombinationsfeld hinzugefügt. Beachten Sie, dass diese Vorgänge innerhalb eines DispatcherQueue.TryEnqueue-Aufrufs ausgeführt werden, da alle UI-Änderungen im UI-Thread vorgenommen werden müssen und dieses Ereignis in einem anderen Thread ausgelöst wird.

private void MediaPlaybackItem_VideoTracksChanged(MediaPlaybackItem sender, IVectorChangedEventArgs args)
{
    DispatcherQueue.TryEnqueue(() =>
    {
        videoTracksComboBox.Items.Clear();
        for (int index = 0; index < sender.VideoTracks.Count; index++)
        {
            var videoTrack = sender.VideoTracks[index];
            ComboBoxItem item = new ComboBoxItem();
            item.Content = String.IsNullOrEmpty(videoTrack.Label) ? $"Track {index}" : videoTrack.Label;
            item.Tag = index;
            videoTracksComboBox.Items.Add(item);
        }
    });
}

Im SelectionChanged-Handler für das Kombinationsfeld wird der Titelindex aus der Tag-Eigenschaft des ausgewählten Elements abgerufen. Das Festlegen der SelectedIndex-Eigenschaft der VideoTracks-Liste des Medienwiedergabeelements bewirkt, dass mediaElement oder MediaPlayer die aktive Videospur in den angegebenen Index wechselt.

private void VideoTracksComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    int trackIndex = (int)((ComboBoxItem)((ComboBox)sender).SelectedItem).Tag;
    mediaPlaybackItem.VideoTracks.SelectedIndex = trackIndex;
}

Das Verwalten von Medienelementen mit mehreren Audiospuren funktioniert genauso wie bei Videospuren. Behandeln Sie AudioTracksChanged, um Ihre Benutzeroberfläche mit den Audiospuren zu aktualisieren, die in der AudioTracks-Liste des Wiedergabeelements enthalten sind. Wenn der Benutzer einen Audiotitel auswählt, legen Sie die SelectedIndex-Eigenschaft der AudioTracks-Liste so fest, dass mediaElement oder MediaPlayer die aktive Audiospur in den angegebenen Index wechselt.

<ComboBox x:Name="audioTracksComboBox" SelectionChanged="AudioTracksComboBox_SelectionChanged"/>
private void MediaPlaybackItem_AudioTracksChanged(MediaPlaybackItem sender, IVectorChangedEventArgs args)
{
    DispatcherQueue.TryEnqueue(() =>
    {
        audioTracksComboBox.Items.Clear();
        for (int index = 0; index < sender.AudioTracks.Count; index++)
        {
            var audioTrack = sender.AudioTracks[index];
            ComboBoxItem item = new ComboBoxItem();
            item.Content = String.IsNullOrEmpty(audioTrack.Label) ? $"Track {index}" : audioTrack.Label;
            item.Tag = index;
            audioTracksComboBox.Items.Add(item);
        }
    });
}
private void AudioTracksComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    int trackIndex = (int)((ComboBoxItem)((ComboBox)sender).SelectedItem).Tag;
    mediaPlaybackItem.AudioTracks.SelectedIndex = trackIndex;
}

Zusätzlich zu Audio und Video kann ein MediaPlaybackItem-Objekt null oder mehr TimedMetadataTrack-Objekte enthalten. Ein zeitgesteuerter Metadatentrack kann Untertitel- oder Beschriftungstext enthalten oder benutzerdefinierte Daten, die proprietär für Ihre App sind. Ein zeitbestimmter Metadatentitel enthält eine Liste von Hinweisen, die durch Objekte dargestellt werden, die von IMediaCue erben, z. B. ein DataCue oder ein TimedTextCue. Jeder Hinweis hat eine Startzeit und eine Dauer, die bestimmt, wann der Marker aktiviert wird und wie lange.

Ähnlich wie Audiospuren und Videospuren können die Zeitmetadatenspuren für ein Medienelement durch Behandeln des TimedMetadataTracksChanged-Ereignisses eines MediaPlaybackItem ermittelt werden. Bei zeitlich begrenzten Metadatenspuren möchte der Benutzer jedoch möglicherweise mehr als eine Metadatenspur zur gleichen Zeit aktivieren. Je nach App-Szenario möchten Sie metadatenspuren möglicherweise auch automatisch aktivieren oder deaktivieren, ohne dass der Benutzer eingreifen muss. Zu Veranschaulichungszwecken fügt dieses Beispiel ein ToggleButton für jede Metadatenspur in einem Medienelement hinzu, damit der Benutzer den Titel aktivieren und deaktivieren kann. Die Tag-Eigenschaft jeder Schaltfläche wird auf den Index der zugeordneten Metadatenspur festgelegt, sodass sie beim Umschalten der Schaltfläche identifiziert werden kann.

<StackPanel x:Name="metadataButtonPanel" Orientation="Horizontal"/>
private void MediaPlaybackItem_TimedMetadataTracksChanged(MediaPlaybackItem sender, IVectorChangedEventArgs args)
{
    DispatcherQueue.TryEnqueue(() =>
    {
        for (int index = 0; index < sender.TimedMetadataTracks.Count; index++)
        {
            var timedMetadataTrack = sender.TimedMetadataTracks[index];

            ToggleButton toggle = new ToggleButton()
            {
                Content = String.IsNullOrEmpty(timedMetadataTrack.Label) ? $"Track {index}" : timedMetadataTrack.Label,
                Tag = (uint)index
            };
            toggle.Checked += Toggle_Checked;
            toggle.Unchecked += Toggle_Unchecked;

            metadataButtonPanel.Children.Add(toggle);
        }
    });
}

Da mehrere Metadatentitel gleichzeitig aktiv sein können, legen Sie nicht einfach den aktiven Index für die Metadatentitelliste fest. Rufen Sie stattdessen SetPresentationMode auf, übergeben Sie den Index des Titels, den Sie umschalten möchten, und geben Sie dann einen Wert aus der TimedMetadataTrackPresentationMode-Aufzählung an. Der von Ihnen ausgewählte Präsentationsmodus hängt von der Implementierung Ihrer App ab. In diesem Beispiel wird der Metadaten-Track auf PlatformPresented festgelegt, wenn er aktiviert ist. Bei textbasierten Titeln bedeutet dies, dass das System automatisch die Texthinweise im Titel anzeigt. Wenn die Umschaltfläche deaktiviert wird, wird der Präsentationsmodus auf "Deaktiviert" festgelegt, was bedeutet, dass kein Text angezeigt wird und keine Hinweisereignisse ausgelöst werden. Hinweisereignisse werden weiter unten in diesem Artikel erläutert.

private void Toggle_Checked(object sender, RoutedEventArgs e) =>
    mediaPlaybackItem.TimedMetadataTracks.SetPresentationMode((uint)((ToggleButton)sender).Tag,
        TimedMetadataTrackPresentationMode.PlatformPresented);
private void Toggle_Unchecked(object sender, RoutedEventArgs e) =>
    mediaPlaybackItem.TimedMetadataTracks.SetPresentationMode((uint)((ToggleButton)sender).Tag,
        TimedMetadataTrackPresentationMode.Disabled);

Während Sie die Metadaten-Spuren verarbeiten, können Sie auf den Satz von Markern innerhalb der Spur zugreifen, indem Sie auf die Cues oder ActiveCues Eigenschaften zugreifen. Sie können dies tun, um die Benutzeroberfläche so zu aktualisieren, dass die Speicherorte für ein Medienobjekt angezeigt werden.

Umgang mit nicht unterstützten Codecs und unbekannten Fehlern beim Öffnen von Medienelementen

WHen ein Medienelement wird geladen, Sie können überprüfen, ob der zum Wiedergeben eines Medienelements erforderliche Codec auf dem Gerät unterstützt oder teilweise unterstützt wird, auf dem Ihre App ausgeführt wird. Überprüfen Sie im Ereignishandler für die MediaPlaybackItem-geänderten Titelereignisse, wie zum Beispiel AudioTracksChanged, zuerst, ob die Änderung der Spur ein Einfügen eines neuen Titels ist. Wenn ja, können Sie mithilfe des Indexes, der im Parameter IVectorChangedEventArgs.Index übergeben wird, mit der entsprechenden Track-Sammlung des MediaPlaybackItem-Parameters, z. B. der AudioTracks-Sammlung, einen Verweis auf den eingefügten Titel abrufen.

Nachdem Sie über einen Verweis auf den eingefügten Titel verfügen, überprüfen Sie den DecoderStatus der SupportInfo-Eigenschaft des Titels. Wenn der Wert "FullySupported" ist, ist der entsprechende Codec zum Wiedergeben des Titels auf dem Gerät vorhanden. Wenn der Wert herabgestuft ist, kann der Titel vom System wiedergegeben werden, die Wiedergabe wird jedoch auf irgendeine Weise beeinträchtigt. Beispielsweise kann eine 5.1-Audiospur stattdessen als 2-Kanal-Stereo wiedergegeben werden. Wenn dies der Fall ist, sollten Sie die Benutzeroberfläche aktualisieren, um den Benutzer über die Beeinträchtigung zu informieren. Wenn der Wert "UnsupportedSubtype " oder "UnsupportedEncoderProperties" lautet, kann der Titel überhaupt nicht mit den aktuellen Codecs auf dem Gerät wiedergegeben werden. Möglicherweise möchten Sie den Benutzer benachrichtigen und die Wiedergabe des Elements überspringen oder die Benutzeroberfläche implementieren, damit der Benutzer den richtigen Codec herunterladen kann. Die GetEncodingProperties-Methode des Titels kann verwendet werden, um den erforderlichen Codec für die Wiedergabe zu ermitteln.

Abschließend können Sie sich für das OpenFailed-Ereignis der Spur registrieren, das ausgelöst wird, wenn die Spur auf dem Gerät unterstützt wird, aber aufgrund eines unbekannten Fehlers in der Pipeline nicht geöffnet werden konnte.

private async void SnippetAudioTracksChanged_CodecCheck(MediaPlaybackItem sender, IVectorChangedEventArgs args)
{
    if (args.CollectionChange == CollectionChange.ItemInserted)
    {
        var insertedTrack = sender.AudioTracks[(int)args.Index];

        var decoderStatus = insertedTrack.SupportInfo.DecoderStatus;
        if (decoderStatus != MediaDecoderStatus.FullySupported)
        {
            if (decoderStatus == MediaDecoderStatus.Degraded)
            {
                ShowMessageToUser($"Track {insertedTrack.Name} can play but playback will be degraded. {insertedTrack.SupportInfo.DegradationReason}");
            }
            else
            {
                // status is MediaDecoderStatus.UnsupportedSubtype or MediaDecoderStatus.UnsupportedEncoderProperties
                ShowMessageToUser($"Track {insertedTrack.Name} uses an unsupported media format.");
            }

            Windows.Media.MediaProperties.AudioEncodingProperties props = insertedTrack.GetEncodingProperties();
            await HelpUserInstallCodec(props);
        }
        else
        {
            insertedTrack.OpenFailed += InsertedTrack_OpenFailed; ;
        }
    }

}

Im OpenFailed-Ereignishandler können Sie überprüfen, ob der MediaSource-Status unbekannt ist. Wenn dies der Fall ist, können Sie programmgesteuert einen anderen Titel für die Wiedergabe auswählen, dem Benutzer die Auswahl eines anderen Titels gestatten oder die Wiedergabe abbrechen.

private async void InsertedTrack_OpenFailed(AudioTrack sender, AudioTrackOpenFailedEventArgs args)
{
    LogError(args.ExtendedError.HResult);

    if (sender.SupportInfo.MediaSourceStatus == MediaSourceStatus.Unknown)
    {
        await SelectAnotherTrackOrSkipPlayback(sender.PlaybackItem);
    }
    ;
}

Festlegen von Anzeigeeigenschaften, die von den Systemmedientransport-Steuerelementen verwendet werden

Medien, die in einem MediaPlayer wiedergegeben werden, werden standardmäßig automatisch in die Steuerelemente für den Systemmedientransport (System Media Transport Controls, SMTC) integriert. Sie können die Metadaten angeben, die vom SMTC angezeigt werden sollen, indem Sie die Anzeigeeigenschaften für ein MediaPlaybackItem-Objekt aktualisieren. Ruft ein Objekt ab, das die Anzeigeeigenschaften für ein Element darstellt, indem Sie GetDisplayProperties aufrufen. Legen Sie fest, ob das Wiedergabeelement Musik oder Video ist, indem Sie die Type-Eigenschaft festlegen. Legen Sie dann die Eigenschaften der VideoProperties oder MusicProperties des Objekts fest. Rufen Sie ApplyDisplayProperties auf, um die Eigenschaften des Elements auf die von Ihnen bereitgestellten Werte zu aktualisieren. In der Regel ruft eine App die Anzeigewerte dynamisch aus einem Webdienst ab. Im folgenden Beispiel wird dieser Vorgang jedoch mit hartcodierten Werten veranschaulicht.

MediaItemDisplayProperties props = mediaPlaybackItem.GetDisplayProperties();
props.Type = Windows.Media.MediaPlaybackType.Video;
props.VideoProperties.Title = "Video title";
props.VideoProperties.Subtitle = "Video subtitle";
props.VideoProperties.Genres.Add("Documentary");
mediaPlaybackItem.ApplyDisplayProperties(props);
props = mediaPlaybackItem.GetDisplayProperties();
props.Type = Windows.Media.MediaPlaybackType.Music;
props.MusicProperties.Title = "Song title";
props.MusicProperties.Artist = "Song artist";
props.MusicProperties.Genres.Add("Polka");
mediaPlaybackItem.ApplyDisplayProperties(props);

Hinzufügen von externem zeitlimitiertem Text mit TimedTextSource

In einigen Szenarien verfügen Sie möglicherweise über externe Dateien, die zeitlich synchronisierten Text enthalten, der einem Medienelement zugeordnet ist, z. B. separate Dateien, die Untertitel in verschiedenen Sprachen enthalten. Verwenden Sie die TimedTextSource-Klasse, um externe zeitgestützte Textdateien aus einem Datenstrom oder einer URI zu laden.

Erstellen Sie eine neue TimedTextSource für jede externe zeitlich festgelegte Textdatei, indem Sie CreateFromUri aufrufen. Fügen Sie einen Eintrag zum Wörterbuch für die zeitgesteuerte Textquelle hinzu. Fügen Sie einen Handler für das TimedTextSource.Resolved-Ereignis hinzu, um zu behandeln, falls das Element nicht richtig geladen wird oder zusätzliche Eigenschaften festgelegt werden, nachdem das Element erfolgreich geladen wurde.

Registrieren Sie alle Ihre TimedTextSource-Objekte mit der MediaSource , indem Sie sie der ExternalTimedTextSources-Auflistung hinzufügen. Beachten Sie, dass externe zeitbasierte Textquellen direkt zur MediaSource und nicht zum mediaPlaybackItem hinzugefügt werden, das aus der Quelle erstellt wurde. Um Die Benutzeroberfläche so zu aktualisieren, dass sie die externen Textspuren wiederspiegelt, registrieren und behandeln Sie das TimedMetadataTracksChanged-Ereignis , wie zuvor in diesem Artikel beschrieben.

Dictionary<TimedTextSource, Uri> timedTextSourceMap;
// Create the TimedTextSource and add entry to URI map
var timedTextSourceUri_En = new Uri("http://contoso.com/MyClipTimedText_en.srt");
var timedTextSource_En = TimedTextSource.CreateFromUri(timedTextSourceUri_En);
timedTextSourceMap[timedTextSource_En] = timedTextSourceUri_En;
timedTextSource_En.Resolved += TimedTextSource_Resolved;

var timedTextSourceUri_Pt = new Uri("http://contoso.com/MyClipTimedText_pt.srt");
var timedTextSource_Pt = TimedTextSource.CreateFromUri(timedTextSourceUri_Pt);
timedTextSourceMap[timedTextSource_Pt] = timedTextSourceUri_Pt;
timedTextSource_Pt.Resolved += TimedTextSource_Resolved;

// Add the TimedTextSource to the MediaSource
mediaSource.ExternalTimedTextSources.Add(timedTextSource_En);
mediaSource.ExternalTimedTextSources.Add(timedTextSource_Pt);

mediaPlaybackItem = new MediaPlaybackItem(mediaSource);
mediaPlaybackItem.TimedMetadataTracksChanged += MediaPlaybackItem_TimedMetadataTracksChanged;

mediaPlayer = new MediaPlayer();
mediaPlayer.Source = mediaPlaybackItem;
mediaPlayerElement.SetMediaPlayer(mediaPlayer);

Überprüfen Sie im Handler für das TimedTextSource.Resolved-Ereignis die Error-Eigenschaft der an den Handler übergebenen TimedTextSourceResolveResultEventArgs , um zu ermitteln, ob beim Laden der Zeitdaten ein Fehler aufgetreten ist. Wenn das Element erfolgreich aufgelöst wurde, können Sie diesen Handler verwenden, um zusätzliche Eigenschaften des aufgelösten Titels zu aktualisieren. In diesem Beispiel wird eine Bezeichnung für jeden Titel basierend auf dem zuvor im Wörterbuch gespeicherten URI hinzugefügt.

private void TimedTextSource_Resolved(TimedTextSource sender, TimedTextSourceResolveResultEventArgs args)
{
    var timedTextSourceUri = timedTextSourceMap[sender];

    if (!(args.Error is null))
    {
        // Show that there was an error in your UI
        ShowMessageToUser($"There was an error resolving track: {timedTextSourceUri}");
        return;
    }

    // Add a label for each resolved track
    var timedTextSourceUriString = timedTextSourceUri.AbsoluteUri;
    if (timedTextSourceUriString.Contains("_en"))
    {
        args.Tracks[0].Label = "English";
    }
    else if (timedTextSourceUriString.Contains("_pt"))
    {
        args.Tracks[0].Label = "Portuguese";
    }
}

Eine Liste der unter Windows unterstützten Zeittextformate finden Sie unter "Unterstützte Codecs".

Hinzufügen zusätzlicher Metadaten-Spuren

Sie können benutzerdefinierte Metadatentitel dynamisch im Code erstellen und sie einer Medienquelle zuordnen. Die von Ihnen erstellten Titel können Untertitel- oder Beschriftungstext enthalten, oder sie können Ihre proprietären App-Daten enthalten.

Erstellen Sie einen neuen TimedMetadataTrack , indem Sie den Konstruktor aufrufen und eine ID, den Sprachbezeichner und einen Wert aus der TimedMetadataKind-Aufzählung angeben. Registrieren Sie Handler für die CueEntered - und CueExited-Ereignisse . Diese Ereignisse werden ausgelöst, wenn die Startzeit für einen Hinweis erreicht wurde und die Dauer für einen Hinweis abgelaufen ist.

Erstellen Sie ein neues Cue-Objekt, das für den Von Ihnen erstellten Metadatentiteltyp geeignet ist, und legen Sie die ID, die Startzeit und die Dauer für den Titel fest. In diesem Beispiel wird ein Datentitel erstellt, sodass eine Reihe von DataCue-Objekten generiert wird und ein Puffer mit app-spezifischen Daten für jeden Hinweis bereitgestellt wird. Um den neuen Titel zu registrieren, fügen Sie ihn der ExternalTimedMetadataTracks-Auflistung des MediaSource-Objekts hinzu.

Die DataCue.Properties-Eigenschaft macht ein PropertySet verfügbar, mit dem Sie benutzerdefinierte Eigenschaften in Schlüssel-/Datenpaaren speichern können, die in den CueEntered - und CueExited-Ereignissen abgerufen werden können.

TimedMetadataTrack metadataTrack = new TimedMetadataTrack("ID_0", "en-us", TimedMetadataKind.Data);
metadataTrack.Label = "Custom data track";
metadataTrack.CueEntered += MetadataTrack_DataCueEntered;
metadataTrack.CueExited += MetadataTrack_CueExited;

// Example cue data
string data = "Cue data";
byte[] bytes = new byte[data.Length * sizeof(char)];
System.Buffer.BlockCopy(data.ToCharArray(), 0, bytes, 0, bytes.Length);
Windows.Storage.Streams.IBuffer buffer = bytes.AsBuffer();

for (int i = 0; i < 10; i++)
{
    DataCue cue = new DataCue();
    cue.Id = "ID_" + i;
    cue.Data = buffer;
    cue.Properties["AdUrl"] = "http://contoso.com/ads/123";
    cue.StartTime = TimeSpan.FromSeconds(3 + i * 3);
    cue.Duration = TimeSpan.FromSeconds(2);

    metadataTrack.AddCue(cue);
}

mediaSource.ExternalTimedMetadataTracks.Add(metadataTrack);

Das CueEntered-Ereignis wird ausgelöst, wenn die Startzeit eines Cues erreicht wurde, solange die zugeordnete Spur einen Präsentationsmodus von ApplicationPresented, Hidden oder PlatformPresented hat. Cue-Ereignisse werden nicht für Metadaten-Spuren ausgelöst, während der Präsentationsmodus für die Spur Disabled ist. In diesem Beispiel werden die dem Hinweis zugeordneten benutzerdefinierten Daten einfach in das Debug-Fenster ausgegeben.

private void MetadataTrack_DataCueEntered(TimedMetadataTrack sender, MediaCueEventArgs args)
{
    DataCue cue = (DataCue)args.Cue;
    string data = System.Text.Encoding.Unicode.GetString(cue.Data.ToArray());
    System.Diagnostics.Debug.WriteLine("Cue entered: " + data);
    System.Diagnostics.Debug.WriteLine("Custom prop value: " + cue.Properties["AdUrl"]);
}

In diesem Beispiel wird ein benutzerdefinierter Texttitel hinzugefügt, indem TimedMetadataKind.Caption beim Erstellen des Titels angegeben und TimedTextCue-Objekte verwendet werden, um dem Titel Hinweise hinzuzufügen.

TimedMetadataTrack metadataTrack = new TimedMetadataTrack("TrackID_0", "en-us", TimedMetadataKind.Caption);
metadataTrack.Label = "Custom text track";
metadataTrack.CueEntered += MetadataTrack_TextCueEntered;

for (int i = 0; i < 10; i++)
{
    TimedTextCue cue = new TimedTextCue()
    {
        Id = "TextCueID_" + i,
        StartTime = TimeSpan.FromSeconds(i * 3),
        Duration = TimeSpan.FromSeconds(2)
    };

    cue.Lines.Add(new TimedTextLine() { Text = "This is a custom timed text cue." });
    metadataTrack.AddCue(cue);
}

mediaSource.ExternalTimedMetadataTracks.Add(metadataTrack);
private void MetadataTrack_TextCueEntered(TimedMetadataTrack sender, MediaCueEventArgs args)
{
    TimedTextCue cue = (TimedTextCue)args.Cue;
    System.Diagnostics.Debug.WriteLine("Cue entered: " + cue.Id + " " + cue.Lines[0].Text);
}

Wiedergeben einer Liste von Medienelementen mit MediaPlaybackList

Mit der MediaPlaybackList können Sie eine Wiedergabeliste mit Medienelementen erstellen, die durch MediaPlaybackItem-Objekte dargestellt werden.

Hinweis Elemente in einer MediaPlaybackList werden mithilfe der lückenlosen Wiedergabe gerendert. Das System verwendet bereitgestellte Metadaten in MP3- oder AAC-codierten Dateien, um die Verzögerungs- oder Abstandskorrektur zu ermitteln, die für die lückelose Wiedergabe erforderlich ist. Wenn die MP3- oder AAC-codierten Dateien diese Metadaten nicht bereitstellen, bestimmt das System die Verzögerung oder den Abstand heuristisch. Bei verlustfreien Formaten wie PCM, FLAC oder ALAC führt das System keine Aktion aus, da diese Encoder keine Verzögerung oder Abstände einführen.

Erstellen Sie ein MediaPlaybackItem-Element für jedes Medienelement, das Sie Ihrer Liste hinzufügen möchten, mithilfe desselben Verfahrens, das zuvor in diesem Artikel beschrieben wurde. Initialisieren Sie Ihr MediaPlaybackList-Objekt , und fügen Sie die Medienwiedergabeelemente hinzu. Registrieren Sie einen Handler für das CurrentItemChanged-Ereignis . Mit diesem Ereignis können Sie die Benutzeroberfläche aktualisieren, um das derzeit wiedergegebene Medienelement anzuzeigen. Sie können sich auch für das ItemOpened-Ereignis registrieren, das ausgelöst wird, wenn ein Element in der Liste erfolgreich geöffnet wird, und das ItemFailed-Ereignis , das ausgelöst wird, wenn ein Element in der Liste nicht geöffnet werden kann.

Sie können die maximale Anzahl der MediaPlaybackItem-Objekte in der MediaPlaybackList angeben, die das System nach deren Wiedergabe geöffnet hält, indem Sie die MaxPlayedItemsToKeepOpen-Eigenschaft festlegen. Wenn ein MediaPlaybackItem geöffnet gehalten wird, kann die Wiedergabe des Elements sofort gestartet werden, wenn der Benutzer zu diesem Element wechselt, da das Element nicht neu geladen werden muss. Das Öffnen von Elementen erhöht jedoch auch den Speicherverbrauch Ihrer App, sodass Sie beim Festlegen dieses Werts das Gleichgewicht zwischen Reaktionsfähigkeit und Speicherauslastung berücksichtigen sollten.

Um die Wiedergabe Ihrer Liste zu aktivieren, legen Sie die Wiedergabequelle des MediaPlayers auf Ihre MediaPlaybackList fest.

MediaPlaybackList mediaPlaybackList;
mediaPlaybackList = new MediaPlaybackList();

var results = await filePicker.PickMultipleFilesAsync();

foreach (var result in results)
{
    var storageFile = await Windows.Storage.StorageFile.GetFileFromPathAsync(result.Path);
    var mediaPlaybackItem = new MediaPlaybackItem(MediaSource.CreateFromStorageFile(storageFile));
    mediaPlaybackList.Items.Add(mediaPlaybackItem);
}

mediaPlaybackList.CurrentItemChanged += MediaPlaybackList_CurrentItemChanged;
mediaPlaybackList.ItemOpened += MediaPlaybackList_ItemOpened; ;
mediaPlaybackList.ItemFailed += MediaPlaybackList_ItemFailed; ;

mediaPlaybackList.MaxPlayedItemsToKeepOpen = 3;

mediaPlayer = new MediaPlayer();
mediaPlayer.Source = mediaPlaybackList;
mediaPlayerElement.SetMediaPlayer(mediaPlayer);

Aktualisieren Sie im CurrentItemChanged-Ereignishandler die Benutzeroberfläche, damit es das aktuell wiedergegebene Element widerspiegelt, das mithilfe der NewItem-Eigenschaft des an das Ereignis übergebenen CurrentMediaPlaybackItemChangedEventArgs-Objekts abgerufen werden kann. Denken Sie daran, dass Sie, wenn Sie die UI auf Basis dieses Ereignisses aktualisieren möchten, dies innerhalb eines Aufrufs von DispatcherQueue.TryEnqueue tun sollten, damit die Aktualisierungen im UI-Thread durchgeführt werden.

Sie können die CurrentMediaPlaybackItemChangedEventArgs.Reason-Eigenschaft überprüfen, um einen Wert abzurufen, der den Grund angibt, warum das Element geändert wurde, z. B. das programmgesteuerte Wechseln von Elementen, das zuvor wiedergegebene Element das Ende erreicht oder ein Fehler aufgetreten ist.

private void MediaPlaybackList_CurrentItemChanged(MediaPlaybackList sender, CurrentMediaPlaybackItemChangedEventArgs args) =>
    LogTelemetryData($"CurrentItemChanged reason: {args.Reason.ToString()}");

Rufen Sie MovePrevious oder MoveNext auf, damit der Media Player das vorherige oder nächste Element in Ihrer MediaPlaybackList wiedergeben kann.

private void PrevButton_Click(object sender, RoutedEventArgs e)
{
    mediaPlaybackList.MovePrevious();
}
private void NextButton_Click(object sender, RoutedEventArgs e)
{
    mediaPlaybackList.MoveNext();
}

Legen Sie die ShuffleEnabled-Eigenschaft fest, um anzugeben, ob der Media Player die Elemente in Ihrer Liste in zufälliger Reihenfolge wiedergeben soll.

private void ShuffleButton_Click(object sender, RoutedEventArgs e)
{
    mediaPlaybackList.ShuffleEnabled = !mediaPlaybackList.ShuffleEnabled;

    DispatcherQueue.TryEnqueue(() =>
    {
        shuffleButton.FontWeight =
            mediaPlaybackList.ShuffleEnabled ? Microsoft.UI.Text.FontWeights.Bold : Microsoft.UI.Text.FontWeights.Light;
    });
}

Legen Sie die AutoRepeatEnabled-Eigenschaft fest, um anzugeben, ob der Media Player die Wiedergabe Ihrer Liste durchlaufen soll.

private void AutoRepeatButton_Click(object sender, RoutedEventArgs e)
{
    mediaPlaybackList.AutoRepeatEnabled = !mediaPlaybackList.AutoRepeatEnabled;

    DispatcherQueue.TryEnqueue(() =>
    {
        autoRepeatButton.FontWeight =
            mediaPlaybackList.AutoRepeatEnabled ? Microsoft.UI.Text.FontWeights.Bold : Microsoft.UI.Text.FontWeights.Light;
    });
}

Verwaltung von Fehlern bei Medienelementen in einer Wiedergabeliste

Das ItemFailed-Ereignis wird ausgelöst, wenn ein Element in der Liste nicht geöffnet werden kann. Die ErrorCode-Eigenschaft des MediaPlaybackItemError - Objekts, das an den Handler übergeben wird, listet die spezifische Ursache des Fehlers auf, wenn möglich, einschließlich Netzwerkfehlern, Decodierungsfehlern oder Verschlüsselungsfehlern.

private void MediaPlaybackList_ItemOpened(MediaPlaybackList sender, MediaPlaybackItemOpenedEventArgs args)
{

}

Deaktivieren der Wiedergabe von Elementen in einer Wiedergabeliste

Sie können die Wiedergabe eines oder mehrerer Elemente in einer MediaPlaybackItemList deaktivieren, indem Sie die IsDisabledInPlaybackList-Eigenschaft eines MediaPlaybackItem auf "false" festlegen.

Ein typisches Szenario für dieses Feature ist für Apps, die Streamingmusik wiedergeben. Die App kann änderungen am Netzwerkverbindungsstatus des Geräts überwachen und die Wiedergabe von Elementen deaktivieren, die nicht vollständig heruntergeladen wurden. Im folgenden Beispiel wird ein Handler für das Ereignis NetworkInformation.NetworkStatusChanged registriert.

Windows.Networking.Connectivity.NetworkInformation.NetworkStatusChanged += NetworkInformation_NetworkStatusChanged; ;

Überprüfen Sie im Handler für NetworkStatusChanged, ob GetInternetConnectionProfile null zurückgibt, was angibt, dass das Netzwerk nicht verbunden ist. Wenn dies der Fall ist, durchlaufen Sie alle Elemente in der Wiedergabeliste, und wenn der TotalDownloadProgress für das Element kleiner als 1 ist, was bedeutet, dass das Element nicht vollständig heruntergeladen wurde, deaktivieren Sie das Element. Wenn die Netzwerkverbindung aktiviert ist, durchlaufen Sie alle Elemente in der Wiedergabeliste, und aktivieren Sie jedes Element.

private void NetworkInformation_NetworkStatusChanged(object sender)
{
    if (Windows.Networking.Connectivity.NetworkInformation.GetInternetConnectionProfile() == null)
    {
        // Check download status of each item in the list. (TotalDownloadProgress < 1 means not completely downloaded)
        foreach (var item in mediaPlaybackList.Items)
        {
            if (item.TotalDownloadProgress < 1)
            {
                item.IsDisabledInPlaybackList = true;
            }
        }
    }
    else
    {
        // Connected to internet, re-enable all playlist items
        foreach (var item in mediaPlaybackList.Items)
        {
            item.IsDisabledInPlaybackList = true;
        }
    }
}

Zurückstellen der Bindung von Medieninhalten für Elemente in einer Wiedergabeliste mithilfe von MediaBinder

In den vorherigen Beispielen wird eine MediaSource aus einer Datei, URL oder einem Stream erstellt, nach der ein MediaPlaybackItem erstellt und einer MediaPlaybackList hinzugefügt wird. In einigen Szenarien, z. B. wenn dem Benutzer das Anzeigen von Inhalten in Rechnung gestellt wird, sollten Sie den Abruf des Inhalts einer MediaSource verzögern, bis das Element in der Wiedergabeliste bereit ist, tatsächlich wiedergegeben zu werden. Erstellen Sie zum Implementieren dieses Szenarios eine Instanz der MediaBinder-Klasse . Legen Sie die Token-Eigenschaft auf eine appdefinierte Zeichenfolge fest, die den Inhalt identifiziert, für den Sie den Abruf zurückstellen möchten, und registrieren Sie dann einen Handler für das Binding-Ereignis . Erstellen Sie als Nächstes eine MediaSource aus dem Binder, indem Sie MediaSource.CreateFromMediaBinder aufrufen. Erstellen Sie dann ein MediaPlaybackItem aus der MediaSource , und fügen Sie es wie gewohnt zur Wiedergabeliste hinzu.

mediaPlaybackList = new MediaPlaybackList();

var binder = new MediaBinder();
binder.Token = "MyBindingToken1";
binder.Binding += Binder_Binding; ;
mediaPlaybackList.Items.Add(new MediaPlaybackItem(MediaSource.CreateFromMediaBinder(binder)));

binder = new MediaBinder();
binder.Token = "MyBindingToken2";
binder.Binding += Binder_Binding;
mediaPlaybackList.Items.Add(new MediaPlaybackItem(MediaSource.CreateFromMediaBinder(binder)));

mediaPlayer = new MediaPlayer();
mediaPlayer.Source = mediaPlaybackList;
mediaPlayerElement.SetMediaPlayer(mediaPlayer);

Wenn das System feststellt, dass der dem MediaBinder zugeordnete Inhalt abgerufen werden muss, löst es das Binding-Ereignis aus. Im Handler für dieses Ereignis können Sie die MediaBinder-Instanz aus dem an das Ereignis übergebenen MediaBindingEventArgs abrufen. Rufen Sie die für die Token-Eigenschaft angegebene Zeichenfolge ab, und verwenden Sie sie, um zu bestimmen, welche Inhalte abgerufen werden sollen. MediaBindingEventArgs stellt Methoden zum Festlegen des gebundenen Inhalts in verschiedenen Darstellungen bereit, einschließlich SetStorageFile, SetStream, SetStreamReference und SetUri.

private void Binder_Binding(MediaBinder sender, MediaBindingEventArgs args)
{
    // Get a deferral if you need to perform async operations
    var deferral = args.GetDeferral();

    var contentUri = new Uri("http://contoso.com/media/" + args.MediaBinder.Token);
    args.SetUri(contentUri);

    // Call complete after your async operations are complete
    deferral.Complete();
}

Beachten Sie, dass Sie beim Ausführen asynchroner Vorgänge, z. B. Webanforderungen, im Binding-Ereignishandler die MediaBindingEventArgs.GetDeferral-Methode aufrufen sollten, um das System anzuweisen, auf den Abschluss des Vorgangs zu warten, bevor Sie fortfahren. Rufen Sie Deferral.Complete auf, nachdem der Vorgang abgeschlossen ist, das System anzuweisen, den Vorgang fortzusetzen.

Ab Windows 10, Version 1703, können Sie eine AdaptiveMediaSource als gebundenen Inhalt bereitstellen, indem Sie SetAdaptiveMediaSource aufrufen. Weitere Informationen zur Verwendung von adaptivem Streaming in Ihrer App finden Sie unter Adaptives Streaming.