Item media, daftar putar, dan trek

Artikel ini menunjukkan kepada Anda cara menggunakan kelas MediaSource , yang menyediakan cara umum untuk mereferensikan dan memutar media dari berbagai sumber seperti file lokal atau jarak jauh dan mengekspos model umum untuk mengakses data media, terlepas dari format media yang mendasar. Kelas MediaPlaybackItem memperluas fungsionalitas MediaSource, memungkinkan Anda mengelola dan memilih dari beberapa trek audio, video, dan metadata yang terkandung dalam item media. MediaPlaybackList memungkinkan Anda membuat daftar pemutaran dari satu atau beberapa item pemutaran media.

Membuat dan memutar MediaSource

Buat instans baru MediaSource dengan memanggil salah satu metode pabrik yang diekspos oleh kelas :

Setelah membuat MediaSource, Anda dapat memutarnya dengan MediaPlayer dengan mengatur properti Sumber. Dimulai dengan Windows 10, versi 1607, Anda dapat menetapkan MediaPlayer ke MediaPlayerElement dengan memanggil SetMediaPlayer untuk merender konten pemutar media di halaman XAML. Ini adalah metode yang disukai daripada menggunakan MediaElement. Untuk informasi selengkapnya tentang menggunakan MediaPlayer, lihat Memutar audio dan video dengan MediaPlayer.

Contoh berikut menunjukkan cara memutar kembali file media yang dipilih pengguna di MediaPlayer menggunakan MediaSource.

Anda harus menyertakan namespace Windows.Media.Core dan Windows.Media.Playback untuk menyelesaikan skenario ini.

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

Mendeklarasikan variabel jenis MediaSource. Untuk contoh dalam artikel ini, sumber media dinyatakan sebagai anggota kelas sehingga dapat diakses dari beberapa lokasi.

MediaSource _mediaSource;

Deklarasikan variabel untuk menyimpan objek MediaPlayer dan, jika Anda ingin merender konten media di XAML, tambahkan kontrol MediaPlayerElement ke halaman Anda.

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

Untuk memperbolehkan pengguna memilih file media untuk diputar, gunakan FileOpenPicker. Dengan objek StorageFile yang dikembalikan dari metode PickSingleFileAsync pemilih, inisialisasi MediaObject baru dengan memanggil MediaSource.CreateFromStorageFile. Terakhir, atur sumber media sebagai sumber pemutaran untuk MediaElement dengan memanggil metode SetPlaybackSource.

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

Secara default, MediaPlayer tidak mulai diputar secara otomatis ketika sumber media diatur. Anda dapat memulai pemutaran secara manual dengan memanggil Putar.

_mediaPlayer.Play();

Anda juga dapat mengatur properti AutoPlay mediaPlayer ke true untuk memberi tahu pemutar untuk mulai memutar segera setelah sumber media diatur.

_mediaPlayer.AutoPlay = true;

Membuat MediaSource dari DownloadOperation

Dimulai dengan Windows, versi 1803, Anda dapat membuat objek MediaSource dari DownloadOperation.

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

Perhatikan bahwa meskipun Anda dapat membuat MediaSource dari unduhan tanpa memulainya atau mengatur properti IsRandomAccessRequired ke true, Anda harus melakukan kedua hal ini sebelum mencoba melampirkan MediaSource ke MediaPlayer atau MediaPlayerElement untuk pemutaran.

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

Menangani beberapa trek audio, video, dan metadata dengan MediaPlaybackItem

Menggunakan MediaSource untuk pemutaran nyaman karena menyediakan cara umum untuk memutar media dari berbagai jenis sumber, tetapi perilaku yang lebih canggih dapat diakses dengan membuat MediaPlaybackItem dari MediaSource. Ini termasuk kemampuan untuk mengakses dan mengelola beberapa trek audio, video, dan data untuk item media.

Deklarasikan variabel untuk menyimpan MediaPlaybackItem Anda.

MediaPlaybackItem _mediaPlaybackItem;

Buat MediaPlaybackItem dengan memanggil konstruktor dan meneruskan objek MediaSource yang diinisialisasi.

Jika aplikasi Anda mendukung beberapa trek audio, video, atau data dalam item pemutaran media, daftarkan penanganan aktivitas untuk peristiwa AudioTracksChanged, VideoTracksChanged, atau TimedMetadataTracksChanged.

