Utilisation des notification endpoints avec Windows Azure Media Services
Une nouvelle version du SDK .NET pour Windows Azure Media Services a été rendue disponible par Microsoft il y a quelques jours. Celle-ci est téléchargeable via la console NuGet (http://nuget.org/packages/windowsazure.mediaservices). L’une des principales nouveautés de cette version est la possibilité d’être notifié du changement d’état des jobs media services, au travers de file d’attente Azure Storage.
En effet, dans les versions précédentes du SDK, il était assez fastidieux de faire du suivi de tâches d’encodage de manière optimisée (et scalable, lors d’utilisation de worker rôle Azure notamment) puisqu’il fallait absolument maintenir des tables d’états et aller requêter à intervalles réguliers, via une instance de CloudMediaContext, pour récupérer l’état des différents jobs. Avec la nouvelle version du SDK, la tâche est beaucoup plus simple, puisqu’il est désormais possible d’associer une file d’attente Azure Storage à un job, et de requêter directement cette file en laissant à Windows Azure Media Services la gestion de l’envoie des différents messages dans celle-ci.
Pour pouvoir utiliser les notification endpoints, il est tout d’abord nécessaire de créer une CloudQueue à partir de votre compte de stockage (celui utilisé par votre service de médias) :
//création du CloudStorageAccount à partir de la clé privé CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(StorageConnectionString); //création d'un client CloudQueueClient à partir de la chaîne de connexion CloudQueueClient cloudQueueClient = cloudStorageAccount.CreateCloudQueueClient(); //récupération d'une référence vers la CloudQueue à utiliser CloudQueue notificationsQueue = cloudQueueClient.GetQueueReference(NotificationQueuePath); //création de la file si elle n'existe pas if (!notificationsQueue.Exists()) { notificationsQueue.Create(); }
Il est alors possible de créer un endpoint de notification, représenté par l’interface INotificationEndpoint, à partir du CloudMediaContext :
//création du CloudMediaContext CloudMediaContext mediaContext = new CloudMediaContext("<mediaservicename>", "<mediaservicekey>"); //création du endpoint INotificationEndPoint notificationEndpoint = mediaContext.NotificationEndPoints .Create("notificationendpoint", NotificationEndPointType.AzureQueue, NotificationQueuePath);
La création du ou des jobs d’encodage se fait exactement comme avec les anciennes versions du SDK :
//création d'un asset IAsset asset = mediaContext.Assets.Create("Wildlife HD", AssetCreationOptions.None); //création d'un fichier associé à l'asset string fileName = System.IO.Path.GetFileName(VideoTestPath); IAssetFile assetFile = asset.AssetFiles.Create(fileName); //envoie de l'asset dans Azure assetFile.Upload(VideoTestPath); //création du job IJob mediaServiceJob = mediaContext.Jobs.Create("Wildlife in HD Adaptive Streaming"); //récupération du Windows Azure Media Encoder IMediaProcessor mediaProcessor = GetLatestsAzureMediaEncoder(mediaContext); //Création d'une tâche d'encodage d'un MP4 multi-débit ITask multibitrateTask = mediaServiceJob.Tasks.AddNew("Multibitrate MP4 encoding", mediaProcessor, "H264 Adaptive Bitrate MP4 Set 720p", TaskOptions.None); //ajout de l'asset en input de la tâche multibitrateTask.InputAssets.Add(asset); //création de l'asset de sortie multibitrateTask.OutputAssets.AddNew("Wildlife HD Output", AssetCreationOptions.None);
Avant de soumettre le job pour qu’il soit exécuté par Windows Azure Media Services, il va être nécessaire d’associer ce dernier au endpoint de notifications qui a été créé plus haut. Pour cela, une nouvelle propriété JobNotificationsSubscriptions est disponible sur l’interface IJob :
mediaServiceJob.JobNotificationSubscriptions.AddNew(NotificationJobState.FinalStatesOnly, notificationEndpoint);
Il est maintenant possible de soumettre le job :
mediaServiceJob.Submit();
Le tour est joué, plus besoin de récupérer l’id du job qui a été créé, de le stocker dans une base externe (par exemple) pour être en capacité de requêter son état. Il suffit d’interroger la CloudQueue associée au notification endpoint :
while (continuePull) { Thread.Sleep(5000);//sleep for 5 sec //récupération du prochain message CloudQueueMessage message = notificationsQueue.GetMessage(); if (message == null)//if null, continue continue; }
Windows Azure Media Services envoie des messages sous formes de JSON dans la file. Ces messages possèdent le prototype suivant :
public class EncodingJobMessage { public String MessageVersion { get; set; } public String EventType { get; set; } public String ETag { get; set; } public String TimeStamp { get; set; } public IDictionary<string, object> Properties { get; set; } }
La propriété EventType peut prendre deux valeurs :
- JobStateChange : indique que le message correspond à un changement d’état du job
- NotificationEndpointRegistration : indique qu’un endpoint de notification a été enregistré ou supprimé
Le message possède également un certain nombre de propriétés représentées par le dictionnaire Properties. Il est possible de récupérer les informations suivantes :
- JobId : l’id du job
- NewState : le nouvel état du job
- OldState : l’ancien état du job
- NotificationEndpointId : l’id du endpoint de notification
- State : l’état du endpoint (Registered ou Unregistered)
Pour déserialiser le message, il suffit d’utiliser le DataContractJsonSerializer comme le montre le code qui suit :
//récupération du message sous forme de byte array using (MemoryStream ms = new MemoryStream(message.AsBytes)) { //déserialisation DataContractJsonSerializerSettings jsonSerializerSettings = new DataContractJsonSerializerSettings(); jsonSerializerSettings.UseSimpleDictionaryFormat = true; DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(EncodingJobMessage), jsonSerializerSettings); EncodingJobMessage jobMessage = (EncodingJobMessage)serializer.ReadObject(ms); //si le message indique un changement d'état if (jobMessage.EventType == "JobStateChange") { //on récupère le nouvel et l'ancien état if (jobMessage.Properties.Any(p => p.Key == "OldState") && jobMessage.Properties.Any(p => p.Key == "NewState")) { string oldJobState = jobMessage.Properties.First(p => p.Key == "OldState").Value.ToString(); string newJobState = jobMessage.Properties.First(p => p.Key == "NewState").Value.ToString(); Console.WriteLine("le job a changé d'état de {0} vers {1}", oldJobState, newJobState); } } }
Et voilà ! Un mécanisme simple pour suivre l’état des jobs en cours dans Windows Azure Media Services. Cette fonctionnalité manquait vraiment ! A voir si les prochaines release permettront de s’appuyer sur des queue du service bus Azure ou même des topics !
A bientôt,
Julien
Commentaires