媒体编码--在Windows Store应用中使用Azure媒体服务之二

上一篇文章里,我们已经了解了如何使用REST API将多媒体数据上传给Azure的媒体服务,但这只是万里长征走完了第一步,为了能够使用多媒体数据,我们需要使用Azure强大的处理功能将数据编码成我们合适的格式,然后分发出去,在这一篇里我们就来讨论多媒体数据编码的问题。

使用用REST API,我们可以将任意格式的文件上传到服务器上,但是为了使媒体数据能够正确的发布,Azure Media需要安装了合适的编码器来做编解码的工作。Azure Media上已经内置了缺省的编码器,可以支持市面上主流的流媒体格式,同时,第三方也可以为Azure Media开发自己的编码器。

上一篇文章中我们已经把媒体文件上传到Azure Media服务器上,但是如果需要encoder的话,这个上传还是不完全的,我们需要在上传之前建立一个Asset文件:

private async Task<string> CreateAssetFile(string accessToken, string assetId)

{

    var request = (HttpWebRequest)HttpWebRequest.Create("https://wamshknclus001rest-hs.cloudapp.net/api/Files");

    request.Method = "POST";

    request.ContentType = "application/json;odata=verbose";

    request.Accept = "application/json;odata=verbose";

 

    string requestbody =

    "{\"Name\":\"test.wmv\", \"ContentFileSize\":\"0\",\"MimeType\":\"video/x-ms-wmv\",\"ParentAssetId\":\"" + assetId + "\"}";

 

    request.Headers["DataServiceVersion"] = "3.0";

    request.Headers["MaxDataServiceVersion"] = "3.0";

    request.Headers["x-ms-version"] = "2.7";

    request.Headers["Authorization"] = "Bearer " + accessToken;

 

    var requestBytes = Encoding.UTF8.GetBytes(requestbody);

 

 

    var requestStream = await request.GetRequestStreamAsync();

    await requestStream.WriteAsync(requestBytes, 0, requestBytes.Length);

    await requestStream.FlushAsync();

 

    var response = await request.GetResponseAsync();

    var responseStream = response.GetResponseStream();

    var stream = new StreamReader(responseStream);

 

    var returnBody = stream.ReadToEnd();

    JObject responseJsonObject = JObject.Parse(returnBody);

    var d = responseJsonObject["d"];

    return d.Value<string>("Id");

}

然后在上传之后更新这个Asset文件信息:

private async Task MergeAssetFile(string accessToken, string fileId, string assetId, ulong size)

{

    var request = (HttpWebRequest)HttpWebRequest.Create("https://wamshknclus001rest-hs.cloudapp.net/api/Files('"+fileId+"')");

    request.Method = "MERGE";

    request.ContentType = "application/json;odata=verbose";

    request.Accept = "application/json;odata=verbose";

 

    string requestbody = "{\"ContentFileSize\":\""+size+"\",\"MimeType\":\"video/x-ms-wmv\",\"Name\":\"test.wmv\",\"ParentAssetId\":\"" + assetId + "\"}";

           

    request.Headers["DataServiceVersion"] = "3.0";

    request.Headers["MaxDataServiceVersion"] = "3.0";

    request.Headers["x-ms-version"] = "2.7";

    request.Headers["Authorization"] = "Bearer " + accessToken;

 

    var requestBytes = Encoding.UTF8.GetBytes(requestbody);

 

 

    var requestStream = await request.GetRequestStreamAsync();

    await requestStream.WriteAsync(requestBytes, 0, requestBytes.Length);

    await requestStream.FlushAsync();

 

    var response = await request.GetResponseAsync();

 

}

这样才算让Azure Media真正的得到上传的媒体文件的信息。接下来就可以进行编码工作了。我们首先获得一个编码处理单元,这里我们选择的处理单元是Windows Azure Media Encoder:

public async Task<String> GetProcessorId(string accessToken)

{

    HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("https://wamshknclus001rest-hs.cloudapp.net/api/MediaProcessors()?$filter=Name%20eq%20'Windows%20Azure%20Media%20Encoder'");

    request.Method = "GET";           

    request.ContentType = "application/json;odata=verbose";

    request.Accept = "application/json;odata=verbose";

    request.Headers["DataServiceVersion"] = "3.0";

    request.Headers["MaxDataServiceVersion"] = "3.0";

    request.Headers["x-ms-version"] = "2.5";

    request.Headers["Authorization"] = "Bearer " + accessToken;

           

    WebResponse response = await request.GetResponseAsync();

    Stream responseStream = response.GetResponseStream();

    StreamReader stream = new StreamReader(responseStream);

                     

    var returnBody = stream.ReadToEnd();

    JObject responseJsonObject = JObject.Parse(returnBody);

var results = responseJsonObject["d"]["results"][0];

    return results.Value<string>("Id");                       

}

在得到了编码处理单元以后,我们就可以创建一个编码任务了:

public async Task<String> CreateEncodeJob(string jobname, string assetId, string processorId, string accessToken)