Terakhir, atur sumber pemutaran MediaElement atau MediaPlayer ke MediaPlaybackItem Anda.

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

Catatan

MediaSource hanya dapat dikaitkan dengan satu MediaPlaybackItem. Setelah membuat MediaPlaybackItem dari sumber, mencoba membuat item pemutaran lain dari sumber yang sama akan mengakibatkan kesalahan. Selain itu, setelah membuat MediaPlaybackItem dari sumber media, Anda tidak dapat mengatur objek MediaSource secara langsung sebagai sumber untuk MediaPlayer tetapi harus menggunakan MediaPlaybackItem.

Peristiwa VideoTracksChanged dimunculkan setelah MediaPlaybackItem yang berisi beberapa trek video ditetapkan sebagai sumber pemutaran, dan dapat dinaikkan lagi jika daftar video melacak perubahan untuk item berubah. Handler untuk kejadian ini memberi Anda kesempatan untuk memperbarui UI Anda untuk memungkinkan pengguna beralih di antara trek yang tersedia. Contoh ini menggunakan ComboBox untuk menampilkan trek video yang tersedia.

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

Di handler VideoTracksChanged, ulangi semua trek dalam daftar VideoTracks item pemutaran. Untuk setiap trek, ComboBoxItem baru dibuat. Jika trek belum memiliki label, label dihasilkan dari indeks trek. Properti Tag dari item kotak kombo diatur ke indeks trek sehingga dapat diidentifikasi nanti. Terakhir, item ditambahkan ke kotak kombo. Perhatikan bahwa operasi ini dilakukan dalam panggilan CoreDispatcher.RunAsync karena semua perubahan UI harus dilakukan pada utas UI dan peristiwa ini dinaikkan pada utas yang berbeda.

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

Dalam kotak Handler SelectionChanged untuk kombo, indeks trek diambil dari properti Tag item yang dipilih. Mengatur properti SelectedIndex dari daftar VideoTracks item pemutaran media menyebabkan MediaElement atau MediaPlayer mengalihkan trek video aktif ke indeks yang ditentukan.

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

Mengelola item media dengan beberapa trek audio berfungsi sama persis dengan trek video. Tangani AudioTracksChanged untuk memperbarui UI Anda dengan trek audio yang ditemukan di daftar AudioTracks item pemutaran. Saat pengguna memilih trek audio, atur properti SelectedIndex dari daftar AudioTracks untuk menyebabkan MediaElement atau MediaPlayer mengalihkan trek audio aktif ke indeks yang ditentukan.

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

Selain audio dan video, objek MediaPlaybackItem mungkin berisi nol atau lebih objek TimedMetadataTrack. Trek metadata berwaktu dapat berisi teks subtitel atau keterangan, atau mungkin berisi data kustom yang merupakan milik aplikasi Anda. Trek metadata berwaktu berisi daftar isjin yang diwakili oleh objek yang mewarisi dari IMediaCue, seperti DataCue atau TimedTextCue. Setiap istimasi memiliki waktu mulai dan durasi yang menentukan kapan isensi diaktifkan dan berapa lama.

Mirip dengan trek audio dan trek video, metadata berwaktu dilacak untuk item media dapat ditemukan dengan menangani peristiwa TimedMetadataTracksChanged dari MediaPlaybackItem. Namun, dengan trek metadata berwaktu, pengguna mungkin ingin mengaktifkan lebih dari satu trek metadata pada satu waktu. Selain itu, tergantung pada skenario aplikasi, Anda mungkin ingin mengaktifkan atau menonaktifkan trek metadata secara otomatis, tanpa intervensi pengguna. Untuk tujuan ilustrasi, contoh ini menambahkan ToggleButton untuk setiap trek metadata dalam item media untuk memungkinkan pengguna mengaktifkan dan menonaktifkan trek. Properti Tag dari setiap tombol diatur ke indeks trek metadata terkait sehingga dapat diidentifikasi saat tombol dialihkan.

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

