What is Windows Azure Media Services and how can I use them


If you follow the cloud news, you probably already know that Windows Azure Media Services was used to broadcast the 2012 London Olympics .

Let's figure out what they are and how to use them.
If you simplify it a bit, then Windows Azure Media Services is a technology of the Microsoft Media Platform , as well as our partners, which have been transferred mostly to the cloud. In other words, on the one hand, these are proven and familiar solutions, on the other hand, the ability to scale these solutions and integrate them into your own processes of encoding, broadcasting and distribution of media content.

Windows Azure Media Services provides the following services for building your own media services and applications:
  • Download content
  • recoding
  • format conversion,
  • content protection
  • broadcast on demand and
  • live broadcasting as well
  • analytics and advertising.

Or, if you present all of the above in the form of a diagram, then the architecture of Windows Azure Media Services will look as follows:
If you look closely at the diagram, you can see another great feature of Windows Azure Media Services - they can be a source of media content for almost all types of devices present Now on the market: from ordinary desktop computers to television set-top boxes or smartphones.

And, of course, this wonderful functionality is available to the developer through the REST API, which allows you to develop solutions based on Windows Azure Media Services using any familiar, convenient or, for example, standard technology organization. Developers on the .NET platform can use the Windows Azure Media Services SDK for .NET, which wraps the provided REST API in a convenient way.

So, now you have a general idea of ​​what Windows Azure Media Services is. Let's get to know them better.

Customer Service Development


Mac and PC
Now you can develop for Mac and PC using Microsoft Silverlight. After some time, the SDK for Flash client development will be available. Available SDKs for Silverlight:
Smooth Streaming Client for Silverlight
Microsoft Media Platform: Player Framework for Silverlight

Windows 8
To develop WinRT applications under Windows 8, you can develop on HTML / JS, C # or C ++ using the following SDKs:
Smooth Streaming Client SDK for WinRT Windows 8applications
Microsoft Media Platform: Player Framework for WinRT Windows 8 Applications

Windows phone
Microsoft provides an SDK for building video applications on Windows Phone.
Smooth Streaming Client for Silverlight
Microsoft Media Platform: Player Framework for Silverlight

iOS devices
For iOS devices, including the iPhone, iPod, and iPad, Microsoft ships the Smooth Streaming SDK for iOS Devices with PlayReady .
Smooth Streaming SDK for iOS Devices with PlayReady

Android devices
Microsoft partners are developing and supplying SDKs for these devices.

Xbox
Xbox supports Xbox LIVE apps with Smooth Streaming. Xbox LIVE Application Development Kit (ADK) contains:
Smooth Streaming client for Xbox LIVE ADK
Microsoft Media Platform: Player Framework for Xbox LIVE ADK

Embedded and other devices
For embedded devices, such as televisions, set-top boxes, media players, etc., that is, for devices with their own framework for developing and working with media content, you can license porting packages:
Smooth Streaming Client Porting Kit
Microsoft PlayReady Device Porting Kit

Work with the service part

To start working with Windows Azure Media Services, you must first create them in your Windows Azure management portal (it is currently in beta):
After the service status is Active, it is ready to work.


After that, if you are a .NET developer, and you already have Visual Studio 2010 SP1 installed, you must additionally install:
You are now fully prepared to develop applications using Windows Azure Media Services.

Let's create a simple application that works with Windows Azure Media Services.

Create a console application project for the .NET Framework 4 in Visual Studio. Add the following libraries to the project in the Reference:
Microsoft.WindowsAzure.MediaServices.Client.dll
\ Program Files (x86) \ Microsoft SDKs \ Windows Azure Media Services \ Services SDK \ v1.0 \

Microsoft.WindowsAzure.StorageClient.dll
\ Program Files \ Windows Azure SDK \ v1.6 \ bin \

