基于Windows Azure Media Service REST API 进行Windows Store/Windows Phone 应用开发系列-Part 4媒体编码

在文章基于Windows Azure Media Service REST API 进行Windows Store/Windows Phone 应用开发系列-Part 1 简介中介绍了基于Windows Azure Media Service(Windows Azure 媒体服务,简称WAMS)进行应用开发的相关信息及包含的基本流程,在文章基于Windows Azure Media Service REST API 进行Windows Store/Windows Phone 应用开发系列-Part 2初始设置链接到WAMS中介绍了如何使用REST API进行WAMS的链接,然后在基于Windows Azure Media Service REST API 进行Windows Store/Windows Phone 应用开发系列-Part 3上传媒体到WAMS中少如何将媒体文件上传到媒体服务,本文将基于前面3篇内容进一步讲解如何对已经上传的媒体文件进行编码进而发布流媒体服务。

使用REST API对媒体文件进行编码,主要流程是:

  1. 创建作业
  2. 编码过程交由媒体服务完成
  3. 监视处理进程

请注意,如前文所强调的在使用REST API时访问媒体服务中的实体时,必须在HTTP请求中添加如下必须的标头字段和值;WAMS 的原始服务URI 为https://media.windows.net/,成功连接到此 URI后,会收到一个“301 重定向”响应指向另一个媒体服务URI,需要从该响应中提取出新的的媒体服务URI,随后的调用都是基于该 URI,详细内容参见Part2内容。

根据文档媒体服务 REST API 开发的设置可知,每次调用WAMS时,客户端必须在请求中包括必需的标头字段和值,列表如下:

Header

Type

Value

Authorization

Bearer

Bearer 是唯一接受的授权机制。

该值还必须包括由 ACS 提供的访问令牌。

x-ms-version

Decimal

2.7

DataServiceVersion

Decimal

3.0

MaxDataServiceVersion

Decimal

3.0

 

首先创建作业,每个作业可以包含一个或多个任务,具体是什么任务视处理类型而定,如将媒体文件转换为MP4文件的任务,或将MP4文件编码为smooth streaming 输出的任务,或者进行编码后的文件进行静态封装动态封装等任务。使用REST API可以创建多个作业及其相应的任务,

此处以一个作业一个视频编码任务为例,具体的可选的编码配置可以参见Media Services Encoder 的任务预设(如常用的H264 Smooth Streaming 720p,H264 Adaptive Bitrate MP4 Set 720p)。

创建编码作业请求简要总结如下,详情请参见:使用 Media Services REST API 创建编码作业

EndPoint

https://media.windows.net/API/Jobs

或重定向后的新的URI/Jobs

HTTP Method

POST

Request Headers

DataServiceVersion: 2.0MaxDataServiceVersion: 3.0x-ms-version: 2.7Authorization: Bear + ACSToken

Request Content Type

application/json; odata=verbose

Request Body Format

