Share via


Medienelemente, Wiedergabelisten und Titel

In diesem Artikel wird die Verwendung der MediaSource-Klasse erläutert, 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 Wiedergeben 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 diese mit einem MediaPlayer abspielen, indem Sie die Eigenschaft Source festlegen. Ab Windows 10, Version 1607, können Sie einem MediaPlayerElement einem MediaPlayer zuweisen, indem Sie SetMediaPlayer aufrufen, um den Media Player-Inhalt auf einer XAML-Seite zu rendern. Dies ist die bevorzugte Methode für die Verwendung von MediaElement. Weitere Informationen zur Verwendung des MediaPlayer finden Sie unter Audio und Video mit dem MediaPlayer abspielen.

Das folgende Beispiel zeigt, wie eine vom Benutzer ausgewählte Mediendatei in einem MediaPlayer mithilfe von MediaSource wiedergegeben wird.

Sie müssen die Namespaces Windows.Media.Core und Windows.Media.Playback einschließen, um dieses Szenario abzuschließen.

using Windows.Media.Core;
using Windows.Media.Playback;

Deklarieren Sie eine Variable vom Typ "MediaSource". Für die Beispiele in diesem Artikel wird die Medienquelle als Klassenmitglied deklariert, sodass von mehreren Speicherorten aus darauf zugegriffen werden kann.

MediaSource _mediaSource;

Deklarieren Sie eine Variable zum Speichern des MediaPlayer-Objekts , und fügen Sie ihrer Seite ein MediaPlayerElement-Steuerelement hinzu, wenn Sie den Medieninhalt in XAML rendern möchten.

MediaPlayer _mediaPlayer;
<MediaPlayerElement x:Name="mediaPlayerElement"/>

Verwenden Sie einen FileOpenPicker, um dem Benutzer die Auswahl einer Mediendatei zur Wiedergabe zu ermöglichen. Initialisieren Sie mit dem StorageFile-Objekt, das von der PickSingleFileAsync-Methode des Pickers zurückgegeben wird, ein neues MediaObject, indem Sie MediaSource.CreateFromStorageFile aufrufen. Legen Sie abschließend die Medienquelle als Wiedergabequelle für das MediaElement fest, indem Sie die Methode SetPlaybackSource aufrufen.

//Create a new picker
var filePicker = new Windows.Storage.Pickers.FileOpenPicker();

//make a collection of all video types you want to support (for testing we are adding just 3).
string[] fileTypes = new string[] {".wmv", ".mp4", ".mkv"};   
   
//Add your fileTypes to the FileTypeFilter list of filePicker.
foreach (string fileType in fileTypes)
{
    filePicker.FileTypeFilter.Add(fileType);
}

//Set picker start location to the video library
filePicker.SuggestedStartLocation = PickerLocationId.VideosLibrary;

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

if (!(file is null))
{
    _mediaSource = MediaSource.CreateFromStorageFile(file);
    _mediaPlayer = new MediaPlayer();
    _mediaPlayer.Source = _mediaSource;
    mediaPlayerElement.SetMediaPlayer(_mediaPlayer);
}

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

_mediaPlayer.Play();

Sie können auch die Eigenschaft AutoPlay des MediaPlayer auf „True“ setzen, um dem Player mitzuteilen, dass die Wiedergabe beginnen soll, sobald die Medienquelle festgelegt ist.

_mediaPlayer.AutoPlay = true;

Erstellen einer MediaSource aus einer DownloadOperation

Ab Windows, Version 1803, können Sie ein MediaSource-Objekt aus einer DownloadOperation erstellen.

StorageFile destinationFile = await KnownFolders.VideosLibrary.CreateFileAsync("file.mp4", CreationCollisionOption.GenerateUniqueName);

var downloader = new BackgroundDownloader();
var downloadOperation = downloader.CreateDownload(new Uri("http://server.com/file.mp4"), destinationFile);
MediaSource mediaSource =
      MediaSource.CreateFromDownloadOperation(downloadOperation);

