Прежде чем приступить к созданию мультимедийных приложений с использованием службы мультимедиа в
Windows Azure , первое, что вам нужно сделать, это создать службу мультимедиа. Вы можете создать новую мультимедийную службу через портал Windows Azure. Следующие скриншоты демонстрируют шаги для того же самого.
1. Укажите название медиа-сервиса и выберите учетную запись хранения
Первое, что вам нужно сделать, это указать имя медиа-службы и выбрать учетную запись хранения, в которой будут храниться файлы, относящиеся к различным ресурсам.
2. Управление ключами доступа
После того, как медиа-сервис успешно создан, вам нужно получить ключи доступа. Если вы использовали службу хранилища Windows Azure, вы были бы знакомы с концепцией ключей доступа. По сути, это ключи, необходимые для безопасной связи с Media Service. Любой, кто имеет доступ к этим ключам (и названию вашей службы), имеет полный доступ к вашей мультимедийной службе, поэтому необходимо соблюдать крайнюю осторожность для защиты этих ключей.
Здесь также следует обратить внимание на раздел « Настройка ключа хранилища ». При создании медиа-сервиса вы указали, какую учетную запись хранения вы хотите использовать для хранения файлов. Выбирая между « синхронизировать первичный ключ » и « синхронизировать вторичный ключ », вы указываете Media Service использовать этот конкретный ключ при взаимодействии с учетной записью хранилища. Кроме того, если вы в конечном итоге регенерируете свой ключ учетной записи хранения (по какой-либо причине), тем самым гарантируете, что ваша медиа-служба продолжает работать. Я считаю, что он постоянно опрашивает службу хранения и выбирает ключ учетной записи хранения, который вы выбрали для синхронизации (общее предположение !!!)
На основании моего тестирования, если я не нажимаю ни одну из этих кнопок « синхронизировать первичный ключ » и « синхронизировать вторичный ключ » по умолчанию, Media Service использует первичный ключ учетной записи хранения. Если я изменю свой первичный ключ, любая выполняемая мной операция, связанная с взаимодействием Media Service с этой учетной записью хранилища, не будет выполнена.
API и SDK
В своей основе Media Service предоставляет функциональность управления через REST API . Он также предоставляет .Net SDK, который по сути является оболочкой для REST API.
Можно задать вопрос, по какому пути идти: REST API или .Net SDK? На мой взгляд, ответ зависит от ряда факторов, таких как:
- Flexibility: Usually in my experience, consuming REST API gives you more flexibility as you are not bound by only the functionality exposed through SDK.
- Convenience: Obviously SDK provides you more convenience as most of the work as far as implementing REST API has already been done for you. Plus it includes some helper functionality (like moving files into blob storage) which is not there in REST API for Media Service.
- Platform Feature Compatibility: In my experience, SDK comes a bit after (sometimes long after) REST API. If we take Windows Azure Storage for example, there are still some things you could not do with SDK (version 1.7 at the time of writing) while they are available in the system and are exposed via REST API. If we look at Media Service in particular, the ability to create Job Templates and Task Templates are still not available through SDK at the time of writing this blog. Thus if you need these functionality, you would have to go REST API route.
- SDK Unavailability: Sometimes you don’t have a choice. For example, if you’re building functionality in say PHP and we know that currently there’s no SDK available for PHP. In that case you would need to use REST API. Having said this thing and given the way things are going in other parts of Windows Azure, I would not be surprised if the SDK for many common platforms (PHP, Java, node.js) arrive pretty soon.
REST API
A few things about REST API:
- Get an access token first: Before using REST API, you would need to get an access token first from Windows Azure Access Control Service (ACS). This is described in detail later in this blog post.
- Know about various request/response headers: Again when using REST API, understand about various headers you would need to pass in your request and the headers returned in response. You can find more information about this here: http://msdn.microsoft.com/en-us/library/windowsazure/hh973616.aspx.
.Net SDK
A thing or two I noticed about .Net SDK:
- Windows Azure Storage Client Library Version: Please note that at the time of writing this blog, the SDK has a dependency on Windows Azure Storage Client Library for SDK version 1.6 (library version 1.1) while the most latest SDK version is 1.7. Please make a note of that.
Authenticating (or is it Authorizing ) REST API Requests
As mentioned above, before you could invoke Media Service REST API functionality you would need to get an access token from Windows Azure Access Control Service (ACS). In order to do so, a few things to keep in mind:
Endpoint:
Endpoint for getting an access token is: https://wamsprodglobal001acs.accesscontrol.windows.net/v2/OAuth2-13
HTTP Method:
HTTP Method for this request is POST.
Request Body:
Request body should be in this format:
grant_type=client_credentials&client_id=[client id value]&client_secret=[URL-encoded client secret value]&scope=urn%3aWindowsAzureMediaServices
For example, if we take the values from above, the request body will be:
grant_type=client_credentials&client_id=gauravdemomediaservice&client_secret=RlT8voLHr6aHNYyxNOxS%2f1MkRsgT5Tb8m9guPMucsfw%3d&scope=urn%3aWindowsAzureMediaServices
Response Body:
The response is returned in JSON format. Here’s what a typical response looks like:
{ "token_type":"http://schemas.xmlsoap.org/ws/2009/11/swt-token-profile-1.0", "access_token":"http%3a%2f%2fschemas.xmlsoap.org%2fws%2f2005%2f05%2fidentity%2fclaims%2fnameidentifier=gauravdemomediaservice&urn%3aSubscriptionId=35d2de3b-a2cd-4160-aee5-f55d799962c4&http%3a%2f%2fschemas.microsoft.com%2faccesscontrolservice%2f2010%2f07%2fclaims%2fidentityprovider=https%3a%2f%2fwamsprodglobal001acs.accesscontrol.windows.net%2f&Audience=urn%3aWindowsAzureMediaServices&ExpiresOn=1349691469&Issuer=https%3a%2f%2fwamsprodglobal001acs.accesscontrol.windows.net%2f&HMACSHA256=LrliUJEEfUlBPTJJVlp35%1fS2XEX7xwWUQRN%2fb1NkJkM%3d", "expires_in":"5999", "scope":"urn:WindowsAzureMediaServices" }
A few things to keep in mind here:
- access_token: This is the access token you would need when working with Media Service REST API. It must be included in every request.
- expires_in: This indicates the number of seconds for which the access token is valid. One must keep an eye on this value and ensure that the access token has not expired. One needs to get the access token again if the access token has expired.
Sample Project
Now what we will do is create a simple class library project which would be the wrapper around REST API much like .Net SDK. Then we’ll start consuming this library in another project. We’ll use VS 2010 to create this project and make use of .Net framework version 4.0. For the sake of simplicity, we’ll call this project as “WAMSRestWrapper”. Also because this REST API sends and receives the data in JSON format, we’ll make use of Json.Net library.
Since I’ll also be learning the REST API, the code would not be the best quality code and would desire a lot of improvements. Please feel free to make improvements as you see fit.
In this blog post, only thing we will do is get the access token and store it with our application.
To do so, let’s first create a class called AcsToken. Members of this class will map to the JSON data returned by ACS.
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace WAMSRestWrapper { public class AcsToken { public string token_type { get; set; } public string access_token { get; set; } public int expires_in { get; set; } public string scope { get; set; } } }
Next let’s create a class for fetching this ACS token. Since this class will be doing a lot of stuff in the days to come, let’s call it “MediaServiceContext” (inspired by MediaContextBase in .Net SDK) .
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Web; using Newtonsoft.Json; using System.Globalization; using System.IO; namespace WAMSRestWrapper { public class MediaServiceContext { private const string acsEndpoint = "https://wamsprodglobal001acs.accesscontrol.windows.net/v2/OAuth2-13"; private const string acsRequestBodyFormat = "grant_type=client_credentials&client_id={0}&client_secret={1}&scope=urn%3aWindowsAzureMediaServices"; private string _accountName; private string _accountKey; private string _accessToken; private DateTime _accessTokenExpiry; /// <summary> /// Creates a new instance of <see cref="MediaServiceContext"/> /// </summary> /// <param name="accountName"> /// Media service account name. /// </param> /// <param name="accountKey"> /// Media service account key. /// </param> public MediaServiceContext(string accountName, string accountKey) { this._accountName = accountName; this._accountKey = accountKey; } /// <summary> /// Gets the access token. If access token is not yet fetched or the access token has expired, /// it gets a new access token. /// </summary> public string AccessToken { get { if (string.IsNullOrWhiteSpace(_accessToken) || _accessTokenExpiry < DateTime.UtcNow) { var tuple = FetchAccessToken(); _accessToken = tuple.Item1; _accessTokenExpiry = tuple.Item2; } return _accessToken; } } /// <summary> /// This function makes the web request and gets the access token. /// </summary> /// <returns> /// <see cref="System.Tuple"/> containing 2 items - /// 1. The access token. /// 2. Token expiry date/time. /// </returns> private Tuple<string, DateTime> FetchAccessToken() { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(acsEndpoint); request.Method = "POST"; string requestBody = string.Format(CultureInfo.InvariantCulture, acsRequestBodyFormat, _accountName, HttpUtility.UrlEncode(_accountKey)); request.ContentLength = Encoding.UTF8.GetByteCount(requestBody); request.ContentType = "application/x-www-form-urlencoded"; using (StreamWriter streamWriter = new StreamWriter(request.GetRequestStream())) { streamWriter.Write(requestBody); } using (var response = (HttpWebResponse)request.GetResponse()) { using (StreamReader streamReader = new StreamReader(response.GetResponseStream(), true)) { var returnBody = streamReader.ReadToEnd(); var acsToken = JsonConvert.DeserializeObject<AcsToken>(returnBody); return new Tuple<string, DateTime>(acsToken.access_token, DateTime.UtcNow.AddSeconds(acsToken.expires_in)); } } } } }
The code is pretty straight forward. The constructor takes 2 parameters – account name and key and it exposes a public property called AccessToken. If an access token has never been fetched in this object’s lifecycle or has expired, a web request is made to ACS and token is fetched.
Now let’s write a simple console application which makes use of this library and all it does is prints out the access token on the console.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using WAMSRestWrapper; using Microsoft.WindowsAzure.MediaServices.Client; namespace WAMSSampleApplication { class Program { static string accountName = "<your media service account name>"; static string accountKey = "<your media service account key>"; static MediaServiceContext context; static void Main(string[] args) { context = GetContext(); var accessToken = context.AccessToken; Console.WriteLine("Acces token fetched: " + accessToken); Console.WriteLine(); Console.WriteLine(); Console.WriteLine("Press any key to terminate the application!"); Console.ReadLine(); } static MediaServiceContext GetContext() { return new MediaServiceContext(accountName, accountKey); } } }
Once we run this program, this is what we see on the console.
Now when invoking the Media Service REST API, we will make use of this access token.
Summary
That’s it for this post. In the next post, we will deal with more REST API functionality and expand this library. I hope you have found this information useful. As always, if you find some issues with this blog post please let me know immediately and I will fix them ASAP.
So long and stay tuned!