Microsoft.Data.Edm.dll
(\ Program Files (x86) \ Microsoft WCF Data Services \ 5.0 \ bin \ .NETFramework \

Microsoft.Data.OData.dll
(\ Program Files (x86) \ Microsoft WCF Data Services \ 5.0 \ bin \ .NETFramework \

Microsoft.Data.Services.Client.dll
(\ Program Files (x86) \ Microsoft WCF Data Services \ 5.0 \ bin \ .NETFramework \

Microsoft.Data.Services.dll
(\ Program Files (x86) \ Microsoft WCF Data Services \ 5.0 \ bin \ .NETFramework \

System.Spatial.dll
(\ Program Files (x86) \ Microsoft WCF Data Services \ 5.0 \ bin \ .NETFramework \

System.Configuration
Add the Media Services account settings to the app.config of your application:
<?xml version="1.0"?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
  </startup>
  <appSettings>
    <add key="accountName" value="Add-Media-Services-Account-Name" />
    <add key="accountKey" value="Add-Media-Services-Account-Key" />
  </appSettings>
</configuration>


Add to the code variables pointing to a local video file and an existing folder for the results of work:
private static readonly string _singleInputFilePath = 
                                             Path.GetFullPath(@"C:\mediaFiles\interview.wmv");

private static readonly string _outputFilesFolder = 
                                              Path.GetFullPath(@"C:\outputfiles");


Replace the using block in the file with the following:
using System.Linq;
using System;
using System.Configuration;
using System.IO;
using System.Threading;
using System.Collections.Generic;
using Microsoft.WindowsAzure.MediaServices.Client;


Define the variables that will contain your account data:
private static readonly string _accountKey = ConfigurationManager.AppSettings["accountKey"];

private static readonly string _accountName = ConfigurationManager.AppSettings["accountName"];


Define variables to reference the server context and the result of the work:
private static CloudMediaContext _context = null;

static string _outputAssetID = null;


In the Main method, add a service context creation:
_context = new CloudMediaContext(_accountName, _accountKey);


Now you need to create and upload media data to the service:
static IAsset CreateAndUploadAsset(string inputMediaFilePath) {
   IAsset theAsset = _context.Assets.Create(inputMediaFilePath, AssetCreationOptions.StorageEncrypted);
   Console.WriteLine("Asset name: " + theAsset.Name);
   Console.WriteLine("Asset ID: " + theAsset.Id);
   Console.WriteLine("Time created: " + theAsset.Created.Date.ToString());
   Console.WriteLine("Encrypted status: " + theAsset.Options.ToString());
   return theAsset;
}

IAsset asset = CreateAndUploadAsset(_singleInputFilePath);


For transcoding tasks on the server, we will create several auxiliary functions:
// Основаня функция 
static void CreateEncodingJob(IAsset asset, string outputFolder) {

  IJob job = _context.Jobs.Create("My Encoding Job");

  // Получаем медиа-процессор
  IMediaProcessor processor = GetMediaProcessor("Windows Azure Media Encoder");

  // Создаём задачу перекодирование
  ITask task = job.Tasks.AddNew("My encoding task", processor, "H.264 256k DSL CBR", TaskCreationOptions.None);

  // Указываем, что перкодировать
  task.InputMediaAssets.Add(asset);

  // Добавляем Asset для результатов работы
  task.OutputMediaAssets.AddNew("Output asset", true, AssetCreationOptions.None);

  // Запускаем процесс. 
  job.Submit();

  // Ждём результата и выводим сообщения в консоль
  CheckJobProgress(job.Id);

  // Получаем ссылку на Job
  job = GetJob(job.Id);

  // Получаем ссылку на результат
  IAsset outputAsset = job.OutputMediaAssets[0];

  // Устанавливаем значение глобальной перменной
  _outputAssetID = outputAsset.Id;

  // Получаем SAS URL для доступа к результатам кодирования
  string sasUrl = GetAssetSasUrl(outputAsset, TimeSpan.FromMinutes(30));

  // Записываем URL в локальный файл
  string outFilePath = Path.GetFullPath(outputFolder + @"\" + "SasUrl.txt");
  WriteToFile(outFilePath, sasUrl);
}


Secondary functions.

We are waiting for the end of the work and display the status in the console:
private static void CheckJobProgress(string jobId) {
  // Флаг окончания работы 
  bool jobCompleted = false;

  // Интервал опроса
  const int JobProgressInterval = 20000;

  while (!jobCompleted) {
     // Получаем свежую ссылку на Job
     IJob theJob = GetJob(jobId);

     // Проверяем состояние и выводим на консоль
     switch (theJob.State) {
        case JobState.Finished:
           jobCompleted = true;
           Console.WriteLine("");
           Console.WriteLine("********************");
           Console.WriteLine("Job state: " + theJob.State + ".");
           Console.WriteLine("Please wait while local tasks complete...");
           Console.WriteLine();
           break;
        case JobState.Queued:
        case JobState.Scheduled:
        case JobState.Processing:
           Console.WriteLine("Job state: " + theJob.State + ".");
           Console.WriteLine("Please wait...");
           Console.WriteLine();
           break;
        case JobState.Error:
           break;
        default:
           Console.WriteLine(theJob.State.ToString());
           break;
     }

     // Ждём, прежде чем проверить состояение снова
     Thread.Sleep(JobProgressInterval);
  }
}


We request the media processor:
private static IMediaProcessor GetMediaProcessor(string mediaProcessor) {
  // Возможные строки для получения ссылки на медиа процессор
  //    MP4 to Smooth Streams Task
  //    Windows Azure Media Encoder
  //    PlayReady Protection Task
  //    Smooth Streams to HLS Task 
  //    Storage Decryption

  // Запрашиваем, чтобы получить ссылку на медиа процессор
  var theProcessor = from p in _context.MediaProcessors
                     where p.Name == mediaProcessor
                     select p;

  // Кастуем в IMediaprocessor.
  IMediaProcessor processor = theProcessor.First();

  if (processor == null)
     throw new ArgumentException(string.Format(System.Globalization.CultureInfo.CurrentCulture, "Unknown processor", mediaProcessor));

  return processor;
}


Getting a link to Job:
static IJob GetJob(string jobId) {
  // Запрашиваем Job по Id
  var job =
      from j in _context.Jobs
      where j.Id == jobId
      select j;

  //Получаем её из результатов запроса
  IJob theJob = job.FirstOrDefault();

  // Проверяем, что Job есть :) 
  if (theJob != null)
     return theJob;
  else
     Console.WriteLine("Job does not exist.");
  return null;
}


Getting SAS URL for coding results:
static String GetAssetSasUrl(IAsset asset, TimeSpan accessPolicyTimeout) {

  // Создаём полиси
  IAccessPolicy readPolicy = _context.AccessPolicies.Create("My Test Policy", accessPolicyTimeout, AccessPermissions.Read);

  // Создаём locator, который обеспечивает доступ к asset с наложенной полиси
  ILocator locator = _context.Locators.CreateSasLocator(asset, 
      readPolicy,
      DateTime.UtcNow.AddMinutes(-5));

  Console.WriteLine("Locator path: ");
  Console.WriteLine(locator.Path);
  Console.WriteLine();

  // Получаем ссылку на mp4 файл - нам не нужны метаданные - xml
  var theOutputFile =
                      from f in asset.Files
                      where f.Name.EndsWith(".mp4")
                      select f;

  // Кастуем IQueryable в IFileInfo.
  IFileInfo theFile = theOutputFile.FirstOrDefault();
  string fileName = theFile.Name;

  // Строим окончательный SAS URL
  var uriBuilder = new UriBuilder(locator.Path);
  uriBuilder.Path += "/" + fileName;


  Console.WriteLine("Full URL to file: ");
  Console.WriteLine(uriBuilder.Uri.AbsoluteUri);
  Console.WriteLine();

  return uriBuilder.Uri.AbsoluteUri;
}


Helper method of writing to a file:

static void WriteToFile(string outFilePath, string fileContent) {
  StreamWriter sr = File.CreateText(outFilePath);
  sr.Write(fileContent);
  sr.Close();


It remains to add to Main:
CreateEncodingJob(asset, _outputFilesFolder);


And you can run our program.
An example of the results of the program
Asset name: interview
Asset ID: nb:cid:UUID:xyzxyza-318a-4a47-b996-27353b23abc3
Time created: 5/24/2012 12:00:00 AM
Encrypted status: StorageEncrypted
Job state: Queued.
Please wait...

Job state: Processing.
Please wait...

Job state: Processing.
Please wait...


********************
Job state: Finished.
Please wait while local tasks complete...

Locator path:
https://MediaServicesServer.blob.core.windows.net/asset-zzzz374-1234-4c60-9da8-3daf
7a6dabcd?st=2012-05-24T21%3A59%3A55Z&se=2012-05-24T22%3A29%3A55Z&sr=c&si=b1a0cf8
f-45bf-4f77-a84a-a38c3f8a002d&sig=tWmPLPpNuQpEXvCd2Ik8rCfY5AqjII3gnWgi9ustBI4%3D


Full URL to file:
https:// MediaServicesServer.blob.core.windows.net/asset- zzzz374-1234-4c60-9da8-3daf
7a6dabcd/interview.mp4?st=2012-05-24T21%3A59%3A55Z&se=2012-05-24T22%3A29%3A55Z&s
r=c&si=b1a0cf8f-45bf-4f77-a84a-a38c3f8a002d&sig=tWmPLPpNuQpEXvCd2Ik8rCfY5AqjII3g
nWgi9ustBI4%3D



So, we got acquainted with the services of Windows Azure Media Services and even tried to write a simple program that takes advantage of the simplest features provided by the services. More information about the services can be found at the following link: www.windowsazure.com/en-us/develop/net/how-to-guides/media-services