Beachten Sie, dass Sie zwar eine MediaSource aus einem Download erstellen können, ohne sie zu starten oder die IsRandomAccessRequired-Eigenschaft auf "true" festzulegen, müssen Sie jedoch beide Aktionen ausführen, bevor Sie versuchen, die MediaSource an einen MediaPlayer oder MediaPlayerElement für die Wiedergabe anzufügen.

downloadOperation.IsRandomAccessRequired = true;
var startAsyncTask = downloadOperation.StartAsync().AsTask();
mediaPlayerElement.Source = mediaSource;

Behandeln mehrerer Audio-, Video- und Metadatentitel mit MediaPlaybackItem

Die Verwendung einer MediaSource für die Wiedergabe ist praktisch, da sie eine allgemeine Möglichkeit zur Wiedergabe von Medien aus unterschiedlichen Quellen bietet. Auf erweiterte Funktionen kann jedoch zugegriffen werden, indem ein MediaPlaybackItem aus der MediaSource erstellt wird. Dies umfasst die Möglichkeit, auf mehrere Audio-, Video- und Datenspuren für ein Medienelement zuzugreifen und diese zu verwalten.

Deklarieren Sie eine Variable zum Speichern Ihres MediaPlaybackItem.

MediaPlaybackItem _mediaPlaybackItem;

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.

_mediaSource = MediaSource.CreateFromStorageFile(file);
_mediaPlaybackItem = new MediaPlaybackItem(_mediaSource);

