媒体编码--在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上查看结果,看到这个媒体文件的编码已经成功了。
在这一篇中,我们实现了对媒体文件的编码,后面我还会继续讲如何发布编码后的流媒体,尽请关注。