Karena lebih dari satu trek metadata dapat aktif pada satu waktu, Anda tidak hanya mengatur indeks aktif untuk daftar trek metadata. Sebagai gantinya, panggil metode SetPresentationMode objek MediaPlaybackItem, meneruskan indeks trek yang ingin Anda alihkan, lalu berikan nilai dari enumerasi TimedMetadataTrackPresentationMode. Mode presentasi yang Anda pilih bergantung pada implementasi aplikasi Anda. Dalam contoh ini, trek metadata diatur ke PlatformPresented saat diaktifkan. Untuk trek berbasis teks, ini berarti bahwa sistem akan secara otomatis menampilkan isyarat teks di trek. Saat tombol pengalih dinonaktifkan, mode presentasi diatur ke Dinonaktifkan, yang berarti bahwa tidak ada teks yang ditampilkan dan tidak ada peristiwa istiadat yang dinaikkan. Peristiwa isika dibahas nanti di artikel ini.

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

Saat memproses trek metadata, Anda dapat mengakses set isdia dalam trek dengan mengakses properti Istiadat atau ActiveCues. Anda dapat melakukan ini untuk memperbarui UI Anda untuk menampilkan lokasi isjinasi untuk item media.

Menangani codec yang tidak didukung dan kesalahan yang tidak diketahui saat membuka item media

Dimulai dengan Windows 10, versi 1607, Anda dapat memeriksa apakah codec yang diperlukan untuk memutar item media didukung atau didukung sebagian pada perangkat tempat aplikasi Anda berjalan. Di penanganan aktivitas untuk peristiwa yang diubah trek MediaPlaybackItem, seperti AudioTracksChanged, pertama-tama periksa untuk melihat apakah perubahan trek adalah penyisipan trek baru. Jika demikian, Anda bisa mendapatkan referensi ke trek yang disisipkan dengan menggunakan indeks yang diteruskan dalam parameter IVectorChangedEventArgs.Index dengan koleksi trek parameter MediaPlaybackItem yang sesuai, seperti koleksi AudioTracks.

Setelah Anda memiliki referensi ke trek yang disisipkan, periksa DecoderStatus properti SupportInfo trek. Jika nilainya FullySupported, maka codec yang sesuai diperlukan untuk memutar kembali trek ada di perangkat. Jika nilai terdegradasi, trek dapat dimainkan oleh sistem, tetapi pemutaran akan diturunkan dalam beberapa cara. Misalnya, trek audio 5.1 dapat diputar kembali sebagai stereo 2 saluran sebagai gantinya. Jika demikian, Anda mungkin ingin memperbarui UI untuk memberi tahu pengguna tentang degradasi. Jika nilainya adalah UnsupportedSubtype atau UnsupportedEncoderProperties, maka trek tidak dapat diputar sama sekali dengan codec saat ini di perangkat. Anda mungkin ingin memperingatkan pengguna dan melewati pemutaran item atau menerapkan UI untuk memungkinkan pengguna mengunduh codec yang benar. Metode GetEncodingProperties trek dapat digunakan untuk menentukan codec yang diperlukan untuk pemutaran.

Terakhir, Anda dapat mendaftar untuk acara OpenFailed trek, yang akan dinaikkan jika trek didukung pada perangkat tetapi gagal dibuka karena kesalahan yang tidak diketahui dalam alur.

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

}

Di penanganan aktivitas OpenFailed, Anda dapat memeriksa untuk melihat apakah status MediaSource tidak diketahui, dan jika demikian, Anda dapat secara terprogram memilih trek lain untuk diputar, memungkinkan pengguna memilih trek yang berbeda, atau meninggalkan pemutaran.

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

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

Mengatur properti tampilan yang digunakan oleh Kontrol Transportasi Media Sistem

Dimulai dengan Windows 10, versi 1607, media yang diputar di MediaPlayer secara otomatis diintegrasikan ke dalam System Media Transport Controls (SMTC) secara default. Anda dapat menentukan metadata yang akan ditampilkan oleh SMTC dengan memperbarui properti tampilan untuk MediaPlaybackItem. Dapatkan objek yang mewakili properti tampilan untuk item dengan memanggil GetDisplayProperties. Atur apakah item pemutaran adalah musik atau video dengan mengatur properti Tipe. Kemudian, atur properti VideoProperties atau MusicProperties objek. Panggil ApplyDisplayProperties untuk memperbarui properti item ke nilai yang Anda berikan. Biasanya, aplikasi akan mengambil nilai tampilan secara dinamis dari layanan web, tetapi contoh berikut mengilustrasikan proses ini dengan nilai yang dikodekan secara permanen.

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

