Memproses file media di latar belakang

Artikel ini menunjukkan kepada Anda cara menggunakan MediaProcessingTrigger dan tugas latar belakang untuk memproses file media di latar belakang.

Contoh aplikasi yang dijelaskan dalam artikel ini memungkinkan pengguna untuk memilih file media input untuk mentranskode dan menentukan file output untuk hasil transcoding. Kemudian, tugas latar belakang diluncurkan untuk melakukan operasi transcoding. MediaProcessingTrigger dimaksudkan untuk mendukung banyak skenario pemrosesan media yang berbeda selain transcoding, termasuk rendering komposisi media ke disk dan mengunggah file media yang diproses setelah pemrosesan selesai.

Untuk informasi lebih rinci tentang berbagai fitur aplikasi Universal Windows yang digunakan dalam sampel ini, lihat:

Membuat tugas latar belakang pemrosesan media

Untuk menambahkan tugas latar belakang ke solusi yang ada di Microsoft Visual Studio, Masukkan nama untuk comp Anda

  1. Dari menu File, pilih Tambahkan lalu Project Baru....
  2. Pilih jenis proyek Windows Runtime Component (Universal Windows).
  3. Masukkan nama untuk proyek komponen baru Anda. Contoh ini menggunakan nama proyek MediaProcessingBackgroundTask.
  4. Klik OK.

Di Penjelajah Solusi, klik kanan ikon untuk file "Class1.cs" yang dibuat secara default dan pilih Ganti Nama. Ganti nama file menjadi "MediaProcessingTask.cs". Saat Visual Studio bertanya apakah Anda ingin mengganti nama semua referensi ke kelas ini, klik Ya.

Dalam file kelas yang diganti namanya, tambahkan yang berikut menggunakan petunjuk untuk menyertakan ruang nama ini dalam proyek Anda.

using Windows.ApplicationModel.Background;
using Windows.Storage;
using Windows.UI.Notifications;
using Windows.Data.Xml.Dom;
using Windows.Media.MediaProperties;
using Windows.Media.Transcoding;
using System.Threading;

Perbarui deklarasi kelas Anda untuk membuat kelas Anda mewarisi dari IBackgroundTask.

public sealed class MediaProcessingTask : IBackgroundTask
{

Tambahkan variabel anggota berikut ke kelas Anda:

  • IBackgroundTaskInstance yang akan digunakan untuk memperbarui aplikasi latar depan dengan kemajuan tugas latar belakang.
  • BackgroundTaskDeferral yang membuat sistem tidak mematikan tugas latar belakang Anda saat transcoding media dilakukan secara asinkron.
  • Objek CancellationTokenSource yang dapat digunakan untuk membatalkan operasi transcoding asinkron.
  • Objek MediaTranscoder yang akan digunakan untuk mentranskode file media.
IBackgroundTaskInstance backgroundTaskInstance;
BackgroundTaskDeferral deferral;
CancellationTokenSource cancelTokenSource = new CancellationTokenSource();
MediaTranscoder transcoder;

Sistem memanggil metode Jalankan tugas latar belakang saat tugas diluncurkan. Atur objek IBackgroundTask diteruskan ke metode ke variabel anggota yang sesuai. Daftarkan penangan untuk acara yang Dibatalkan , yang akan dinaikkan jika sistem perlu mematikan tugas latar belakang. Kemudian, atur properti Progress ke nol.

Selanjutnya, panggil metode GetDeferral objek tugas latar belakang untuk mendapatkan penangguhan. Ini memberi tahu sistem untuk tidak mematikan tugas Anda karena Anda melakukan operasi asinkron.

Selanjutnya, panggil metode pembantu TranscodeFileAsync, yang didefinisikan di bagian berikutnya. Jika itu berhasil diselesaikan, metode pembantu dipanggil untuk meluncurkan pemberitahuan roti panggang untuk memberi tahu pengguna bahwa transcoding selesai.

Di akhir metode Run , panggil Complete pada objek penangguhan untuk memberi tahu sistem bahwa tugas latar belakang Anda selesai dan dapat dihentikan.

public async void Run(IBackgroundTaskInstance taskInstance)
{
    Debug.WriteLine("In background task Run method");

    backgroundTaskInstance = taskInstance;
    taskInstance.Canceled += new BackgroundTaskCanceledEventHandler(OnCanceled);
    taskInstance.Progress = 0;

    deferral = taskInstance.GetDeferral();
    Debug.WriteLine("Background " + taskInstance.Task.Name + " is called @ " + (DateTime.Now).ToString());

    try
    {
        await TranscodeFileAsync();
        ApplicationData.Current.LocalSettings.Values["TranscodingStatus"] = "Completed Successfully";
        SendToastNotification("File transcoding complete.");

    }
    catch (Exception e)
    {
        Debug.WriteLine("Exception type: {0}", e.ToString());
        ApplicationData.Current.LocalSettings.Values["TranscodingStatus"] = "Error ocurred: " + e.ToString();
    }


    deferral.Complete();
}

Dalam metode pembantu TranscodeFileAsync , nama file untuk file input dan output untuk operasi transcoding diambil dari LocalSettings untuk aplikasi Anda. Nilai-nilai ini akan ditetapkan oleh aplikasi latar depan Anda. Buat objek StorageFile untuk file input dan output dan kemudian buat profil pengkodean untuk digunakan untuk transcoding.

Panggil PrepareFileTranscodeAsync, meneruskan file input, file output, dan profil pengkodean. Objek PrepareTranscodeResult yang dikembalikan dari panggilan ini memberi tahu Anda jika transcoding dapat dilakukan. Jika properti CanTranscode benar, panggil TranscodeAsync untuk melakukan operasi transcoding.

Metode AsTask memungkinkan Anda untuk melacak kemajuan operasi asinkron atau membatalkannya. Buat objek Kemajuan baru, tentukan unit kemajuan yang Anda inginkan dan nama metode yang akan dipanggil untuk memberi tahu Anda tentang kemajuan tugas saat ini. Berikan objek Progress ke dalam metode AsTask bersama dengan token pembatalan yang memungkinkan Anda membatalkan tugas.