_mediaPlaybackItem.AudioTracksChanged += PlaybackItem_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 Handler VideoTracksChanged alle Titel in der Liste VideoTracks 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 Kombinationsfeldelements wird auf den Titelindex 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 CoreDispatcher.RunAsync-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 async void MediaPlaybackItem_VideoTracksChanged(MediaPlaybackItem sender, IVectorChangedEventArgs args)
{
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        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 Trackindex aus de Tag-Eigenschaft des ausgewählten Elements abgerufen. Das Festlegen der Eigenschaft SelectedIndex der Liste VideoTracks des Medienwiedergabeelements bewirkt, dass das MediaElement oder der MediaPlayer die aktive Videospur auf den angegebenen Index umschaltet.

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 sich in der Liste AudioTracks des Wiedergabeelements befinden. 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 async void PlaybackItem_AudioTracksChanged(MediaPlaybackItem sender, IVectorChangedEventArgs args)
{
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        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;
            videoTracksComboBox.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 zeitorientierter Metadatentitel kann Untertitel oder Untertitel Text enthalten oder benutzerdefinierte Daten enthalten, die für Ihre App geschützt sind. Eine zeitgesteuerte Metadatenspur enthält eine Liste von Hinweisen, die durch Objekte dargestellt werden, die von IMediaCue erben, wie 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 zeitlimitierten Metadatentiteln möchte der Benutzer jedoch möglicherweise mehrere Metadatentitel gleichzeitig 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 async void MediaPlaybackItem_TimedMetadataTracksChanged(MediaPlaybackItem sender, IVectorChangedEventArgs args)
{
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        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 die Methode SetPresentationMode des MediaPlaybackItem-Objekts auf, übergeben Sie den Index des Titels, den Sie umschalten möchten, und geben Sie dann einen Wert aus der Aufzählung TimedMetadataTrackPresentationMode an. Der von Ihnen ausgewählte Präsentationsmodus hängt von der Implementierung Ihrer App ab. In diesem Beispiel wird die Metadatenspur auf PlatformPresented festgelegt, wenn sie 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 Metadatentracks verarbeiten, können Sie auf die Cues-Gruppe innerhalb des Tracks zugreifen, indem Sie auf die Eigenschaften Cues oder ActiveCues zugreifen. Sie können dies tun, um Die Benutzeroberfläche so zu aktualisieren, dass die Speicherorte für ein Medienelement angezeigt werden.

Behandeln nicht unterstützter Codecs und unbekannter Fehler beim Öffnen von Medienelementen

Ab Windows 10, Version 1607, können Sie ü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-Ereignisse geänderte Ereignisse, z . B. AudioTracksChanged, zuerst, um festzustellen, ob die Änderung der Spur eine Einfügung eines neuen Titels ist. Wenn ja, können Sie mithilfe des indexes, der im Parameter "IVectorChangedEventArgs.Index " übergeben wird, mit der entsprechenden Track-Auflistung des MediaPlaybackItem-Parameters , z. B. der AudioTracks-Auflistung , einen Verweis auf den eingefügten Titel abrufen.

Sobald Sie einen Verweis auf den eingefügten Track haben, überprüfen Sie den DecoderStatus der Eigenschaft SupportInfo des Tracks. Wenn der Wert FullySupportedlautet, ist der entsprechende Codec, der zur Wiedergabe des Titels benötigt wird, auf dem Gerät vorhanden. Wenn der Wert Degraded 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 UnsupportedEncoderPropertiesist, kann der Track mit den aktuellen Codecs auf dem Gerät überhaupt nicht 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 Methode GetEncodingProperties des Tracks kann der für die Wiedergabe erforderliche Codec ermittelt werden.

Schließlich können Sie sich für das Ereignis OpenFailed des Tracks registrieren, das ausgelöst wird, wenn der Track 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 Ereignishandler OpenFailed können Sie prüfen, ob der Status von MediaSource unbekannt ist. Wenn dies der Fall ist, können Sie programmgesteuert einen anderen Titel zur Wiedergabe auswählen, dem Benutzer die Auswahl eines anderen Titels erlauben 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 Steuerelementen für den Systemmedientransport verwendet werden

Ab Windows 10, Version 1607, ist die in einem MediaPlayer wiedergegebene Medien 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 zeitbezogenen Text enthalten, der einem Medienelement zugeordnet ist, z. B. separate Dateien, die Untertitel für verschiedene Gebietsschemas enthalten. Verwenden Sie die TimedTextSource-Klasse , um in externen zeitgestützten Textdateien aus einem Datenstrom oder URI zu laden.

In diesem Beispiel wird eine Dictionary-Sammlung verwendet, um eine Liste der zeitgesteuerten Textquellen für das Medienelement mithilfe des Quell-URI und des TimedTextSource-Objekts als Schlüssel-Wert-Paar zu speichern, um die Spuren nach der Auflösung zu identifizieren.

Dictionary<TimedTextSource, Uri> timedTextSourceMap;

Erstellen Sie für jede externe zeitgesteuerte Textdatei eine neue TimedTextSource, indem Sie CreateFromUri aufrufen. Fügen Sie einen Eintrag zum Dictionary für die zeitlimitierte Textquelle hinzu. Fügen Sie einen Handler für das TimedTextSource.Resolved-Ereignis hinzu, um zu behandeln, wenn das Element nicht geladen oder zusätzliche Eigenschaften festgelegt wurde, 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.

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

IÜberprüfen Sie im Handler für das Ereignis TimedTextSource.Resolved die Eigenschaft Error der an den Handler übergebenen TimedTextSourceResolveResultEventArgs,um zu ermitteln, ob beim Versuch, die zeitgesteuerten Textdaten zu laden, 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 Dictionary 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 Metadatentracks

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

Erstellen Sie einen neuen TimedMetadataTrack, indem Sie den Konstruktor aufrufen und eine ID, die Sprachenkennung und einen Wert aus der Enumeration TimedMetadataKind angeben. Registrieren Sie Handler für die Ereignisse CueEntered und CueExited. 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 Track zu registrieren, fügen Sie ihn der ExternalTimedMetadataTracks-Auflistung des MediaSource-Objekts hinzu.

Ab Windows 10, Version 1703, macht die DataCue.Properties-Eigenschaft 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 Markers erreicht wurde, solange der zugeordnete Titel über einen Präsentationsmodus von ApplicationPresented, Hidden oder PlatformPresented verfügt. Cue-Ereignisse werden für Metadatentitel nicht ausgelöst, während der Präsentationsmodus für den Titel deaktiviert ist. In diesem Beispiel werden einfach die benutzerdefinierten Daten ausgegeben, die dem Hinweis zugeordnet sind, in das Debugfenster.

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 eine benutzerdefinierte Texttrack hinzugefügt, indem beim Erstellen der Track TimedMetadataKind.Caption angegeben wird und TimedTextCue-Objekte verwendet werden, um dem Track 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 einer 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ückenlose 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.

Deklarieren Sie zunächst eine Variable, um Ihre MediaPlaybackList zu speichern.

MediaPlaybackList _mediaPlaybackList;

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. Register a handler for the CurrentItemChanged event. Mit diesem Ereignis können Sie die Benutzeroberfläche aktualisieren, um das aktuell wiedergegebene Medienelement widerzuspiegeln. 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.

Ab Windows 10, Version 1703, können Sie die maximale Anzahl von MediaPlaybackItem-Objekten in der MediaPlaybackList angeben, die das System geöffnet bleibt, nachdem sie wiedergegeben wurden, 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 = new MediaPlaybackList();

var files = await filePicker.PickMultipleFilesAsync();

foreach (var file in files)
{
    var mediaPlaybackItem = new MediaPlaybackItem(MediaSource.CreateFromStorageFile(file));
    _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 so, dass 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 Benutzeroberfläche von diesem Ereignis aktualisieren, in einem Aufruf von CoreDispatcher.RunAsync dies tun sollten, damit die Aktualisierungen im UI-Thread vorgenommen werden.

Ab Windows 10, Version 1703, können Sie die CurrentMediaPlaybackItemChangedEventArgs.Reason-Eigenschaft überprüfen, um einen Wert abzurufen, der angibt, warum das Element geändert wurde, z. B. die App programmgesteuert wechselt, das zuvor wiedergegebene Element das Ende erreicht oder ein Fehler auftritt.

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 wiedergibt.

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 async void shuffleButton_Click(object sender, RoutedEventArgs e)
{
    _mediaPlaybackList.ShuffleEnabled = !_mediaPlaybackList.ShuffleEnabled;

    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        shuffleButton.FontWeight =
            _mediaPlaybackList.ShuffleEnabled ? Windows.UI.Text.FontWeights.Bold : Windows.UI.Text.FontWeights.Light;
    });
}

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

private async void autoRepeatButton_Click(object sender, RoutedEventArgs e)
{
    _mediaPlaybackList.AutoRepeatEnabled = !_mediaPlaybackList.AutoRepeatEnabled;

    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        autoRepeatButton.FontWeight =
            _mediaPlaybackList.AutoRepeatEnabled ? Windows.UI.Text.FontWeights.Bold : Windows.UI.Text.FontWeights.Light;
    });
}

