Cet article vous montre comment utiliser MediaProcessingTrigger et une tâche en arrière-plan pour traiter des fichiers multimédias en arrière-plan.
L’exemple d’application décrit dans cet article permet à l’utilisateur de sélectionner un fichier multimédia d’entrée à transcoder et de spécifier un fichier de sortie pour le résultat de transcodage. Ensuite, une tâche en arrière-plan est lancée pour effectuer l’opération de transcodage. Outre le transcodage, MediaProcessingTrigger est destiné à prendre en charge différents scénarios de traitement multimédia, notamment le rendu de compositions multimédias sur disque et le chargement de fichiers multimédias traités une fois le traitement terminé.
Pour obtenir des informations plus détaillées sur les différentes fonctionnalités des applications Windows universelles utilisées dans cet exemple, voir :
- Transcoder des fichiers multimédias
- Lancement de tâches de reprise et en arrière-plan
- Vignettes, badges et notifications
Créer une tâche de traitement multimédia en arrière-plan
Pour ajouter une tâche en arrière-plan à votre solution existante dans Microsoft Visual Studio, entrez un nom pour votre composition.
- Dans le menu Fichier, sélectionnez Ajouter, puis Nouveau projet….
- Sélectionnez le type de projet Composant Windows Runtime (Universel Windows).
- Entrez un nom pour votre nouveau projet de composant. Cet exemple utilise le nom de projetMediaProcessingBackgroundTask.
- Cliquez sur OK.
Dans l’Explorateur de solutions, cliquez avec le bouton droit sur l’icône du fichier « Class1.cs » qui est créé par défaut et sélectionnez Renommer. Renommez le fichier «MediaProcessingTask.cs». Lorsque Visual Studio vous demande si vous souhaitez renommer toutes les références à cette classe, cliquez sur Oui.
Dans le fichier de classe renommé, ajoutez les directives using suivantes pour inclure ces espaces de noms dans votre projet.C#Copier
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;
Mettez à jour votre déclaration de classe pour faire en sorte que votre classe hérite de IBackgroundTask.C#Copier
public sealed class MediaProcessingTask : IBackgroundTask
{
Ajoutez les variables membres suivantes à votre classe:
- Un objet IBackgroundTaskInstance qui sera utilisé pour mettre à jour l’application au premier plan avec la progression de la tâche en arrière-plan.
- Un objet BackgroundTaskDeferral qui empêche le système d’arrêter votre tâche en arrière-plan pendant que le transcodage multimédia est exécuté en mode asynchrone.
- Un objet CancellationTokenSource qui peut être utilisé pour annuler l’opération de transcodage asynchrone.
- L’objet MediaTranscoder qui sera utilisé pour transcoder des fichiers multimédias.
C#Copier
IBackgroundTaskInstance backgroundTaskInstance;
BackgroundTaskDeferral deferral;
CancellationTokenSource cancelTokenSource = new CancellationTokenSource();
MediaTranscoder transcoder;
Le système appelle la méthode Run d’une tâche en arrière-plan lorsque la tâche est lancée. Définissez l’objet IBackgroundTasktransmis dans la méthode sur la variable membre correspondante. Enregistrez un gestionnaire de l’événement Canceled, qui sera déclenché si le système a besoin d’arrêter la tâche en arrière-plan. Ensuite, affectez à la propriété Progress la valeur zéro.
Appelez ensuite la méthode GetDeferral de l’objet de tâche en arrière-plan pour obtenir un report. Cela indique au système de ne pas arrêter votre tâche car vous exécutez des opérations asynchrones.
Ensuite, appelez la méthode d’assistance TranscodeFileAsync qui est définie dans la section suivante. Si l’opération se termine correctement, une méthode d’assistance est appelée pour lancer une notification toast afin d’avertir l’utilisateur que le transcodage est terminé.
À la fin de la méthode Run, appelez Complete sur l’objet de report pour indiquer au système que votre tâche en arrière-plan est terminée et peut être fermée.C#Copier
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();
}
Dans la méthode d’assistance TranscodeFileAsync, les noms de fichiers des fichiers d’entrée et de sortie pour les opérations de transcodage sont récupérés à partir de l’objet LocalSettings de votre application. Ces valeurs seront définies par votre application au premier plan. Créez un objet StorageFile pour les fichiers d’entrée et de sortie, puis créez un profil d’encodage à utiliser pour le transcodage.
Appelez PrepareFileTranscodeAsync en passant dans le fichier d’entrée, le fichier de sortie et le profil d’encodage. L’objetPrepareTranscodeResult renvoyé à partir de cet appel vous permet de savoir si le transcodage peut être effectué. Si la propriétéCanTranscode est true, appelez TranscodeAsync pour effectuer l’opération de transcodage.
La méthode AsTask vous permet de suivre la progression de l’opération asynchrone ou de l’annuler. Créez un objet Progress en spécifiant les unités de progression souhaitées et le nom de la méthode qui sera appelée pour vous informer de la progression actuelle de la tâche. Passez l’objet Progress dans la méthode AsTask avec le jeton d’annulation qui vous permet d’annuler la tâche.C#Copier
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;
}
}
Dans la méthode que vous avez utilisée pour créer l’objet de progression à l’étape précédente, Progress, définissez la progression de l’instance de tâche en arrière-plan. Cela transmettra la progression à l’application au premier plan, si celle-ci est en cours d’exécution.C#Copier
void TranscodeProgress(double percent)
{
Debug.WriteLine("Transcoding progress: " + percent.ToString().Split('.')[0] + "%");
backgroundTaskInstance.Progress = (uint)percent;
}
La méthode d’assistance SendToastNotification crée une notification toast en obtenant un modèle de document XML pour un toast uniquement constitué de texte. L’élément de texte du XML de toast est défini, puis un objet ToastNotification est créé à partir du document XML. Enfin, le toast est affiché à l’utilisateur en appelant ToastNotifier.Show.C#Copier
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);
}
Dans le gestionnaire de l’événement Canceled, qui est appelé lorsque le système annule la tâche en arrière-plan, vous pouvez consigner l’erreur à des fins de télémétrie.C#Copier
private void OnCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
{
Debug.WriteLine("Background " + sender.Task.Name + " Cancel Requested..." + reason.ToString());
}
Enregistrer et lancer la tâche en arrière-plan
Avant de pouvoir lancer la tâche en arrière-plan à partir de votre application au premier plan, vous devez mettre à jour le fichier Package.appmanifest de votre application au premier plan pour indiquer au système que votre application utilise une tâche en arrière-plan.
- Dans l’Explorateur de solutions, double-cliquez sur l’icône du fichier Package.appmanifest pour ouvrir l’éditeur du manifeste.
- Sélectionnez l’onglet Déclarations.
- Dans Déclarations disponibles, sélectionnez Tâches en arrière-plan, puis cliquez sur Ajouter.
- Sous Déclarations prises en charge, vérifiez que l’élément Tâches en arrière-plan est sélectionné. Sous Propriétés, cochez la case Traitement multimédia.
- Dans la zone de texte Point d’entrée, spécifiez l’espace de noms et le nom de classe de votre test en arrière-plan, séparés par un point. Pour cet exemple, l’entrée est:
csharp MediaProcessingBackgroundTask.MediaProcessingTask
Ensuite, vous devez ajouter une référence à votre tâche en arrière-plan à votre application au premier plan. - Dans l’Explorateur de solutions, sous votre projet d’application au premier plan, cliquez avec le bouton droit sur le dossier Références et sélectionnez Ajouter une référence….
- Développez le nœud Projets et sélectionnez Solution.
- Cochez la case en regard de votre projet de tâche en arrière-plan, puis cliquez sur OK.
Le reste du code dans cet exemple doit être ajouté à votre application au premier plan. Tout d’abord, vous devez ajouter les espaces de noms suivants à votre projet.C#Copier
using Windows.ApplicationModel.Background;
using Windows.Storage;
Ensuite, ajoutez les variables membres suivantes qui sont nécessaires pour enregistrer la tâche en arrière-plan.C#Copier
MediaProcessingTrigger mediaProcessingTrigger;
string backgroundTaskBuilderName = "TranscodingBackgroundTask";
BackgroundTaskRegistration taskRegistration;
La méthode d’assistance PickFilesToTranscode utilise des objets FileOpenPicker et FileSavePicker pour ouvrir les fichiers d’entrée et de sortie pour le transcodage. L’utilisateur peut sélectionner des fichiers situés à un emplacement auquel votre application n’a pas accès. Pour vous assurer que votre tâche en arrière-plan peut ouvrir les fichiers, ajoutez-les à l’objet FutureAccessList de votre application.
Enfin, définissez les entrées pour les noms de fichiers d’entrée et de sortie dans l’objet LocalSettings de votre application. La tâche en arrière-plan récupère les noms de fichiers à partir de cet emplacement.C#Copier
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;
}
Pour enregistrer la tâche en arrière-plan, créez des objets MediaProcessingTrigger et BackgroundTaskBuilder. Définissez le nom du générateur de tâches en arrière-plan afin de pouvoir l’identifier ultérieurement. Définissez TaskEntryPoint sur l’espace de noms et la chaîne de noms de classe utilisés dans le fichier manifeste. Affectez la propriété Trigger à l’instance MediaProcessingTrigger.
Avant d’enregistrer la tâche, assurez-vous que vous annulez l’enregistrement de toutes les tâches précédemment enregistrées en parcourant la collection AllTasks et en appelant Unregister sur toutes les tâches portant le nom que vous avez spécifié dans la propriété BackgroundTaskBuilder.Name.
Enregistrez la tâche en arrière-plan en appelant Register. Enregistrez des gestionnaires des événements Completed et Progress.C#Copier
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;
}
Une application standard s’inscrire leur tâche en arrière-plan lorsque l’application est lancée initialement, comme dans l’événement OnNavigatedTo .
Lancez la tâche en arrière-plan en appelant la méthode RequestAsync de l’objet MediaProcessingTrigger. L’objet MediaProcessingTriggerResult renvoyé par cette méthode vous permet de savoir si la tâche en arrière-plan a été démarrée. Si ce n’est pas le cas, il vous permet de savoir pourquoi la tâche en arrière-plan n’a pas été lancée.C#Copier
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);
}
}
}
Une application standard lancera la tâche en arrière-plan en réponse à une interaction utilisateur, comme dans l’événement Clickd’un contrôle de l’interface utilisateur.
Le gestionnaire d’événements OnProgress est appelé lorsque la tâche en arrière-plan met à jour la progression de l’opération. Vous pouvez utiliser cette opportunité pour mettre à jour votre interface utilisateur avec les informations de progression.C#Copier
private void OnProgress(IBackgroundTaskRegistration task, BackgroundTaskProgressEventArgs args)
{
string progress = "Progress: " + args.Progress + "%";
Debug.WriteLine(progress);
}
Le gestionnaire d’événements OnCompleted est appelé lorsque l’exécution de la tâche en arrière-plan est terminée. Il s’agit d’une autre opportunité de mettre à jour votre interface utilisateur pour fournir des informations d’état à l’utilisateur.C#Copier
private void OnCompleted(IBackgroundTaskRegistration task, BackgroundTaskCompletedEventArgs args)
{
Debug.WriteLine(" background task complete");
}