Menambahkan teks berwaktu eksternal dengan TimedTextSource

Untuk beberapa skenario, Anda mungkin memiliki file eksternal yang berisi teks berwaktu yang terkait dengan item media, seperti file terpisah yang berisi subtitel untuk lokal yang berbeda. Gunakan kelas TimedTextSource untuk memuat file teks berwaktu eksternal dari aliran atau URI.

Contoh ini menggunakan koleksi Kamus untuk menyimpan daftar sumber teks berwaktu untuk item media menggunakan URI sumber dan objek TimedTextSource sebagai pasangan kunci/nilai untuk mengidentifikasi trek setelah diselesaikan.

Dictionary<TimedTextSource, Uri> timedTextSourceMap;

Buat TimedTextSource baru untuk setiap file teks berwaktu eksternal dengan memanggil CreateFromUri. Tambahkan entri ke Kamus untuk sumber teks berwaktif. Tambahkan handler untuk peristiwa TimedTextSource.Resolved untuk menangani apakah item gagal dimuat atau untuk mengatur properti tambahan setelah item berhasil dimuat.

Daftarkan semua objek TimedTextSource Anda dengan MediaSource dengan menambahkannya ke koleksi ExternalTimedTextSources. Perhatikan bahwa sumber teks berwaktif eksternal ditambahkan ke MediaSource secara langsung dan bukan MediaPlaybackItem yang dibuat dari sumbernya. Untuk memperbarui UI Anda untuk mencerminkan trek teks eksternal, daftarkan dan tangani peristiwa TimedMetadataTracksChanged seperti yang dijelaskan sebelumnya dalam artikel ini.

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

Di handler untuk peristiwa TimedTextSource.Resolved, periksa properti Kesalahan TimedTextSourceResolveResultEventArgs yang diteruskan ke handler untuk menentukan apakah terjadi kesalahan saat mencoba memuat data teks berwaktu. Jika item berhasil diselesaikan, Anda dapat menggunakan handler ini untuk memperbarui properti tambahan dari trek yang diselesaikan. Contoh ini menambahkan label untuk setiap trek berdasarkan URI yang sebelumnya disimpan dalam Kamus.

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

Untuk daftar format teks berwakti yang didukung di Windows, lihat Codec yang didukung.

Menambahkan trek metadata tambahan

Anda dapat membuat trek metadata kustom secara dinamis dalam kode dan mengaitkannya dengan sumber media. Trek yang Anda buat dapat berisi teks subtitel atau keterangan, atau dapat berisi data aplikasi milik Anda.

Buat TimedMetadataTrack baru dengan memanggil konstruktor dan menentukan ID, pengidentifikasi bahasa, dan nilai dari enumerasi TimedMetadataKind. Daftarkan handler untuk peristiwa CueEntered dan CueExited. Peristiwa ini dimunculkan ketika waktu mulai untuk istime integrasi telah tercapai dan ketika durasi untuk isnggah telah kedaluwarsa, masing-masing.

Buat objek isian baru, yang sesuai untuk jenis trek metadata yang Anda buat, dan atur ID, waktu mulai, dan durasi untuk trek. Contoh ini membuat trek data, sehingga sekumpulan objek DataCue dihasilkan dan buffer yang berisi data khusus aplikasi disediakan untuk setiap iseng. Untuk mendaftarkan trek baru, tambahkan ke koleksi ExternalTimedMetadataTracks dari objek MediaSource .

Dimulai dengan Windows 10, versi 1703, properti DataCue.Properties mengekspos PropertySet yang dapat Anda gunakan untuk menyimpan properti kustom dalam pasangan kunci/data yang dapat diambil dalam peristiwa CueEntered dan CueExited.

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

Peristiwa CueEntered dimunculkan ketika waktu mulai iseng telah tercapai selama trek terkait memiliki mode presentasi ApplicationPresented, Hidden, atau PlatformPresented. Peristiwa isika tidak dinaikkan untuk trek metadata saat mode presentasi untuk trek dinonaktifkan. Contoh ini hanya menghasilkan data kustom yang terkait dengan iseng ke jendela debug.

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