Behandeln des Fehlers von Medienelementen in einer Wiedergabeliste

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

private void MediaPlaybackList_ItemFailed(MediaPlaybackList sender, MediaPlaybackItemFailedEventArgs args)
{
    LogError(args.Error.ErrorCode.ToString());
    LogError(args.Error.ExtendedError.HResult);
}

Deaktivieren der Wiedergabe von Elementen in einer Wiedergabeliste

Ab Windows 10, Version 1703, können Sie 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 Musik wiedergeben, die aus dem Internet gestreamt werden. 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;
        }
    }
}

Aufschieben der Bindung von Media-Inhalten 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 Eigenschaft Token auf eine App-definierte Zeichenfolge fest, die den Inhalt identifiziert, dessen Abruf Sie verschieben möchten, und registrieren Sie dann einen Handler für das Ereignis Binding. Erstellen Sie nun eine MediaSource aus dem Binder durch den Aufruf MediaSource.CreateFromMediaBinder. Erstellen Sie dann ein MediaPlaybackItem aus der MediaSource und fügen Sie es wie immer der 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 den 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. Die MediaBindingEventArgs bieten Methoden zum Festlegen des gebundenen Inhalts in mehreren verschiedenen Darstellungen, darunter 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 Ihr Vorgang abgeschlossen ist, um das System anzuweisen, fortzufahren.

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.