{

                     

    var assertURI = "https://media.windows.net/api/Assets('" + assetId + "')";

 

    HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("https://wamshknclus001rest-hs.cloudapp.net/api/Jobs");

    request.Method = "POST";

    request.ContentType = "application/json;odata=verbose";

    request.Accept = "application/json;odata=verbose";

                       

    string name = "UploadPolicy" + DateTime.UtcNow.ToString("s") + "Z";

    string dura = "300";

    int permission = 2;

    String requestbody = "{ \"Name\" : \"" + name + "\"," +

                            " \"DurationInMinutes\" : \"" + dura + "\", " +

                            " \"Permissions\" : " + permission + "}";

    requestbody ="{\"Name\" : \"" + jobname +  "\"," +

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

                    " \"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>\"}]}";

 

 

    request.Headers["DataServiceVersion"] = "3.0";

    request.Headers["MaxDataServiceVersion"] = "3.0";

    request.Headers["x-ms-version"] = "2.2";

    request.Headers["Authorization"] = "Bearer " + accessToken;

           

    var requestBytes = Encoding.UTF8.GetBytes(requestbody);

 

    var requestStream = await request.GetRequestStreamAsync();

    await requestStream.WriteAsync(requestBytes, 0, requestBytes.Length);

    await requestStream.FlushAsync();

 

    var response = await request.GetResponseAsync();

    var responseStream = response.GetResponseStream();

    var stream = new StreamReader(responseStream);

 

    var returnBody = stream.ReadToEnd();

    JObject responseJsonObject = JObject.Parse(returnBody);

    var d = responseJsonObject["d"];

    return d.Value<string>("Id");

}

这里我们选择将媒体文件编码为H264 Smooth Streaming 720p。该流媒体格式是主要针对Windows平台的,Azure Mobile也提供了跨平台的支持,比如说HLS或者MPEG-DASH。

在创建完成编码任务以后,Azure Media就开始在后台进行编码工作了。您可以等待一会儿,或者在你需要的时候查询编码状态,如果编码完成的话就换返回状态值3.首先我们实现查询编码状态的函数:

public async Task<int> GetJobState(string Id, string accessToken)

{

    String uir = "https://wamshknclus001rest-hs.cloudapp.net/api/Jobs('" + Id + "')/State";

 

    HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uir);

    request.Method = "GET";

    request.ContentType = "application/json;odata=verbose";

    request.Accept = "application/json;odata=verbose";

 

    request.Headers["DataServiceVersion"] = "3.0";

    request.Headers["MaxDataServiceVersion"] = "3.0";

    request.Headers["x-ms-version"] = "2.5";

    request.Headers["Authorization"] = "Bearer " + acsBearerToken;

 

    WebResponse response = await request.GetResponseAsync();

    Stream responseStream = response.GetResponseStream();

    StreamReader stream = new StreamReader(responseStream);

           

    var returnBody = stream.ReadToEnd();

    JObject responseJsonObject = JObject.Parse(returnBody);

           

    var d = responseJsonObject["d"];

    return d.Value<int>("State");

}

 

然后我们在前一篇文章的Button_Click事件处理函数中添加代码如下:

private async void Button_Click(object sender, RoutedEventArgs e)

{

    StorageFolder library = Windows.Storage.KnownFolders.VideosLibrary;

    var video = await library.GetFileAsync("test.wmv");

 

    string accessToken = await GetAccessToken();

 

    string assetId = await CreateAsset(accessToken);

    string fileId = await CreateAssetFile(accessToken, assetId);

    string policyId = await UpdateAccessPolicy(accessToken);

    string containerName = await GetContainerName(policyId, assetId, accessToken);

 

    //use storage API to upload

    StorageCredentials credentials = new StorageCredentials(storageName, storageKey);

 

    var storageAccount = new CloudStorageAccount(credentials, false);

    var cloudBlobClient = storageAccount.CreateCloudBlobClient();

 

    var container = cloudBlobClient.GetContainerReference(containerName);

    await container.CreateIfNotExistsAsync();

 

    CloudBlockBlob blockBlob = container.GetBlockBlobReference("Wildlife.wmv");

 

    await blockBlob.UploadFromFileAsync(video);

 

    var bp = await video.GetBasicPropertiesAsync();

 

    await MergeAssetFile(accessToken, fileId, assetId, bp.Size);

 

    var processorId = await GetProcessorId(accessToken);

    var Id = await CreateEncodeJob("testJob", assetId, processorId, accessToken);

 

    int jobState = 0;

    while (jobState != 3)

    {

        jobState = await GetJobState(Id, accessToken);

        await Task.Delay(TimeSpan.FromSeconds(2));

    }

}

这里我们通过轮询编码任务的状态来等待任务结束,为了避免等待过于频繁,我这边设定每次轮询时间为5秒。

这样我们已经完成了媒体文件的编码了,执行上述代码,当任务完成后,我们可以到Azure Portal上查看结果,看到这个媒体文件的编码已经成功了。

 

在这一篇中,我们实现了对媒体文件的编码,后面我还会继续讲如何发布编码后的流媒体,尽请关注。