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 Sourire

Ces billets pourraient aussi vous intéresser

Vous nous direz ?!

Commentaires

comments powered by Disqus