Contoh ini menambahkan trek teks kustom dengan menentukan TimedMetadataKind.Caption saat membuat trek dan menggunakan objek TimedTextCue untuk menambahkan isjin ke trek.

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

Memutar daftar item media dengan MediaPlaybackList

MediaPlaybackList memungkinkan Anda membuat daftar putar item media, yang diwakili oleh objek MediaPlaybackItem.

Item Catatan dalam MediaPlaybackList dirender menggunakan pemutaran tanpa celah. Sistem akan menggunakan metadata yang disediakan dalam file yang dikodekan MP3 atau AAC untuk menentukan kompensasi penundaan atau pengisian yang diperlukan untuk pemutaran tanpa celah. Jika file yang dikodekan MP3 atau AAC tidak menyediakan metadata ini, maka sistem menentukan penundaan atau padding secara heuristik. Untuk format lossless, seperti PCM, FLAC, atau ALAC, sistem tidak mengambil tindakan karena encoder ini tidak memperkenalkan penundaan atau padding.

Untuk memulai, deklarasikan variabel untuk menyimpan MediaPlaybackList Anda.

MediaPlaybackList _mediaPlaybackList;

Buat MediaPlaybackItem untuk setiap item media yang ingin Anda tambahkan ke daftar Anda menggunakan prosedur yang sama yang dijelaskan sebelumnya dalam artikel ini. Inisialisasi objek MediaPlaybackList Anda dan tambahkan item pemutaran media ke dalamnya. Daftarkan handler untuk peristiwa CurrentItemChanged. Kejadian ini memungkinkan Anda memperbarui UI untuk mencerminkan item media yang sedang diputar. Anda juga dapat mendaftar untuk peristiwa ItemOpened , yang dimunculkan ketika item dalam daftar berhasil dibuka, dan peristiwa ItemFailed , yang dimunculkan ketika item dalam daftar tidak dapat dibuka.

Dimulai dengan Windows 10, versi 1703, Anda dapat menentukan jumlah maksimum objek MediaPlaybackItem di MediaPlaybackList yang akan dibuka sistem setelah dimainkan dengan mengatur properti MaxPlayedItemsToKeepOpen . Saat MediaPlaybackItem tetap terbuka, pemutaran item dapat dimulai secara instan saat pengguna beralih ke item tersebut karena item tidak perlu dimuat ulang. Tetapi menjaga item tetap terbuka juga meningkatkan konsumsi memori aplikasi Anda, jadi Anda harus mempertimbangkan keseimbangan antara responsivitas dan penggunaan memori saat mengatur nilai ini.

Untuk mengaktifkan pemutaran daftar Anda, atur sumber pemutaran MediaPlayer ke MediaPlaybackList Anda.

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

Di penanganan aktivitas CurrentItemChanged, perbarui UI Anda untuk mencerminkan item yang sedang diputar, yang dapat diambil menggunakan properti NewItem dari objek CurrentMediaPlaybackItemChangedEventArgs yang diteruskan ke dalam peristiwa. Ingatlah bahwa jika Anda memperbarui UI dari peristiwa ini, Anda harus melakukannya dalam panggilan ke CoreDispatcher.RunAsync sehingga pembaruan dilakukan pada utas UI.

Dimulai dengan Windows 10, versi 1703, Anda dapat memeriksa properti CurrentMediaPlaybackItemChangedEventArgs.Reason untuk mendapatkan nilai yang menunjukkan alasan item diubah, seperti item peralihan aplikasi secara terprogram, item yang sebelumnya diputar mencapai akhir, atau kesalahan yang terjadi.

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

Panggil MovePrevious atau MoveNext untuk menyebabkan pemutar media memutar item sebelumnya atau berikutnya di MediaPlaybackList Anda.

private void prevButton_Click(object sender, RoutedEventArgs e) =>  _mediaPlaybackList.MovePrevious();
private void nextButton_Click(object sender, RoutedEventArgs e) => _mediaPlaybackList.MoveNext();

Atur properti ShuffleEnabled untuk menentukan apakah pemutar media harus memutar item dalam daftar Anda dalam urutan acak.

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

