流媒体发布--在Windows Store应用中使用Azure媒体服务之三
经过前面的努力,我们终于完成了视频文件的上传和编码,那么接下来的最后一步就是将如何该视频发布出去了。相对应前面的步骤,这一次就要简单的多了。
首先,在确认编码已经成功之后,我们可以获得输出的媒体的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的policy编号
private async Task<string> DownloadAccessPolicy(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 = "DownloadPolicy" + DateTime.UtcNow.ToString("s") + "Z";
string dura = "3600";
int permission = 1;
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");
}
根据这个Asset编号以及相应的Policy编号,就可以得到Stream的路径了:
public async Task<string> GetOriginURL(string policyId, string assetId, string accessToken)
{
HttpWebRequest 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.ToString("s") + "Z";
int type = 2;
String requestbody = "{ \"AccessPolicyId\" : \"" + policyId + "\", \"AssetId\" : \"" + assetId + "\", \"StartTime\" : \"" + starttime + "\", \"Type\" : " + type + "}";
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();
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<string>("Path");
}
这个路径是不包含文件名的,另外,为了支持不同的平台,我们需要在该路径后面加上不同的manifest标志,由于我们前面是将媒体文件编码为Smooth Streaming流的,所以这里只需要加上manifest就可以了,最终在Button_Click中的代码就是:
var outputAssetId=await GetOutputAssetId(Id,accessToken);
policyId = await DownloadAccessPolicy(accessToken);
var streamPath = await GetOriginURL(policyId, outputAssetId, accessToken);
var streamFullPath=streamPath+"Wildlife.ism/manifest";
这里得到的streamFullPath就是可以用来播放的流媒体路径了。你可以把它放到任意一个支持Smooth Streaming流媒体的播放器中播放。那么在Windows Store应用中该如何播放呢?其实微软已经提供了支持Smooth Streaming的Windows Store应用控件,你可以首先下载Microsoft Smooth Streaming Client SDK for Windows 8.1:
https://visualstudiogallery.msdn.microsoft.com/0170c67c-c183-4fee-8dd4-c2b44d710d40
以及Player Framework for Windows and WP v2.0:
https://playerframework.codeplex.com/releases
然后在您的应用的Reference中添加三个引用:
Microsoft Smooth Streaming Client SDK For Windows 8.1
Microsoft Player Framework
Microsoft Player Framework Adaptive Streaming Plugin
注意,在添加了这三个引用以后,您的应用就不能使用Any CPU了,而必须的显式的设置x86或者x64。
然后在Toolbox里面就可以看到一个新的控件MediaPlayer,将该Media Player加到我们的XAML文件中
<PlayerFramework:MediaPlayer x:Name="mediaPlayer"/>
然后在后台的Button_Click的事件处理函数中添加代码来使Media player支持Smooth Streaming 并且设置它的Source,这样我们得到的流媒体才可以在Windows Store应用中播放:
var adaptivePlugin = new Microsoft.PlayerFramework.Adaptive.AdaptivePlugin();
mediaPlayer.Plugins.Add(adaptivePlugin);
mediaPlayer.Source = new Uri(streamFullPath);
mediaPlayer.Play();
终于,所有的工作都已经大告成功,我们现在可以享受Smooth Streaming的流畅播放体验了。当然不管是Azure Mobile以及Microsoft Player Framework都是支持HLS以及MPEG DASH,所以如果你想采用这两种格式的话也是完全没问题的,区别就在于编码时格式选择的不同以及streamFullPath中manifest后缀的不同,有兴趣的朋友可以去自己尝试一下,这里我不重复了。