媒体上传--在Windows Store应用中使用Azure媒体服务之一
Windows Azure的媒体服务预览已经于8月15日在中国上线,我已经迫不及待的想在在Windows Store应用中加入媒体服务功能带来的便利了。可是,一个很让人沮丧的事情是,目前的Azure Media的SDK还不支持windows Store应用。不过没关系,我们还有REST API可以使用,这里我就讲解一下如何在Windows store应用中完成媒体文件的上传,编码及发布。在这一篇blog中,我们首先来看一下媒体文件的上传。
为了使用Azure Media,你首先需要在Azure上创建一个媒体服务账号。该账号用以提供访问该媒体服务所需的信息。下面是创建媒体服务账号的步骤:
1. 登录进入Azure管理门户:
https://manage.windowsazure.com/
如果你还没有Windows Azure的账号,那么有两种办法可以免费试用Windows Azure:
a. 因为Windows Azure已经在中国落地,你可以到https://www.windowsazure.cn上去申请试用,这段时间1元试用可是有大礼包送的哦。
b. 你可以登录全球的Windows Azure网站https://www.windowsazure.com来建立一个试用账号。在建立使用账号过程中如果无法进行电话或者短信验证的话,可以到以下网址提交一个问题来要求免去电话和短信验证步骤:
https://support.microsoft.com/oas/default.aspx?prid=14238&ln=en-us&st=1&wfxredirect=1
在提交问题的时候,你需要设定如下支持类型
然后再后续的邮件中再描述一下你遇到的问题,要求免去电话和短信验证步骤就可以了。
2. 点击新建->应用服务->媒体服务->快速创建,输入所需的名称,选择媒体服务存放的地点以及存储服务的账户。如果你之前没有建立存储服务的账户的话,你也可以选择“新建存储账户”。然后点击“创建媒体服务”就创建了一个媒体服务账号:
3. 点击新创建的媒体服务账号->管理密钥,你就可以获得访问该媒体服务所需的账户名称以及访问密钥,请将这两个字符串拷贝出来,后面我们会在编程的时候使用到:
在配置完Azure Media以后,我们就可以在Windows Store应用程序中通过REST API来传文件了。
首先,我们创建一个新的Windows Store应用,然后为项目添加两个引用:
Microsoft.WindowsAzure.Storage
Newtonsoft.Json
为了演示视频文件的上传,我们可以在示例代码中加入一个Button,然后在Button的处理函数中添加相关的代码。我们需要定义两个string来存放前面获得的Account Name和Access Key。另外,我们还需要定义两个string来存放对应的存储账户的Account Name和Access Key以便于后续对存储容器的直接访问。对应的存储账户信息可以从媒体服务的仪表板中获得:
接下来就是具体的实现代码了,对于要发送的http报文的内容,下面的MSDN链接已经有详细的描述,我这边就不再重复了:
https://msdn.microsoft.com/en-us/library/azure/jj129593.aspx
根据上述的描述,我们首先要获得一个Access Token,代码如下:
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;}
}
private async Task<string> GetAccessToken()
{
string scope = "urn:WindowsAzureMediaServices";
string accessControlServiceUri = "https://wamsprodglobal001acs.accesscontrol.windows.net/v2/OAuth2-13";
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(accessControlServiceUri);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
var requestBytes = Encoding.UTF8.GetBytes("grant_type=client_credentials&client_id=" +
mediaServicesAccountName + "&client_secret=" + System.Net.WebUtility.UrlEncode(mediaServicesAccountKey) +
"&scope=" + System.Net.WebUtility.UrlEncode(scope));
var requestStream = await request.GetRequestStreamAsync();
await requestStream.WriteAsync(requestBytes, 0, requestBytes.Length);
await requestStream.FlushAsync();
WebResponse response = await request.GetResponseAsync();
Stream responseStream = response.GetResponseStream();
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(AcsToken));
var acsToken = (AcsToken)ser.ReadObject(responseStream);
return acsToken.access_token;
}
在得到访问令牌后,就可以创建Asset了:
private async Task<string> CreateAsset(string accessToken)
{
var request = (HttpWebRequest)HttpWebRequest.Create("https://wamshknclus001rest-hs.cloudapp.net/api/Assets");
request.Method = "POST";
request.ContentType = "application/json;odata=verbose";
request.Accept = "application/json;odata=verbose";
string assertName = "myAssert";
string requestbody = "{ \"Name\" : \"" + assertName + "\" }";
request.Headers["DataServiceVersion"] = "3.0";
request.Headers["MaxDataServiceVersion"] = "3.0";
request.Headers["x-ms-version"] = "2.5";
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");
}
接下来我们需要更新Access Policy,允许对Asset进行写操作:
private async Task<string> UpdateAccessPolicy(string accessToken)
{
var request = (HttpWebRequest)HttpWebRequest.Create("https://wamshknclus001rest-hs.cloudapp.net/api/AccessPolicies");
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;
var requestbody = "{ \"Name\" : \"" + name + "\", \"DurationInMinutes\" : \"" + dura + "\", \"Permissions\" : " + permission + "}";
request.Headers["DataServiceVersion"] = "3.0";
request.Headers["MaxDataServiceVersion"] = "3.0";
request.Headers["x-ms-version"] = "2.5";
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();
var responseJsonObject = JObject.Parse(returnBody);
var d = responseJsonObject["d"];
return d.Value<string>("Id");
}
得到了所获得的权限以后,我们就可以通过Assert的存储容器来上传媒体文件了。首先来获得Asset对用的存储容器的名称:
private async Task<string> GetContainerName(string policyId, string assetId, string accessToken)
{
var request = (HttpWebRequest)HttpWebRequest.Create("https://wamshknclus001rest-hs.cloudapp.net/api/Locators");
request.Method = "POST";
request.ContentType = "application/json;odata=verbose";
request.Accept = "application/json;odata=verbose";
string starttime = DateTime.UtcNow.AddMinutes(-5).ToString("s") + "Z";
int type = 1;
var requestbody = "{ \"AccessPolicyId\" : \"" + policyId + "\", \"AssetId\" : \"" + assetId + "\", \"StartTime\" : \"" + starttime + "\", \"Type\" : " + type + "}";
request.Headers["MaxDataServiceVersion"] = "3.0";
request.Headers["x-ms-version"] = "2.5";
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();
var responseJsonObject = JObject.Parse(returnBody);
var d = responseJsonObject["d"];
string path = d.Value<string>("Path");
return (new Uri(path)).Segments[1];
}
接下来就是通过存储服务的API来上传视频文件了,因为存储服务的SDK支持Windows Store应用,所以这里就不用REST API来实现了,直接调用SDK提供的接口,这样整个的Button响应函数代码如下:
private async void Button_Click(object sender, RoutedEventArgs e)
{
StorageFolder library = Windows.Storage.KnownFolders.VideosLibrary;
var video = await library.GetFileAsync("Wildlife.wmv");
string accessToken = await GetAccessToken();
string assetId = await CreateAsset(accessToken);
string policyId = await UpdateAccessPolicy(accessToken);
string containerName = await GetContainerName(policyId, assetId, accessToken);
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("videoblob");
await blockBlob.UploadFromFileAsync(video);
}
通过以上代码,我们就完成了对视频文件的上传,后续我还将讲述如何对媒体文件进行转码及播放,尽情期待。