Atur properti AutoRepeatEnabled untuk menentukan apakah pemutar media harus mengulang pemutaran daftar Anda.

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

Menangani kegagalan item media dalam daftar pemutaran

Peristiwa ItemFailed dimunculkan ketika item dalam daftar gagal dibuka. Properti ErrorCode dari objek MediaPlaybackItemError yang diteruskan ke handler menghitung penyebab spesifik kegagalan jika memungkinkan, termasuk kesalahan jaringan, kesalahan decoding, atau kesalahan enkripsi.

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

Menonaktifkan pemutaran item dalam daftar pemutaran

Dimulai dengan Windows 10, versi 1703, Anda dapat menonaktifkan pemutaran satu atau beberapa item di MediaPlaybackItemList dengan mengatur properti IsDisabledInPlaybackList dari MediaPlaybackItem ke false.

Skenario umum untuk fitur ini adalah untuk aplikasi yang memutar musik yang dialirkan dari internet. Aplikasi dapat mendengarkan perubahan dalam status koneksi jaringan perangkat dan menonaktifkan pemutaran item yang tidak sepenuhnya diunduh. Dalam contoh berikut, handler terdaftar untuk peristiwa NetworkInformation.NetworkStatusChanged .

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

Di handler untuk NetworkStatusChanged, periksa untuk melihat apakah GetInternet Koneksi ionProfile mengembalikan null, yang menunjukkan bahwa jaringan tidak tersambung. Jika demikian, ulangi semua item dalam daftar pemutaran, dan jika TotalDownloadProgress untuk item kurang dari 1, yang berarti bahwa item belum sepenuhnya diunduh, nonaktifkan item. Jika koneksi jaringan diaktifkan, ulangi semua item dalam daftar pemutaran dan aktifkan setiap item.

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

Tangguhkan pengikatan konten media untuk item dalam daftar pemutaran dengan menggunakan MediaBinder

Dalam contoh sebelumnya, MediaSource dibuat dari file, URL, atau streaming, setelah itu MediaPlaybackItem dibuat dan ditambahkan ke MediaPlaybackList. Untuk beberapa skenario, seperti jika pengguna ditagih untuk melihat konten, Anda mungkin ingin menunda pengambilan konten MediaSource sampai item dalam daftar pemutaran siap untuk benar-benar diputar. Untuk menerapkan skenario ini, buat instans kelas MediaBinder . Atur properti Token ke string yang ditentukan aplikasi yang mengidentifikasi konten yang ingin Anda tunda pengambilannya lalu daftarkan handler untuk peristiwa Pengikatan. Selanjutnya, buat MediaSource dari Binder dengan memanggil MediaSource.CreateFromMediaBinder. Kemudian, buat MediaPlaybackItem dari MediaSource dan tambahkan ke daftar pemutaran seperti biasa.

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

Ketika sistem menentukan bahwa konten yang terkait dengan MediaBinder perlu diambil, sistem akan menaikkan peristiwa Pengikatan . Dalam handler untuk peristiwa ini, Anda dapat mengambil instans MediaBinder dari MediaBindingEventArgs yang diteruskan ke peristiwa tersebut. Ambil string yang Anda tentukan untuk properti Token dan gunakan untuk menentukan konten apa yang harus diambil. MediaBindingEventArgs menyediakan metode untuk mengatur konten terikat dalam beberapa representasi yang berbeda, termasuk SetStorageFile, SetStream, SetStreamReference, dan 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();
}

Perhatikan bahwa jika Anda melakukan operasi asinkron, seperti permintaan web, di pengikatan penanganan aktivitas, Anda harus memanggil metode MediaBindingEventArgs.GetDeferral untuk menginstruksikan sistem menunggu operasi Anda selesai sebelum melanjutkan. Panggil Deferral.Complete setelah operasi Anda selesai untuk menginstruksikan sistem untuk melanjutkan.

Dimulai dengan Windows 10, versi 1703, Anda dapat menyediakan AdaptiveMediaSource sebagai konten terikat dengan memanggil SetAdaptiveMediaSource. Untuk informasi selengkapnya tentang menggunakan streaming adaptif di aplikasi Anda, lihat Streaming adaptif.