  private async Task TranscodeFileAsync()
  {
      transcoder = new MediaTranscoder();

      try
      {
          var settings = ApplicationData.Current.LocalSettings;

          settings.Values["TranscodingStatus"] = "Started";

          var inputFileName = ApplicationData.Current.LocalSettings.Values["InputFileName"] as string;
          var outputFileName = ApplicationData.Current.LocalSettings.Values["OutputFileName"] as string;

          if (inputFileName == null || outputFileName == null)
          {
              return;
          }


          // retrieve the transcoding information
          var inputFile = await Windows.Storage.StorageFile.GetFileFromPathAsync(inputFileName);
          var outputFile = await Windows.Storage.StorageFile.GetFileFromPathAsync(outputFileName);

          // create video encoding profile                
          MediaEncodingProfile encodingProfile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.HD720p);

          Debug.WriteLine("PrepareFileTranscodeAsync");
          settings.Values["TranscodingStatus"] = "Preparing to transcode ";
          PrepareTranscodeResult preparedTranscodeResult = await transcoder.PrepareFileTranscodeAsync(
              inputFile, 
              outputFile, 
              encodingProfile);

          if (preparedTranscodeResult.CanTranscode)
          {
              var startTime = TimeSpan.FromMilliseconds(DateTime.Now.Millisecond);
              Debug.WriteLine("Starting transcoding @" + startTime);

              var progress = new Progress<double>(TranscodeProgress);
              settings.Values["TranscodingStatus"] = "Transcoding ";
              settings.Values["ProcessingFileName"] = inputFileName;
              await preparedTranscodeResult.TranscodeAsync().AsTask(cancelTokenSource.Token, progress);

          }
          else
          {
              Debug.WriteLine("Source content could not be transcoded.");
              Debug.WriteLine("Transcode status: " + preparedTranscodeResult.FailureReason.ToString());
              var endTime = TimeSpan.FromMilliseconds(DateTime.Now.Millisecond);
              Debug.WriteLine("End time = " + endTime);
          }
      }
      catch (Exception e)
      {
          Debug.WriteLine("Exception type: {0}", e.ToString());
          throw;
      }
  }

Dalam metode yang Anda gunakan untuk membuat objek Kemajuan pada langkah sebelumnya, Kemajuan, mengatur kemajuan instans tugas latar belakang. Ini akan meneruskan kemajuan ke aplikasi latar depan, jika sedang berjalan.

void TranscodeProgress(double percent)
{
    Debug.WriteLine("Transcoding progress:  " + percent.ToString().Split('.')[0] + "%");
    backgroundTaskInstance.Progress = (uint)percent;
}