{ "Name": "<Job Name>", (自定义便于理解的作业名,如Encoding H264 Broadband 720p)    “InputMediaAssets”: [{

     "__metadata":{“uri”: “https://media.windows.net/api/Assets(‘AssetID’ )”}}],(注意请换为重定向后的URI)
     “Tasks”:[{
             “Configration”: “<encoding preset name>”   (如H264 Broadband 720p)
             “MediaProcessorId”: ”nb:mpid:UUID:70bdc2c3-ebf4-42a9-8542-5afc1e55d217”
             “TaskBody”: "<?xml version=\"1.0\" encoding=\"utf-8\"?>
                                       <taskBody>
                                              <inputAsset>JobInputAsset(0)</inputAsset>
                                              <outputAsset>JobOutputAsset(0)</outputAsset>
                                       </taskBody>" }]} 

 创建编码作业的代码参考如下,其中processorId 可以直接取自MSDN 文档: nb:mpid:UUID:70bdc2c3-ebf4-42a9-8542-5afc1e55d217,或者通过发送相应的请求获得。

    private async Task<bool> EncodeSmooth(string acsToken, string assetId, string jobName, string wamsEndpoint, string processorId)

        {

            AuthenticationHeaderValue header = CreateBasicAuthenticationHeader(acsToken);

            HttpClient httpClient = new HttpClient();

            httpClient.MaxResponseContentBufferSize = int.MaxValue; 

            httpClient.DefaultRequestHeaders.Add("Authorization", header.ToString());

            httpClient.DefaultRequestHeaders.Add("x-ms-version", "2.7");

            httpClient.DefaultRequestHeaders.Add("DataServiceVersion", "2.0");

            httpClient.DefaultRequestHeaders.Add("MaxDataServiceVersion", "3.0");  

 

            var assetURI = wamsEndpoint+"Assets('" + assetId + "')";

 

            String requestBody = "{ \"Name\" : \"" + jobName + "\"," +

                            " \"InputMediaAssets\" : [{\"__metadata\" : {\"uri\" : \"" + assetURI + "\"}}]," +

                            " \"Tasks\" : [{\"Configuration\" : \"H264 Smooth Streaming 720p\"," +

                             " \"MediaProcessorId\" : \"" + processorId + "\"," +

                           " \"TaskBody\" : \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?><taskBody><inputAsset>JobInputAsset(0)</inputAsset><outputAsset>JobOutputAsset(0)</outputAsset></taskBody>\"}]}";

                     

            HttpContent body = new StringContent(requestBody, Encoding.UTF8, "application/json");

            var response = await httpClient.PostAsync(wamsEndpoint+"Jobs", body);

 

     if (response.IsSuccessStatusCode)

     {              

          var content = await response.Content.ReadAsStringAsync();

          XmlDocument xmlDoc = new XmlDocument();

          xmlDoc.LoadXml(content);

 

          XmlNodeList elemListBase = xmlDoc.GetElementsByTagName("d:Id");

          string jobId = null;

          foreach (var ele in elemListBase)

          {

             jobId = ele.InnerText; 

          } 

          return jobId;

       }

       else

       {

           return null;

       }

        }

 

获取ProcessorID 的代码可以参考如下,注意,此处的processorName针对应用场景,可以是Windows Azure Media Encoder, 或者是Windows Azure Media Packager(在Static Packaging场景会用到)。

   private async Task<string> GetProcessorId(string acsToken, string wamsEndPoint, string processorName)

        {

             AuthenticationHeaderValue header = CreateBasicAuthenticationHeader(acsToken); 

            HttpClient httpClient = new HttpClient();

            httpClient.MaxResponseContentBufferSize = int.MaxValue; 

            httpClient.DefaultRequestHeaders.Add("Authorization", header.ToString());

            httpClient.DefaultRequestHeaders.Add("x-ms-version", "2.7");

            httpClient.DefaultRequestHeaders.Add("DataServiceVersion", "3.0");

            httpClient.DefaultRequestHeaders.Add("MaxDataServiceVersion", "3.0");

 

            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, wamsEndPoint);

            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

 

            string uri = Uri.EscapeUriString("Name eq "+"\'" +processorName +"\'");

            string endPoint = wamsEndPoint + "MediaProcessors()?$filter="+uri;

 

            var response = await httpClient.GetAsync(endPoint);

 

            string processorID = null;

            if (response.IsSuccessStatusCode)

            {

                var content = await response.Content.ReadAsStringAsync();

                XmlDocument xmlDoc = new XmlDocument();

                xmlDoc.LoadXml(content);

                XmlNodeList elemList = xmlDoc.GetElementsByTagName("d:Id");               

                foreach (var ele in elemList)

                {

                    processorID = ele.InnerText;                

                }

            }

            return processorID;

     }

       

创建好编码工作后,剩余的编码任务交由媒体服务负责完成,编码时间依赖于媒体文件的大小,在编码完成之后才能进行流媒体发布,但是客户端如何才能知道server端编码结束了呢?这里我们也可以对编码进程进行查询。查询作业状态的请求简要总结如下,详情请参见:使用 Media Services REST API 创建编码作业

EndPoint

https://media.windows.net/API/Jobs(jobId)/State  

或重定向后的新的URI/Jobs(jobId)/State (注意对jobId进行Url编码)

HTTP Method

GET

Request Headers

DataServiceVersion: 3.0MaxDataServiceVersion: 3.0x-ms-version: 2.7Authorization: Bear + ACSToken

Request Content Type

application/json; odata=verbose

 

执行代码参考如下,根据返回信息确定编码状态,如2-表示processing,3-表示finished,那么返回值为3时表示编码工作完成,即可进行后续的流媒体发布工作啦。

  private async Task<string> GetJobStateAsync(string acsToken, string wamsEndpoint, string jobId)

        {

            AuthenticationHeaderValue header = CreateBasicAuthenticationHeader(acsToken); 

            HttpClient httpClient = new HttpClient();

            httpClient.MaxResponseContentBufferSize = int.MaxValue; 

            httpClient.DefaultRequestHeaders.Add("Authorization", header.ToString());

            httpClient.DefaultRequestHeaders.Add("x-ms-version", "2.7");

            httpClient.DefaultRequestHeaders.Add("DataServiceVersion", "3.0");

            httpClient.DefaultRequestHeaders.Add("MaxDataServiceVersion", "3.0");

            httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));          

 

            string url = wamsEndpoint + "Jobs('" + WebUtility.UrlEncode(jobId) + "')/State"; 

            var response = await httpClient.GetAsync(url);

         

            if (response.IsSuccessStatusCode)

            {

                var content = await response.Content.ReadAsStringAsync();

                JObject jsonObject = JObject.Parse(content);

                string jobState = jsonObject.Value<string>("value");

                return jobState;               

            }

            else

                return null;    

        }

同时我们可以查看 Azure Porta以了解编码进展情况,如下截图所示编码已经完成:

 

 

完成文件的编码后后,便可以进行后续流媒体的发布,将在后续文章中详细讲述,敬请期待。