Metode pembantu SendToastNotification membuat pemberitahuan roti panggang baru dengan mendapatkan dokumen XML template untuk roti panggang yang hanya memiliki konten teks. Elemen teks dari xml roti panggang diatur dan kemudian objek ToastNotification baru dibuat dari dokumen XML. Akhirnya, roti panggang ditampilkan kepada pengguna dengan memanggil ToastNotifier.Show.

private void SendToastNotification(string toastMessage)
{
    ToastTemplateType toastTemplate = ToastTemplateType.ToastText01;
    XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(toastTemplate);

    //Supply text content for your notification
    XmlNodeList toastTextElements = toastXml.GetElementsByTagName("text");
    toastTextElements[0].AppendChild(toastXml.CreateTextNode(toastMessage));

    //Create the toast notification based on the XML content you've specified.
    ToastNotification toast = new ToastNotification(toastXml);

    //Send your toast notification.
    ToastNotificationManager.CreateToastNotifier().Show(toast);
}

Di penangan untuk acara yang Dibatalkan , yang dipanggil ketika sistem membatalkan tugas latar belakang Anda, Anda dapat mencatat kesalahan untuk tujuan telemetri.

private void OnCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
{
    Debug.WriteLine("Background " + sender.Task.Name + " Cancel Requested..." + reason.ToString());
}

Mendaftar dan meluncurkan tugas latar belakang

Sebelum Anda dapat meluncurkan tugas latar belakang dari aplikasi latar depan Anda, Anda harus memperbarui file Package.appmanifest aplikasi latar depan Anda untuk memberi tahu sistem bahwa aplikasi Anda menggunakan tugas latar belakang.

  1. Di Penjelajah Solusi, klik dua kali ikon file Package.appmanifest untuk membuka editor manifes.
  2. Pilih tab Deklarasi.
  3. Dari Deklarasi yang Tersedia, pilih Tugas Latar Belakang dan klik Tambahkan.
  4. Di bawah Deklarasi yang Didukung pastikan item Tugas Latar Belakang dipilih. Di bawah Properti, pilih kotak centang untuk Pemrosesan Media.
  5. Dalam kotak teks Titik Masuk , tentukan ruang nama dan nama kelas untuk tes latar belakang Anda, dipisahkan oleh periode. Untuk contoh ini, entrinya adalah:
MediaProcessingBackgroundTask.MediaProcessingTask

Selanjutnya, Anda perlu menambahkan referensi ke tugas latar belakang ke aplikasi latar depan Anda.

  1. Di Penjelajah Solusi, di bawah proyek aplikasi latar depan Anda, klik kanan folder Referensi dan pilih Tambahkan Referensi ....
  2. Perluas simpul Proyek dan pilih Solusi.
  3. Centang kotak di samping proyek tugas latar belakang Anda dan klik OK.

Sisa kode dalam contoh ini harus ditambahkan ke aplikasi latar depan Anda. Pertama, Anda perlu menambahkan ruang nama berikut ke proyek Anda.

using Windows.ApplicationModel.Background;
using Windows.Storage;

Selanjutnya, tambahkan variabel anggota berikut yang diperlukan untuk mendaftarkan tugas latar belakang.

MediaProcessingTrigger mediaProcessingTrigger;
string backgroundTaskBuilderName = "TranscodingBackgroundTask";
BackgroundTaskRegistration taskRegistration;

Metode pembantu PickFilesToTranscode menggunakan FileOpenPicker dan FileSavePicker untuk membuka file input dan output untuk transcoding. Pengguna dapat memilih file di lokasi yang tidak dapat diakses oleh aplikasi Anda. Untuk memastikan tugas latar belakang Anda dapat membuka file, tambahkan ke FutureAccessList untuk aplikasi Anda.

Terakhir, atur entri untuk nama file input dan output di LocalSettings untuk aplikasi Anda. Tugas latar belakang mengambil nama file dari lokasi ini.

private async void PickFilesToTranscode()
{
    var openPicker = new Windows.Storage.Pickers.FileOpenPicker();

    openPicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.VideosLibrary;
    openPicker.FileTypeFilter.Add(".wmv");
    openPicker.FileTypeFilter.Add(".mp4");

    StorageFile source = await openPicker.PickSingleFileAsync();

    var savePicker = new Windows.Storage.Pickers.FileSavePicker();

    savePicker.SuggestedStartLocation =
        Windows.Storage.Pickers.PickerLocationId.VideosLibrary;

    savePicker.DefaultFileExtension = ".mp4";
    savePicker.SuggestedFileName = "New Video";

    savePicker.FileTypeChoices.Add("MPEG4", new string[] { ".mp4" });

    StorageFile destination = await savePicker.PickSaveFileAsync();

    if(source == null || destination == null)
    {
        return;
    }

    var storageItemAccessList = Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList;
    storageItemAccessList.Add(source);
    storageItemAccessList.Add(destination);

    ApplicationData.Current.LocalSettings.Values["InputFileName"] = source.Path;
    ApplicationData.Current.LocalSettings.Values["OutputFileName"] = destination.Path;
}

Untuk mendaftarkan tugas latar belakang, buat MediaProcessingTrigger baru dan BackgroundTaskBuilder baru. Atur nama pembuat tugas latar belakang sehingga Anda dapat mengidentifikasinya nanti. Atur TaskEntryPoint ke namespace dan string nama kelas yang sama dengan yang Anda gunakan dalam file manifes. Atur properti Pemicu ke instans MediaProcessingTrigger .

Sebelum mendaftarkan tugas, pastikan Anda membatalkan pendaftaran tugas yang terdaftar sebelumnya dengan mengulang pengumpulan AllTasks dan memanggil Unregister pada tugas apa pun yang memiliki nama yang Anda tentukan di properti BackgroundTaskBuilder.Name .

Daftarkan tugas latar belakang dengan memanggil Register. Daftarkan penangan untuk peristiwa Selesai dan Kemajuan .

private void RegisterBackgroundTask()
{
    // New a MediaProcessingTrigger
    mediaProcessingTrigger = new MediaProcessingTrigger();

    var builder = new BackgroundTaskBuilder();

    builder.Name = backgroundTaskBuilderName;
    builder.TaskEntryPoint = "MediaProcessingBackgroundTask.MediaProcessingTask";
    builder.SetTrigger(mediaProcessingTrigger);

    // unregister old ones
    foreach (var cur in BackgroundTaskRegistration.AllTasks)
    {
        if (cur.Value.Name == backgroundTaskBuilderName)
        {
            cur.Value.Unregister(true);
        }
    }

    taskRegistration = builder.Register();
    taskRegistration.Progress += new BackgroundTaskProgressEventHandler(OnProgress);
    taskRegistration.Completed += new BackgroundTaskCompletedEventHandler(OnCompleted);

    return;
}

Aplikasi yang khas akan mendaftarkan tugas latar belakang mereka ketika aplikasi awalnya diluncurkan, seperti di acara OnNavigatedTo .

Luncurkan tugas latar belakang dengan memanggil metode RequestAsync objek MediaProcessingTrigger. Objek MediaProcessingTriggerResult yang dikembalikan dengan metode ini memungkinkan Anda mengetahui apakah tugas latar belakang berhasil dimulai, dan jika tidak, memberi tahu Anda mengapa tugas latar belakang tidak diluncurkan.

private async void LaunchBackgroundTask()
{
    var success = true;

    if (mediaProcessingTrigger != null)
    {
        MediaProcessingTriggerResult activationResult;
        activationResult = await mediaProcessingTrigger.RequestAsync();

        switch (activationResult)
        {
            case MediaProcessingTriggerResult.Allowed:
                // Task starting successfully
                break;

            case MediaProcessingTriggerResult.CurrentlyRunning:
            // Already Triggered

            case MediaProcessingTriggerResult.DisabledByPolicy:
            // Disabled by system policy

            case MediaProcessingTriggerResult.UnknownError:
                // All other failures
                success = false;
                break;
        }

        if (!success)
        {
            // Unregister the media processing trigger background task
            taskRegistration.Unregister(true);
        }
    }

}

Aplikasi yang khas akan meluncurkan tugas latar belakang sebagai respons terhadap interaksi pengguna, seperti dalam peristiwa Klik kontrol UI.

Penangan peristiwa OnProgress dipanggil saat tugas latar belakang memperbarui kemajuan operasi. Anda dapat menggunakan kesempatan ini untuk memperbarui UI Anda dengan informasi kemajuan.

private void OnProgress(IBackgroundTaskRegistration task, BackgroundTaskProgressEventArgs args)
{
    string progress = "Progress: " + args.Progress + "%";
    Debug.WriteLine(progress);
}

Penangan peristiwa OnCompleted dipanggil ketika tugas latar belakang telah selesai berjalan. Ini adalah kesempatan lain untuk memperbarui UI Anda untuk memberikan informasi status kepada pengguna.

private void OnCompleted(IBackgroundTaskRegistration task, BackgroundTaskCompletedEventArgs args)
{
    Debug.WriteLine(" background task complete");
}