<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Blogs of Jenny Li</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/lj/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/lj/feed.xml</link>
    <description>Windows Store/ Windows Phone apps development</description>
    <lastBuildDate>Wed, 17 Apr 2019 03:23:23 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>微软云平台媒体服务实践系列 3- 基于媒体服务REST API及Xamarin进行iOS, Android , Windows 应用开发</title>
      <link>https://docs.microsoft.com/archive/blogs/lj/3-rest-apixamarinios</link>
      <pubDate>Wed, 06 May 2015 01:15:00 GMT</pubDate>
      <dc:creator><![CDATA[JennyLi-MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/lj/2015/05/06/3-rest-apixamarinios/</guid>
      <description><![CDATA[据统计，在Internet Traffic中，Video...]]></description>
      <content:encoded><![CDATA[<p>据统计，在Internet Traffic中，Video 所占的量超过了一半；相对于只使用电视机看节目的用户而言，使用移动设备的用户会多看接近50%的节目。可见，视频支持的终端设备越多，意味着越高的收视率，拥有越多的用户群，但是如果视频的缓冲时间长、画质差，用户很可能放弃观看。自适应流媒体技术可以根据客户端的网络带宽、系统资源等自动地选择恰当分辨率的媒体内容进行播放，为用户提供画质清晰流畅的播放体验。本文基于微软云平台媒体服务，介绍如何制定一个跨iOS,Android,Windows移动平台的自适应流媒体视频点播（VoD）方案，以期望在当今3大移动平台上，进行流媒体的制作与播放。</p>
<p>在移动平台上使用Azure Media Services (AMS) 的第一大难点就是对于iOS, Android,Windows Store 或Windows Phone app,没有可以直接使用的AMS SDK，也没有相应的移动应用使用媒体服务的code 样例；此外，各个移动平台拥有不同的开发环境与开发语言，那是否意味着需要分别去学习objective-c/swift, java,C#/VB.Net等才能完成整个方案? 而且该过程所耗费的时间及成本都不低。虽然困难重重，但是我们还是有机会的：一是媒体服务提供了可供所有平台调用的REST APIs；二是<a href="https://www.visualstudio.com/en-US/explore/xamarin-vs">Xamarin</a>的出现为我们解决了高效开发跨平台应用的难题，当然<a href="https://www.visualstudio.com/en-US/explore/cordova-vs">Cordova</a>也是一个选择；三是媒体服务有相应的.Net code 样例供参考使用。（总结如下图所示） &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/4744.001.jpg" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/4744.001.jpg"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/4744.001.jpg" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/4744.001.jpg" alt="" border="0" /></a>&nbsp;</p>
<p>基于AMS REST APIs和Xamarin, 整个方案如下图所示，主要分为移动客户端和媒体服务端，首先移动客户端负责将原始媒体文件上传到云端，再让媒体服务完成编码、流媒体发布等任务，最后再由客户端播放使用。那么针对不同的客户端，是不是就需要3个开发团队完成各自平台的项目开发及维护、修正等，有没有一种一次编写、到处运行的方案呢？</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/8233.002.jpg" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/8233.002.jpg"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/8233.002.jpg" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/8233.002.jpg" alt="" border="0" /></a>&nbsp;&nbsp;</p>
<p>&nbsp;Xamarin为我们解决了高效开发的难题，开发者基于Visual Studio, 使用C#便可同时开发出iOS, Android, Windows Phone和Windows Store App。如下图所示，Xamarin 由Mono .net framework开源项目的创始人创办，基于微软.Net Framework, 将 3大移动平台的SDK APIs 100%的移植成C#类库，由于拥有共同的类库，因此各个平台的项目可以共享与平台无关的code，如使用web service，当然每个平台也有其独特性，如UI 控件，只不过都是通过C#及描述性语言如XAML,XML活XIB实现。</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/0552.003.jpg" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/0552.003.jpg"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/0552.003.jpg" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/0552.003.jpg" alt="" border="0" /></a>&nbsp;</p>
<p>&nbsp;</p>
<p>基于以上信息，在共享项目code里使用媒体服务，各个移动平台再使用对应的流媒体播SDK API即完成整个方案的设计。</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/7411.004.jpg" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/7411.004.jpg"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/7411.004.jpg" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/7411.004.jpg" alt="" border="0" /></a>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;</p>
<p>基于REST APIs使用媒体服务的详细过程在前面的系列文：<a href="https://blogs.msdn.com/b/lj/archive/2014/10/08/windows-azure-media-service-rest-api-windows-store-windows-phone-part-1.aspx">基于Windows Azure Media Service REST API 进行Windows Store/Windows Phone 应用开发系列1</a>,<a href="https://blogs.msdn.com/b/lj/archive/2014/10/08/windows-azure-media-service-rest-api-windows-store-windows-phone-part-2-wams.aspx">2</a>,<a href="https://blogs.msdn.com/b/lj/archive/2014/11/28/windows-azure-media-service-rest-api-windows-store-windows-phone-part-3-wams.aspx">3</a>,<a href="https://blogs.msdn.com/b/lj/archive/2015/01/10/windows-azure-media-service-rest-api-windows-store-windows-phone-part-3.aspx">4</a>,<a href="https://blogs.msdn.com/b/lj/archive/2015/01/10/windows-azure-media-service-rest-api-windows-store-windows-phone-part-5.aspx">5</a> 进行了详细的介绍，代码基本上可以直接复用（基于System.Net.Http. <strong>HttpClient</strong> ），只是有些响应的返回内容的解析，在Xamarin中使用System.Linq.XDocument 类；此外，在上传媒体文件时（如下代码所示），不再使用Windows Runtime 的Windows.Storage.StorageFolder 类（高亮显示部分），由于上传过程使用的是Stream类型的数据且Xamarin支持System.IO.Stream 类，所以可以在各个平台独立地读取video为System.IO.Stream 类型，再传给share code操作 ；<strong>PCL Storage extension</strong>可以进行文件系统的读取，类似于Windows.Storage.StorageFolder的作用。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpClientHandler handler = new HttpClientHandler { MaxRequestContentBufferSize = 10000000 };</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpClient httpClient = new HttpClient(handler);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("x-ms-version", "2011-08-18");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("x-ms-date", "2011-01-17");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("x-ms-blob-type", "<strong>BlockBlob</strong>");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="background-color: #ffff00;"><strong>StorageFolder</strong> library = Windows.Storage.KnownFolders.VideosLibrary; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span></p>
<p><span style="background-color: #ffff00;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var videoFile = await library.GetFileAsync(MediaFileName);</span></p>
<p><span style="background-color: #ffff00;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var props = await videoFile.GetBasicPropertiesAsync();</span></p>
<p><span style="background-color: #ffff00;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var stream = await videoFile.OpenStreamForReadAsync();</span></p>
<p><span style="background-color: #ffff00;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ContentSize = props.Size;</span></p>
<p><span style="background-color: #888888;"><br /></span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StreamContent streamContent = new StreamContent(<span style="background-color: #ff0000;"><strong>stream</strong></span>, (int)props.Size);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpResponseMessage response = await httpClient.PutAsync(uploadUrl, streamContent);</p>
<p>在使用模拟器进行测试时，可以直接使用System.Reflection.Assembly 类中的API读取项目中的资源，将读取的Stream传给share code 即可。</p>
<p style="padding-left: 30px;">var assembly = Assembly.GetExecutingAssembly();</p>
<p style="padding-left: 30px;">var resourceName = "iStream.Droid.Assets.FromAndroid.wmv";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p style="padding-left: 30px;">Stream videoStream = assembly.GetManifestResourceStream(resourceName);</p>
<p>在MERGE过程中，Xamarin中使用的System.Net.HttpWebRequest 类型的request没有GetRequestStreamAsync() 及GetResponseAsync() 函数，为便于操作，为HttpWebRequest添加扩展方法：</p>
<p style="padding-left: 30px;">public static class HttpWebRequestExtensions</p>
<p style="padding-left: 30px;">&nbsp; &nbsp;{</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static Task&lt;Stream&gt; GetRequestStreamAsync(this HttpWebRequest request)</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var tcs = new TaskCompletionSource&lt;Stream&gt;();</p>
<p style="padding-left: 30px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;try</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; request.BeginGetRequestStream(iar =&gt;</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var response = request.EndGetRequestStream(iar);</p>
<p style="padding-left: 30px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;tcs.SetResult(response);</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch (Exception exc)</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tcs.SetException(exc);</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }, null);</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch (Exception exc)</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tcs.SetException(exc);</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p style="padding-left: 30px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return tcs.Task;</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static Task&lt;HttpWebResponse&gt; GetResponseAsync(this HttpWebRequest request)</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var tcs = new TaskCompletionSource&lt;HttpWebResponse&gt;();</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; request.BeginGetResponse(iar =&gt;</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var response = (HttpWebResponse)request.EndGetResponse(iar);</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tcs.SetResult(response);</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch (Exception exc)</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tcs.SetException(exc);</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }, null);</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch (Exception exc)</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tcs.SetException(exc);</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p style="padding-left: 30px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return tcs.Task;</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p style="padding-left: 30px;">&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;以上就是关于跨移动平台使用媒体服务制定自适应流媒体点播方案的介绍，通过对Xamarin及媒体服务 REST APIs的研究与编程实现，扩展了媒体服务在移动平台的运用，也极大地提高了开发效率，同时，该方案还可适用于其他基于REST API的服务，制定跨多平台的开发方案。</p>]]></content:encoded>
    </item>
    <item>
      <title>微软云平台媒体服务实践系列 2- 使用动态封装为iOS, Android , Windows 等多平台提供视频点播（VoD）方案</title>
      <link>https://docs.microsoft.com/archive/blogs/lj/2-ios-android-windows-228</link>
      <pubDate>Mon, 16 Mar 2015 01:32:00 GMT</pubDate>
      <dc:creator><![CDATA[JennyLi-MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/lj/2015/03/16/2-ios-android-windows-228/</guid>
      <description><![CDATA[文章微软云平台媒体服务实践系列 1- 使用静态封装为iOS, Android 设备实现点播（VoD）方案&nbsp; 介绍了如何针对少数iOS, Android...]]></description>
      <content:encoded><![CDATA[<p><span style="font-size: small;">文章</span><a href="https://blogs.msdn.com/b/lj/archive/2015/02/09/1-ios-android-vod.aspx"><span style="color: #0563c1;"><span style="font-size: small;">微软云平台媒体服务实践系列<span style="font-family: Calibri;"> 1- </span>使用静态封装为<span style="font-family: Calibri;">iOS, Android </span>设备实现点播（<span style="font-family: Calibri;">VoD</span>）方案</span></span></a><span style="font-size: small;"><span style="font-family: Calibri;">&nbsp; </span>介绍了如何针对少数<span style="font-family: Calibri;">iOS, Android </span>客户端的场景，出于节约成本的目的使用媒体服务的静态封装实现视频点播方案。实际应用中，所支持的客户端越多，那么所获得的用户越多，客户端多种多样：<span style="font-family: Calibri;">PC</span>端<span style="font-family: Calibri;">, Xbox, iOS, Android, Windows </span>等移动设备端，针对如此之大的客户端市场，能否搭建一套全面的点播方案呢？答案是肯定的，本文将基于微软云平台媒体服务介绍如何实现跨多移动客户端的视频点播方案。</span></p>
<p><span style="font-size: small;">微软的云平台</span><a href="https://msdn.microsoft.com/zh-cn/library/azure/hh973629.aspx"><span style="color: #0563c1; font-size: small;">媒体服务</span></a><span style="font-size: small;">为流媒体服务提供了多种选择，在使用流媒体服务为企业做流媒体方案时，首先需要确认要流媒体接收目标，如针对广大<span style="font-family: Calibri;">iOS, Android</span>移动设备，由于它们都支持<span style="font-family: Calibri;">HLS </span>格式的流媒体，微软平台支持<span style="font-family: Calibri;">smooth streaming </span>格式，基于该认知，比较推荐的是使用</span><a href="https://msdn.microsoft.com/zh-cn/library/azure/jj889436.aspx"><span style="color: #0563c1;"><span style="font-size: small;">动态封装</span></span></a><span style="font-size: small;">，但是必须额外</span><a href="https://azure.microsoft.com/en-us/documentation/articles/media-services-how-to-scale/"><span style="color: #0563c1; font-size: small;">添加流式处理单元</span></a><span style="font-size: small;">，方法是在<span style="font-family: Calibri;">Azure </span>门户，点击媒体服务，然后点击所使用的媒体服务，选择流式处理端点标签页，选择需要编辑的流媒体端点，然后再缩放标签页下设置，如下截图所示：</span></p>
<p><span style="font-family: Calibri; font-size: small;">&nbsp;&nbsp;&nbsp; <a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/7635.00-StreamingUnit.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/7635.00_2D00_StreamingUnit.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/7635.00-StreamingUnit.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/7635.00_2D00_StreamingUnit.png" alt="" border="0" /></a></span>&nbsp;</p>
<p><span style="font-family: Calibri; font-size: small;">&nbsp;</span><span style="font-size: small;">使用</span><a href="https://msdn.microsoft.com/zh-cn/library/azure/jj889436.aspx"><span style="color: #0563c1; font-size: small;">动态封装</span></a><span style="font-size: small;">制定支持</span><span style="font-size: small;"><span style="font-family: Calibri;">Windows, iOS, Android </span>平台的视频点播方案的流程如下截图所示：原始媒体文件<span style="font-family: Calibri;">&mdash;&mdash;&gt;</span>转码为<span style="font-family: Calibri;">MP4</span>文件<span style="font-family: Calibri;">&mdash;&mdash;&gt;</span>使用动态封装功能，按照客户端需求提供流媒体码流<span style="font-family: Calibri;">, </span>构造流媒体地址<span style="font-family: Calibri;">&mdash;&mdash;&gt;</span>测试。</span></p>
<p><span style="font-family: Calibri; font-size: small;">&nbsp; <a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/1651.01-DiagArct.jpg" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/1651.01_2D00_DiagArct.jpg"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/1651.01-DiagArct.jpg" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/1651.01_2D00_DiagArct.jpg" alt="" border="0" /></a></span></p>
<p><span style="font-family: Calibri; font-size: small;">&nbsp;</span><span style="font-size: small;">此外我们还可以在编码过程中<a href="https://msdn.microsoft.com/zh-cn/library/azure/dn673581.aspx"><span style="color: #0563c1;">为视频创建缩略图</span></a><span style="font-family: Calibri;">, </span>需要使用到相应的配置文件<span style="font-family: Calibri;">Thumbnail_Configuration.xml</span>，内容如下：</span></p>
<p><span style="font-family: Calibri;"><span style="font-size: small;">&lt;?xml version="1.0" encoding="utf-8"?&gt;</span></span></p>
<p><span style="font-family: Calibri;"><span style="font-size: small;">&lt;Thumbnail Size="100%,*" Type="Jpeg" Filename="{OriginalFilename}_{Size}_{ThumbnailTime}_{ThumbnailIndex}_{Date}_{Time}.{DefaultExtension}"&gt;</span></span></p>
<p><span style="font-family: Calibri;"><span style="font-size: small;">&nbsp;&nbsp;&nbsp; &lt;Time Value="10%" Step="10%" Stop="95%"/&gt;</span></span></p>
<p><span style="font-family: Calibri;"><span style="font-size: small;">&lt;/Thumbnail&gt;</span></span></p>
<p><span style="font-family: Calibri; font-size: small;">&nbsp;</span></p>
<p><span style="font-size: small;">整个代码流程可以参考如下：（使用流媒体服务<span style="font-family: Calibri;">.Net SDK</span>，注意指定媒体服务的账号名字<span style="font-family: Calibri;">(</span></span><span style="font-family: Calibri;">accName<span style="font-size: small;">)</span></span><span style="font-size: small;">及<span style="font-family: Calibri;">key(</span></span><span style="font-family: Calibri;">accKey<span style="font-size: small;">)</span></span><span style="font-size: small;">）</span></p>
<p><span style="font-family: Calibri;">class Program</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp; {</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static string accName = "[MediaService_accountName]";</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static string accKey = "[MediaService_accountKey]";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static readonly string _supportFiles =</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Path.GetFullPath(@"../..\..\..\..\");</span></p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Paths to support files (within the above base path). </span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // provide paths to your own media files below to run.</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static readonly string singleInputFilePath =</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Path.GetFullPath(_supportFiles + @"\azure.wmv");</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static readonly string outputPath = _supportFiles; </span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static CloudMediaContext context;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static readonly string configFilePath = Path.GetFullPath(_supportFiles + @"\Thumbnail_Configuration.xml");</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void Main(string[] args)</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; context = new CloudMediaContext(accName, accKey);</span></p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string inputAssetId = CreateAssetAndUploadFile(context);</span></p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //thumbnail</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IJob jobThumb = ThumbnailMaker(context, inputAssetId);</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string thumbnailUri = GetThumbnailUrl(context, jobThumb.OutputMediaAssets[0]);</span></p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//encode to MP4</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IJob job = EncodeToMp4(context, inputAssetId);</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IAsset mp4Output = job.OutputMediaAssets.FirstOrDefault();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Dynamic Packaging</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var mp4Asset = job.OutputMediaAssets.FirstOrDefault();</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string mp4Url = GetDynamicStreamingUrl(context, mp4Asset.Id, LocatorType.Sas);</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string smoothStreamingUrl = GetDynamicStreamingUrl(context, mp4Asset.Id, LocatorType.OnDemandOrigin);</span></p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string hlsStreamingUrl = smoothStreamingUrl + "(format=m3u8-aapl)";</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string mpegdashStreamingUrl = smoothStreamingUrl + "(format=mpd-time-csf)";</span></p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Output</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string content = "\n Thumbnail Url:&nbsp;&nbsp;&nbsp; \n" + thumbnailUri </span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+"\n Mp4 Url:&nbsp;&nbsp;&nbsp; \n" + mp4Url </span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + "\n Dynamic Packaging Smooth Url: \n" + smoothStreamingUrl </span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +"\n Dynamic Packaging HLS Url:&nbsp;&nbsp;&nbsp; \n" + hlsStreamingUrl</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +"\n Dynamic Packaging MPEG DASH Url:&nbsp;&nbsp;&nbsp; \n" + mpegdashStreamingUrl;</span></p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("\n Thumbnail Url:&nbsp;&nbsp;&nbsp; \n" + thumbnailUri);</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("\n Mp4 Url:&nbsp;&nbsp;&nbsp; \n" + mp4Url);</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("\n Smooth Url: \n" + smoothStreamingUrl);</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("\n HLS Url:&nbsp;&nbsp;&nbsp; \n" + hlsStreamingUrl);</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("\n MPEG DASH Url:&nbsp;&nbsp;&nbsp; \n" + mpegdashStreamingUrl);</span></p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string outFilePath = Path.GetFullPath(outputPath + @"\" + "StreamingUrl.txt");</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WriteToFile(outFilePath, content);</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.ReadKey();</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.ReadKey();</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static string CreateAssetAndUploadFile(CloudMediaContext context)</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var assetName = Path.GetFileNameWithoutExtension(singleInputFilePath);</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var inputAsset = context.Assets.Create(assetName, AssetCreationOptions.None);</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var assetFile = inputAsset.AssetFiles.Create(Path.GetFileName(singleInputFilePath));</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;assetFile.UploadProgressChanged += new EventHandler&lt;UploadProgressChangedEventArgs&gt;(assetFile_UploadProgressChanged);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; assetFile.Upload(singleInputFilePath);</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return inputAsset.Id;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void assetFile_UploadProgressChanged(object sender, UploadProgressChangedEventArgs e)</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(string.Format("{0}&nbsp;&nbsp; Progress: {1:0}&nbsp;&nbsp; Time: {2}", ((IAssetFile)sender).Name, e.Progress, DateTime.UtcNow.ToString(@"yyyy_M_d__hh_mm_ss")));</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static IJob EncodeToMp4(CloudMediaContext context, string inputAssetId)</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var inputAsset = context.Assets.Where(a =&gt; a.Id == inputAssetId).FirstOrDefault();</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (inputAsset == null)</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;throw new ArgumentException("Could not find assetId: " + inputAssetId);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var encodingPreset = "H264 Adaptive Bitrate MP4 Set 720p";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IJob job = context.Jobs.Create(".Net Encoding&nbsp; " + inputAsset.Name + " to MP4 job");</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IMediaProcessor latestWameMediaProcessor = (from p in context.MediaProcessors where p.Name == "Windows Azure Media Encoder" select p).ToList()</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .OrderBy(wame =&gt; new Version(wame.Version)).LastOrDefault();</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ITask encodeTask = job.Tasks.AddNew(".Net Encoding to Mp4 Task ", latestWameMediaProcessor, encodingPreset, TaskOptions.None);</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; encodeTask.InputAssets.Add(inputAsset);</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;encodeTask.OutputAssets.AddNew(inputAsset.Name + " as " + " mp4 output asset", AssetCreationOptions.None);</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; job.StateChanged += new EventHandler&lt;JobStateChangedEventArgs&gt;(JobStateChanged);</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; job.Submit();</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; job.GetExecutionProgressTask(CancellationToken.None).Wait();</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return job;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void JobStateChanged(object sender, JobStateChangedEventArgs e)</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(string.Format("{0}\n&nbsp; State: {1}\n&nbsp; Time: {2}\n\n",</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ((IJob)sender).Name, e.CurrentState, DateTime.UtcNow.ToString(@"yyyy_M_d__hh_mm_ss")));</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void WriteToFile(string outFilePath, string fileContent)</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StreamWriter sr = File.CreateText(outFilePath);</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sr.Write(fileContent);</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sr.Close();</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static string GetDynamicStreamingUrl(CloudMediaContext context, string outputAssetId, LocatorType type)</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;{</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var daysForWhichStreamingUrlIsActive = 365;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var outputAsset = context.Assets.Where(a =&gt; a.Id == outputAssetId).FirstOrDefault();</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var accessPolicy = context.AccessPolicies.Create(outputAsset.Name,</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TimeSpan.FromDays(daysForWhichStreamingUrlIsActive),</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AccessPermissions.Read | AccessPermissions.List);</span></p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var assetFiles = outputAsset.AssetFiles.ToList();</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (type == LocatorType.OnDemandOrigin)</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var assetFile = assetFiles.Where(f =&gt; f.Name.ToLower().EndsWith(".ism")).FirstOrDefault();</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (assetFile != null)</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var locator = context.Locators.CreateLocator(LocatorType.OnDemandOrigin, outputAsset, accessPolicy);</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Uri smoothUri = new Uri(locator.Path + assetFile.Name + "/manifest");</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return smoothUri.ToString();</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (type == LocatorType.Sas)</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var mp4Files = assetFiles.Where(f =&gt; f.Name.ToLower().EndsWith(".mp4")).ToList();</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var assetFile = mp4Files.OrderBy(f =&gt; f.ContentFileSize).LastOrDefault(); //Get Largest File</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (assetFile != null)</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var locator = context.Locators.CreateLocator(LocatorType.Sas, outputAsset, accessPolicy);</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var mp4Uri = new UriBuilder(locator.Path);</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mp4Uri.Path += "/" + assetFile.Name;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return mp4Uri.ToString();</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return string.Empty;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static IJob ThumbnailMaker(CloudMediaContext context, string inputAssetId)</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span></p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var inputAsset = context.Assets.Where(a =&gt; a.Id == inputAssetId).FirstOrDefault();</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (inputAsset == null)</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new ArgumentException("Could not find assetId: " + inputAssetId);</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IMediaProcessor latestWameMediaProcessor = (from p in context.MediaProcessors where p.Name == "Windows Azure Media Encoder" select p).ToList()</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .OrderBy(wame =&gt; new Version(wame.Version)).LastOrDefault();</span></p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //thumbnail</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Get thumbnail configuration from a XML file</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var ThumbnailConfig = File.ReadAllText(configFilePath);</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Create a job</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IJob jobThumbnail = context.Jobs.Create("Thumbnail job Thumbnail Making " + inputAsset.Name);</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Create a task</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ITask thumbnailTask = jobThumbnail.Tasks.AddNew("Thumbnail task",</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; latestWameMediaProcessor,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ThumbnailConfig,</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TaskOptions.None);</span></p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; thumbnailTask.InputAssets.Add(inputAsset);</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; thumbnailTask.OutputAssets.AddNew(inputAsset.Name + " as Thumbnail job", AssetCreationOptions.None);</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jobThumbnail.StateChanged += new EventHandler&lt;JobStateChangedEventArgs&gt;(JobStateChanged);</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jobThumbnail.Submit();</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jobThumbnail.GetExecutionProgressTask(CancellationToken.None).Wait();</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return jobThumbnail;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static string GetThumbnailUrl(CloudMediaContext context, IAsset outputAsset)</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var output = outputAsset; </span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var accessPolicy = context.AccessPolicies.Create("Read Policy", TimeSpan.FromDays(10), AccessPermissions.Read);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var locator = context.Locators.CreateSasLocator(output, accessPolicy);</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var primaryFile = (from a in output.AssetFiles</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where a.IsPrimary == true</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; select a).FirstOrDefault();</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return locator.BaseUri + '/' + primaryFile.Name + locator.ContentAccessComponent;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp; }</span></p>
<p><span style="font-size: small;">最终我们可以获得编码后的视频缩略图地址、<span style="font-family: Calibri;">MP4 </span>文件地址（可以直接用于网页，使用<span style="font-family: Calibri;">Video tag</span>）、<span style="font-family: Calibri;">Smooth Streaming, HLS, MPEG-DASH</span>地址：</span></p>
<p><span style="font-family: Calibri;"><span style="font-size: small;">Thumbnail URL: <a href="https://myappsstorage.blob.core.windows.net/asset-e157385d-1500-80c2-af19-f1e4cbb3271f/azure_1280x720_00.00.00.6346000_1_3-16-2015_8.06%20AM.jpg?sv=2012-02-12&amp;sr=c&amp;si=804d04b5-3450-4d00-9ed8-8d16913c2330&amp;sig=n7chFUFuHRA3R9RMpknxvFBkCbsG2kDgx0VWd6AJfiE%3D&amp;se=2015-03-26T08%3A06%3A18Z"><span style="color: #0563c1;">https://myappsstorage.blob.core.windows.net/asset-e157385d-1500-80c2-af19-f1e4cbb3271f/azure_1280x720_00.00.00.6346000_1_3-16-2015_8.06%20AM.jpg?sv=2012-02-12&amp;sr=c&amp;si=804d04b5-3450-4d00-9ed8-8d16913c2330&amp;sig=n7chFUFuHRA3R9RMpknxvFBkCbsG2kDgx0VWd6AJfiE%3D&amp;se=2015-03-26T08%3A06%3A18Z</span></a></span></span></p>
<p><span style="font-family: Calibri;"><span style="font-size: small;">MP4 URL: </span></span><a href="https://myappsstorage.blob.core.windows.net/asset-e157385d-1500-80c2-9cfd-f1e4cbb3517b/azure_H264_3400kbps_AAC_und_ch2_96kbps.mp4?sv=2012-02-12&amp;sr=c&amp;si=150c9ab8-a78c-4557-aab8-1deba001a998&amp;sig=pcl58cJgJ8lxRPSic4tM0us5wMSON8MIEUPDZBsXa3Y%3D&amp;se=2016-03-15T08%3A07%3A30Z"><span style="color: #0563c1; font-family: Calibri; font-size: small;">https://myappsstorage.blob.core.windows.net:443/asset-e157385d-1500-80c2-9cfd-f1e4cbb3517b/azure_H264_3400kbps_AAC_und_ch2_96kbps.mp4?sv=2012-02-12&amp;sr=c&amp;si=150c9ab8-a78c-4557-aab8-1deba001a998&amp;sig=pcl58cJgJ8lxRPSic4tM0us5wMSON8MIEUPDZBsXa3Y%3D&amp;se=2016-03-15T08%3A07%3A30Z</span></a></p>
<p><span style="font-family: Calibri;"><span style="font-size: small;">Smooth Streaming URL: &nbsp;&nbsp;</span></span><a href="https://test20140404.origin.mediaservices.windows.net/e5b3f1e4-a662-41da-b8af-4423aaea492b/azure.ism/manifest"><span style="color: #0563c1; font-family: Calibri; font-size: small;">https://test20140404.origin.mediaservices.windows.net/e5b3f1e4-a662-41da-b8af-4423aaea492b/azure.ism/manifest</span></a></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">HLS</span>：<a href="https://test20140404.origin.mediaservices.windows.net/e5b3f1e4-a662-41da-b8af-4423aaea492b/azure.ism/manifest(format=m3u8-aapl)"><span style="color: #0563c1; font-family: Calibri;">https://test20140404.origin.mediaservices.windows.net/e5b3f1e4-a662-41da-b8af-4423aaea492b/azure.ism/manifest(format=m3u8-aapl)</span></a></span></p>
<p><span style="font-family: Calibri; font-size: small;">MPEG-DASH: </span><a href="https://test20140404.origin.mediaservices.windows.net/e5b3f1e4-a662-41da-b8af-4423aaea492b/azure.ism/manifest(format=mpd-time-csf)"><span style="color: #0563c1; font-family: Calibri; font-size: small;">https://test20140404.origin.mediaservices.windows.net/e5b3f1e4-a662-41da-b8af-4423aaea492b/azure.ism/manifest(format=mpd-time-csf)</span></a></p>
<p><span style="font-family: Calibri; font-size: small;">&nbsp;</span></p>
<p><span style="font-size: small;">自适应流媒体的最大的特征是根据客户端的网络带宽情况自适应地选择对应码流媒体内容进行传输，保证流畅的视频播放体验，因此需要特殊的客户端播放器。对于这<span style="font-family: Calibri;">3</span>种常用的流媒体格式，可以使用如下播放器进行测试：</span></p>
<p><span style="font-family: Calibri; font-size: small;">Smooth Streaming player: </span><a href="https://smf.cloudapp.net/healthmonitor"><span style="color: #0563c1; font-family: Calibri; font-size: small;">https://smf.cloudapp.net/healthmonitor</span></a></p>
<p><span style="font-family: Calibri; font-size: small;">HLS: JW player: </span><a href="https://www.jwplayer.com/partners/azure/"><span style="color: #0563c1; font-family: Calibri; font-size: small;">https://www.jwplayer.com/partners/azure/</span></a></p>
<p><span style="font-family: Calibri; font-size: small;">MPEG-DASH player: </span><a href="https://dashplayer.azurewebsites.net/"><span style="color: #0563c1; font-family: Calibri; font-size: small;">https://dashplayer.azurewebsites.net/</span></a></p>
<p><span style="font-family: Calibri; font-size: small;">&nbsp;</span></p>
<p><span style="font-size: small;">更多关于微软云平台的媒体服务的使用实践内容，将在后续文章中介绍，敬请期待！</span></p>]]></content:encoded>
    </item>
    <item>
      <title>微软云平台媒体服务实践系列 1- 使用静态封装为iOS, Android 设备实现点播（VoD）方案</title>
      <link>https://docs.microsoft.com/archive/blogs/lj/1-ios-android-23454</link>
      <pubDate>Mon, 09 Feb 2015 02:44:12 GMT</pubDate>
      <dc:creator><![CDATA[JennyLi-MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/lj/2015/02/09/1-ios-android-23454/</guid>
      <description><![CDATA[微软的云平台媒体服务为流媒体服务提供了多种选择，在使用流媒体服务为企业做流媒体方案时，首先需要确认要流媒体接收目标，如针对广大iOS, Android移动设备，由于它们都支持HLS...]]></description>
      <content:encoded><![CDATA[<p><span style="font-size: small;">微软的云平台<a href="https://msdn.microsoft.com/zh-cn/library/azure/hh973629.aspx"><span style="color: #0563c1;">媒体服务</span></a>为流媒体服务提供了多种选择，在使用流媒体服务为企业做流媒体方案时，首先需要确认要流媒体接收目标，如针对广大<span style="font-family: Calibri;">iOS, Android</span>移动设备，由于它们都支持<span style="font-family: Calibri;">HLS </span>格式的流媒体，基于该认知，比较推荐的是使用<a href="https://msdn.microsoft.com/zh-cn/library/azure/jj889436.aspx"><span style="color: #0563c1;">动态封装</span></a>，但是必须额外<a href="https://azure.microsoft.com/en-us/documentation/articles/media-services-how-to-scale/"><span style="color: #0563c1;">添加流式处理单元</span></a>，方法是在<span style="font-family: Calibri;">Azure </span>门户，点击媒体服务，然后点击所使用的媒体服务，选择流式处理端点标签页，选择需要编辑的流媒体端点，然后再缩放标签页下设置，如下截图所示</span></p>
<p><span style="font-family: Calibri; font-size: small;">&nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp; <a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/8640.01.jpg" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/8640.01.jpg"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/8640.01.jpg" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/8640.01.jpg" alt="" border="0" /></a><span style="font-family: Calibri; font-size: small;">&nbsp;</span></p>
<p><span style="font-size: small;">使用流式处理单元需要支付一定的费用，且最小单元就是<span style="font-family: Calibri;">200mbps</span>，根据文档<a href="https://mingfeiy.com/windows-azure-media-services-pricing-explanation"><span style="color: #0563c1; font-family: Calibri;">Windows Azure Media Services Pricing Details</span></a>内容引用如下，我们可以计算出：在使用<span style="font-family: Calibri;">1</span>个流式处理单元，使用<a href="https://msdn.microsoft.com/zh-cn/library/azure/dn619413.aspx"><span style="color: #0563c1; font-family: Calibri;">H264 Adaptive Bitrate MP4 Set 720p</span></a>（范围从<span style="font-family: Calibri;"> 3400 kbps </span>到<span style="font-family: Calibri;"> 400 kbps</span>）编码方式的情况下，同时可以观看流媒体的客户端个数约为<span style="font-family: Calibri;">47 </span>个（<span style="font-family: Calibri;">160/3.4</span>）。</span></p>
<p><span style="font-family: Times New Roman; font-size: small;">&ldquo;</span><span style="font-family: Simsun;"><strong><em>Question: How do I estimate # of on-demand streaming reserved&nbsp;unit I need?</em></strong></span></p>
<p><span style="font-family: Simsun;">Answer: For the most conservative estimate you can go directly with SLA limitations -&nbsp;i.e. total bandwidth is <strong>160 Mbps * # of RU&rsquo;s</strong>. To obtain an initial estimate you can take <strong>the # of concurrent customers * top bitrate that you are encoding video at</strong>. For most video&nbsp;business, I think it is always better to be conservative first and if you end up over provisioning, you could always reduce # of&nbsp;reserved&nbsp;unit.</span></p>
<p><span style="font-family: Calibri;"><span style="font-size: small;">&rdquo;</span></span></p>
<p><span style="font-size: small;">那么如果仅针对少数客户端，可能总数达不到<span style="font-family: Calibri;">47</span>个，那么出于节省开支的目的，我们还有其他方法吗？答案是肯定的，本文将详细介绍该方案。</span></p>
<p><span style="font-size: small;">针对<span style="font-family: Calibri;">iOS, Android </span>客户端，同时观看的客户端数比较少的点播情况下，我们可以使用<a href="https://msdn.microsoft.com/zh-cn/library/azure/jj129580.aspx"><span style="color: #0563c1;">静态封装</span></a>方法将编码后的文件包装成<span style="font-family: Calibri;">HLS</span>即可，这样就可以不使用流式处理单元，需要注意的是，由于<span style="font-family: Calibri;">Microsoft Azure Media Packager </span>和<span style="font-family: Calibri;"> Microsoft Azure Media Encryptor </span>将在<span style="font-family: Calibri;"> 2015 </span>年<span style="font-family: Calibri;"> 11 </span>月<span style="font-family: Calibri;"> 1 </span>日终结使用，所以本文方案在此日期之后不推荐使用。</span></p>
<p><span style="font-size: small;">在封装为<span style="font-family: Calibri;">HLS</span>格式之前，必须先将媒体文件转码成<span style="font-family: Calibri;">smooth streaming </span>格式，再使用<span style="font-family: Calibri;">&ldquo;Windows Azure Media Packager&rdquo;</span>将其封装为<span style="font-family: Calibri;">HLS</span>，然后再在<span style="font-family: Calibri;">iOS </span>设备和<span style="font-family: Calibri;">Android </span>设备上使用自带的浏览器测试<span style="font-family: Calibri;">HLS </span>格式的流媒体<span style="font-family: Calibri;">URL</span>。所以整个流程为：</span></p>
<p><span style="font-size: small;">原始媒体文件<span style="font-family: Calibri;">&mdash;&mdash;&gt;</span>转码为<span style="font-family: Calibri;">MP4</span>文件<span style="font-family: Calibri;">&mdash;&mdash;&gt;</span>将<span style="font-family: Calibri;">MP4</span>编码为<span style="font-family: Calibri;">SmoothStreaming </span>格式<span style="font-family: Calibri;">&mdash;&mdash;&gt;</span>将<span style="font-family: Calibri;">SmoothStreaming</span>格式输出封装为<span style="font-family: Calibri;">HLS</span>格式<span style="font-family: Calibri;">&mdash;&mdash;&gt;</span>获取静态<span style="font-family: Calibri;">HLS</span>流媒体<span style="font-family: Calibri;">URL&mdash;&mdash;&gt;</span>设备测试</span></p>
<p><span style="font-family: Calibri; font-size: small;">&nbsp;</span></p>
<p><span style="font-size: small;">需要使用到<span style="font-family: Calibri;">2</span>个配置文件：</span></p>
<ol>
<li><span style="font-family: Calibri; font-size: small;">1.</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-size: small;"><span style="font-family: Calibri;">MP4</span>转为<span style="font-family: Calibri;">smooth streaming </span>格式的配置文件：<span style="font-family: Calibri;">MediaPackager_MP4ToSmooth.xml</span>，内容如下：</span></li>
</ol>
<p><span style="font-family: Calibri; font-size: small;">&nbsp;</span></p>
<p><span style="font-family: Calibri;"><span style="font-size: small;">&nbsp;</span>&lt;?xml version="1.0" encoding="utf-8"?&gt;</span></p>
<p><span style="font-family: Calibri;">&lt;taskDefinition xmlns="https://schemas.microsoft.com/iis/media/v4/TM/TaskDefinition#"&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp; &lt;name&gt;MP4 to Smooth Streams&lt;/name&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp; &lt;id&gt;5e1e1a1c-bba6-11df-8991-0019d1916af0&lt;/id&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp; &lt;description xml:lang="en" /&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp; &lt;inputFolder /&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp; &lt;properties namespace="https://schemas.microsoft.com/iis/media/V4/TM/MP4ToSmooth#" prefix="mp4"&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp; &lt;property name="keepSourceNames" value="false" /&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp; &lt;/properties&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp; &lt;taskCode&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp; &lt;type&gt;Microsoft.Web.Media.TransformManager.MP4toSmooth.MP4toSmooth_Task, Microsoft.Web.Media.TransformManager.MP4toSmooth, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35&lt;/type&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp; &lt;/taskCode&gt;</span></p>
<p><span style="font-family: Calibri;">&lt;/taskDefinition&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<ol>
<li><span style="font-family: Calibri; font-size: small;">2.</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-size: small;"><span style="font-family: Calibri;">packager </span>配置文件<span style="font-family: Calibri;">MediaPackager_MP4ToSmooth.xml</span>，内容如下：</span></li>
</ol>
<p><span style="font-family: Calibri; font-size: small;">&nbsp;</span></p>
<p><span style="font-family: Calibri;">&lt;?xml version="1.0" encoding="utf-8" ?&gt;</span></p>
<p><span style="font-family: Calibri;">&lt;taskDefinition xmlns="https://schemas.microsoft.com/iis/media/v4/TM/TaskDefinition#"&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp; &lt;name&gt;Smooth Streams to Apple HTTP Live Streams&lt;/name&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp; &lt;id&gt;A72D7A5D-3022-45f2-89B4-1DDC5457C111&lt;/id&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp; &lt;description xml:lang="en"&gt;Converts on-demand Smooth Streams encoded with H.264 (AVC) video and AAC-LC audio codecs to Apple HTTP Live Streams (MPEG-2 TS) and creates an Apple HTTP Live Streaming playlist (.m3u8) file for the converted presentation.&lt;/description&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp; &lt;inputDirectory&gt;&lt;/inputDirectory&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp; &lt;outputFolder&gt;TS_Out&lt;/outputFolder&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp; &lt;properties namespace="https://schemas.microsoft.com/iis/media/AppleHTTP#" prefix="hls"&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp; &lt;property name="maxbitrate" required="true" value="6600000" helpText="The maximum bit rate, in bits per second (bps), to be converted to MPEG-2 TS. On-demand Smooth Streams at or below this value are converted to MPEG-2 TS segments. Smooth Streams above this value are not converted. Most Apple devices can play media encoded at bit rates up to 1,600 Kbps."/&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp; &lt;property name="manifest" required="false" value="" helpText="The file name to use for the converted Apple HTTP Live Streaming playlist file (a file with an .m3u8 file name extension). If no value is specified, the following default value is used: &amp;lt;ISM_file_name&amp;gt;-m3u8-aapl.m3u8"/&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp; &lt;property name="segment" required="false" value="10" helpText="The duration of each MPEG-2 TS segment, in seconds. 10 seconds is the Apple-recommended setting for most Apple mobile digital devices."/&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp; &lt;property name="log"&nbsp; required="false" value="" helpText="The file name to use for a log file (with a .log file name extension) that records the conversion activity. If you specify a log file name, the file is stored in the task output folder." /&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp; &lt;property name="encrypt"&nbsp; required="false" value="false" helpText="Enables encryption of MPEG-2 TS segments by using the Advanced Encryption Standard (AES) with a 128-bit key (AES-128)." /&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp; &lt;property name="pid"&nbsp; required="false" value="" helpText="The program ID of the MPEG-2 TS presentation. Different encodings of MPEG-2 TS streams in the same presentation use the same program ID so that clients can easily switch between bit rates." /&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp; &lt;property name="codecs"&nbsp; required="false" value="false" helpText="Enables codec format identifiers, as defined by RFC 4281, to be included in the Apple HTTP Live Streaming playlist (.m3u8) file." /&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp; &lt;property name="backwardcompatible"&nbsp; required="false" value="false" helpText="Enables playback of the MPEG-2 TS presentation on devices that use the Apple iOS 3.0 mobile operating system." /&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp; &lt;property name="allowcaching"&nbsp; required="false" value="true" helpText="Enables the MPEG-2 TS segments to be cached on Apple devices for later playback." /&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp; &lt;property name="key"&nbsp; required="false" value="" helpText="The hexadecimal representation of the 16-octet content key value that is used for encryption." /&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp; &lt;property name="keyuri"&nbsp; required="false" value="" helpText="An alternate URI to be used by clients for downloading the key file. If no value is specified, it is assumed that the Live Smooth Streaming publishing point provides the key file." /&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp; &lt;property name="overwrite"&nbsp; required="false" value="true" helpText="Enables existing files in the output folder to be overwritten if converted output files have identical file names." /&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp; &lt;/properties&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp; &lt;taskCode&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp; &lt;type&gt;Microsoft.Web.Media.TransformManager.SmoothToHLS.SmoothToHLSTask, Microsoft.Web.Media.TransformManager.SmoothToHLS, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35&lt;/type&gt;</span></p>
<p><span style="font-family: Calibri;">&nbsp; &lt;/taskCode&gt;</span></p>
<p><span style="font-family: Calibri;">&lt;/taskDefinition&gt;</span></p>
<p><span style="font-family: Calibri; font-size: small;">&nbsp;</span></p>
<p><span style="font-size: small;">代码可以参考如下：（使用流媒体服务<span style="font-family: Calibri;">.Net SDK</span>，注意指定媒体服务的账号名字及<span style="font-family: Calibri;">key</span>）</span></p>
<p>class Program</p>
<p>&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static string accName = "[MediaService accountName]";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static string accKey = "[MediaService accountKey]";</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static readonly string _supportFiles =</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Path.GetFullPath(@"../..\..\..\..\");</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Paths to support files (within the above base path). You can use</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // the provided sample media files from the "supportFiles" folder, or</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // provide paths to your own media files below to run these samples.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static readonly string singleInputFilePath =</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Path.GetFullPath(_supportFiles + @"\azure.wmv");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static readonly string outputPath = _supportFiles;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static CloudMediaContext context;</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void Main(string[] args)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; context = new CloudMediaContext(accName, accKey);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string inputAssetId = CreateAssetAndUploadFile(context);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //encode to MP4</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IJob job = EncodeToMp4(context, inputAssetId);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IAsset mp4Output = job.OutputMediaAssets.FirstOrDefault();</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //convert MP4 to smooth streaming</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IJob jobSS = ConvertMP4toSmooth(context, mp4Output, mp4Output.Id);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IAsset ssAsset = jobSS.OutputMediaAssets.FirstOrDefault();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string SSStreamingUrlStatic = GetStaticSS(context, ssAsset.Id, LocatorType.OnDemandOrigin);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //package ss to HLS-Static Packaging</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IJob jobHLS = SmoothToHLS(context, ssAsset.Id, ssAsset);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var hlsAsset = jobHLS.OutputMediaAssets.FirstOrDefault();</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string hlsStreamingUrlStatic = GetStaticHLS(context, hlsAsset.Id, LocatorType.OnDemandOrigin);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string content = "\n Static Packaging Smooth Streaming Url:&nbsp;&nbsp;&nbsp; \n" + SSStreamingUrlStatic +</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "\n Static Packaging HLS Url:&nbsp;&nbsp;&nbsp; \n" + hlsStreamingUrlStatic +</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "\n Mp4 Url:&nbsp;&nbsp;&nbsp; \n" + mp4StreamingUrl;</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("\n Static Packaging Smooth Streaming Url:&nbsp;&nbsp;&nbsp; \n" + SSStreamingUrlStatic);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("\n Static Packaging HLS Url:&nbsp;&nbsp;&nbsp; \n" + hlsStreamingUrlStatic);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("\n Mp4 Url:&nbsp;&nbsp;&nbsp; \n" + mp4StreamingUrl);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("\n Smooth Url: \n" + smoothStreamingUrl);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string outFilePath = Path.GetFullPath(outputPath + @"\" + "StreamingUrl.txt");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WriteToFile(outFilePath, content);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.ReadKey();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.ReadKey();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static string CreateAssetAndUploadFile(CloudMediaContext context)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var assetName = Path.GetFileNameWithoutExtension(singleInputFilePath);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var inputAsset = context.Assets.Create(assetName, AssetCreationOptions.None);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var assetFile = inputAsset.AssetFiles.Create(Path.GetFileName(singleInputFilePath));</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; assetFile.UploadProgressChanged += new EventHandler&lt;UploadProgressChangedEventArgs&gt;(assetFile_UploadProgressChanged);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; assetFile.Upload(singleInputFilePath);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return inputAsset.Id;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void assetFile_UploadProgressChanged(object sender, UploadProgressChangedEventArgs e)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(string.Format("{0}&nbsp;&nbsp; Progress: {1:0}&nbsp;&nbsp; Time: {2}", ((IAssetFile)sender).Name, e.Progress, DateTime.UtcNow.ToString(@"yyyy_M_d__hh_mm_ss")));</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static IJob EncodeToMp4(CloudMediaContext context, string inputAssetId)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var inputAsset = context.Assets.Where(a =&gt; a.Id == inputAssetId).FirstOrDefault();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (inputAsset == null)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new ArgumentException("Could not find assetId: " + inputAssetId);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var encodingPreset = "H264 Adaptive Bitrate MP4 Set 720p";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //var encodingPreset = "H264 Broadband 720p";</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IJob job = context.Jobs.Create(".Net Encoding&nbsp; " + inputAsset.Name + " to MP4 job");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;IMediaProcessor latestWameMediaProcessor = (from p in context.MediaProcessors where p.Name == "Windows Azure Media Encoder" select p).ToList()</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .OrderBy(wame =&gt; new Version(wame.Version)).LastOrDefault();</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ITask encodeTask = job.Tasks.AddNew(".Net Encoding to Mp4 Task ", latestWameMediaProcessor, encodingPreset, TaskOptions.None);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; encodeTask.InputAssets.Add(inputAsset);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; encodeTask.OutputAssets.AddNew(inputAsset.Name + " as " + " mp4 output asset", AssetCreationOptions.None);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; job.StateChanged += new EventHandler&lt;JobStateChangedEventArgs&gt;(JobStateChanged);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; job.Submit();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; job.GetExecutionProgressTask(CancellationToken.None).Wait();</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return job;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static IJob ConvertMP4toSmooth(CloudMediaContext context, IAsset assetToConvert, string inputAssetId)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var inputAsset = context.Assets.Where(a =&gt; a.Id == inputAssetId).FirstOrDefault();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (inputAsset == null)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new ArgumentException("Could not find assetId: " + inputAssetId);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IJob job = context.Jobs.Create("Conversion&nbsp; " + inputAsset.Name + " to Smooth Streaming job");</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string smoothconfig = Path.GetFullPath(_supportFiles + @"\MediaPackager_MP4ToSmooth.xml");</p>
<p>string configMp4ToSmooth = File.ReadAllText(Path.GetFullPath(smoothconfig));</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IMediaProcessor LatestPackager = (from p in context.MediaProcessors where p.Name == "Windows Azure Media Packager" select p).ToList()</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .OrderBy(wame =&gt; new Version(wame.Version)).LastOrDefault();</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ITask convertTask = job.Tasks.AddNew(".Net Conversion MP4 to Smooth Streaming Task for " + inputAsset.Name,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LatestPackager, configMp4ToSmooth, TaskOptions.None);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; convertTask.InputAssets.Add(assetToConvert);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; convertTask.OutputAssets.AddNew(".Net output-MP4 converted Smooth Streaming-" + inputAsset.Name, AssetCreationOptions.None);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; job.StateChanged += new EventHandler&lt;JobStateChangedEventArgs&gt;(JobStateChanged);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; job.Submit();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; job.GetExecutionProgressTask(CancellationToken.None).Wait();</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return job;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static IJob SmoothToHLS(CloudMediaContext context, string inputAssetId, IAsset asset)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var inputAsset = context.Assets.Where(a =&gt; a.Id == inputAssetId).FirstOrDefault();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (inputAsset == null)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new ArgumentException("Could not find assetId: " + inputAssetId);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var conversionPreset = "HLS";</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IJob job = context.Jobs.Create("Conversion " + inputAsset.Name + " to " + conversionPreset);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //var ssOutput = encodeTask.OutputAssets.AddNew("output-Silverlight-" + inputAsset.Name,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp; AssetCreationOptions.None);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string smooth2HLSFilePath = Path.GetFullPath(_supportFiles + @"\MediaPackager_SmoothToHLS.xml");</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var packager = context.MediaProcessors.Where(m =&gt; m.Name == "Windows Azure Media Packager").First();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var conversionTask = job.Tasks.AddNew("Conversion Task for " + inputAsset.Name, packager,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;File.ReadAllText(smooth2HLSFilePath), TaskOptions.None);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; conversionTask.InputAssets.Add(asset);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; conversionTask.OutputAssets.AddNew(</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "output-HLS-" + inputAsset.Name, AssetCreationOptions.None);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; job.StateChanged += new EventHandler&lt;JobStateChangedEventArgs&gt;(JobStateChanged);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; job.Submit();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; job.GetExecutionProgressTask(CancellationToken.None).Wait();</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return job;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void JobStateChanged(object sender, JobStateChangedEventArgs e)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(string.Format("{0}\n&nbsp; State: {1}\n&nbsp; Time: {2}\n\n",</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ((IJob)sender).Name, e.CurrentState, DateTime.UtcNow.ToString(@"yyyy_M_d__hh_mm_ss")));</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void WriteToFile(string outFilePath, string fileContent)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StreamWriter sr = File.CreateText(outFilePath);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sr.Write(fileContent);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sr.Close();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static string GetStaticSS(CloudMediaContext context, string outputAssetId, LocatorType type)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var daysForWhichStreamingUrlIsActive = 365;</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var outputAsset = context.Assets.Where(a =&gt; a.Id == outputAssetId).FirstOrDefault();</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var accessPolicy = context.AccessPolicies.Create(outputAsset.Name,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TimeSpan.FromDays(daysForWhichStreamingUrlIsActive),</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AccessPermissions.Read | AccessPermissions.List);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var assetFiles = outputAsset.AssetFiles.ToList();</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (type == LocatorType.OnDemandOrigin)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var assetFile = assetFiles.Where(f =&gt; f.Name.ToLower().EndsWith(".ism")).FirstOrDefault();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (assetFile != null)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var locator = context.Locators.CreateLocator(LocatorType.OnDemandOrigin, outputAsset, accessPolicy);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Uri smoothUri = new Uri(locator.Path + assetFile.Name + "/manifest");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return smoothUri.ToString();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (type == LocatorType.Sas)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var mp4Files = assetFiles.Where(f =&gt; f.Name.ToLower().EndsWith(".mp4")).ToList();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var assetFile = mp4Files.OrderBy(f =&gt; f.ContentFileSize).LastOrDefault(); //Get Largest File</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (assetFile != null)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var locator = context.Locators.CreateLocator(LocatorType.Sas, outputAsset, accessPolicy);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var mp4Uri = new UriBuilder(locator.Path);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mp4Uri.Path += "/" + assetFile.Name;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return mp4Uri.ToString();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return string.Empty;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static string GetStaticHLS(CloudMediaContext context, string outputAssetId, LocatorType type)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var daysForWhichStreamingUrlIsActive = 365;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var outputAsset = context.Assets.Where(a =&gt; a.Id == outputAssetId).FirstOrDefault();</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var accessPolicy = context.AccessPolicies.Create(outputAsset.Name,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TimeSpan.FromDays(daysForWhichStreamingUrlIsActive),</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AccessPermissions.Read | AccessPermissions.List);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var assetFiles = outputAsset.AssetFiles.ToList();</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach (var f in assetFiles.Where(x =&gt; x.Name.EndsWith(".ism")))</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (f.Name.Contains("m3u8"))</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #region publish HLS to a WAMS origin</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("will create a new locator for HLS");</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var originLocator = context.Locators.CreateLocator(LocatorType.OnDemandOrigin, outputAsset, accessPolicy);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string urlForClientStreaming = originLocator.Path + f.Name</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + "/manifest(format=m3u8-aapl)";</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return urlForClientStreaming.ToString();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #endregion</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return string.Empty;</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p><span style="font-size: small;">最终输出如：<span style="font-family: Calibri;">https://test20140404.origin.mediaservices.windows.net/1dcaef59-56b1-4bf9-9dd2-8502d62d5095/azure-m3u8-aapl.ism/manifest(format=m3u8-aapl)</span></span></p>
<p><span style="font-family: Calibri; font-size: small;">&nbsp;</span></p>
<p><span style="font-size: small;">更多关于微软云平台的媒体服务的使用实践内容，将在后续文章中介绍，敬请期待！</span></p>]]></content:encoded>
    </item>
    <item>
      <title>基于Windows Azure Media Service REST API 进行Windows Store/Windows Phone 应用开发系列-Part 5发布流媒体</title>
      <link>https://docs.microsoft.com/archive/blogs/lj/windows-azure-media-service-rest-api-windows-storewindows-phone-part-5</link>
      <pubDate>Fri, 09 Jan 2015 19:47:36 GMT</pubDate>
      <dc:creator><![CDATA[JennyLi-MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/lj/2015/01/09/windows-azure-media-service-rest-api-windows-storewindows-phone-part-5/</guid>
      <description><![CDATA[在文章基于Windows Azure Media Service REST API 进行Windows Store/Windows Phone 应用开发系列-Part 1...]]></description>
      <content:encoded><![CDATA[<p><span style="font-size: small;">在文章</span><a href="https://blogs.msdn.com/b/lj/archive/2014/10/08/windows-azure-media-service-rest-api-windows-store-windows-phone-part-1.aspx"><span style="color: #0563c1;"><span style="font-size: small;">基于<span style="font-family: Calibri;">Windows Azure Media Service REST API </span>进行<span style="font-family: Calibri;">Windows Store/Windows Phone </span>应用开发系列<span style="font-family: Calibri;">-Part 1 </span>简介</span></span></a><span style="font-size: small;">中介绍了基于<span style="font-family: Calibri;">Windows Azure Media Service(Windows Azure </span>媒体服务，简称<span style="font-family: Calibri;">WAMS)</span>进行应用开发的相关信息及包含的基本流程，在文章</span><a href="https://blogs.msdn.com/b/lj/archive/2014/10/08/windows-azure-media-service-rest-api-windows-store-windows-phone-part-2-wams.aspx"><span style="color: #0563c1;"><span style="font-size: small;">基于<span style="font-family: Calibri;">Windows Azure Media Service REST API </span>进行<span style="font-family: Calibri;">Windows Store/Windows Phone </span>应用开发系列<span style="font-family: Calibri;">-Part 2</span>初始设置链接到<span style="font-family: Calibri;">WAMS</span></span></span></a><span style="font-size: small;">中介绍了如何使用<span style="font-family: Calibri;">REST API</span>进行<span style="font-family: Calibri;">WAMS</span>的链接，然后在</span><a href="https://blogs.msdn.com/b/lj/archive/2014/11/28/windows-azure-media-service-rest-api-windows-store-windows-phone-part-3-wams.aspx"><span style="color: #0563c1;"><span style="font-size: small;">基于<span style="font-family: Calibri;">Windows Azure Media Service REST API </span>进行<span style="font-family: Calibri;">Windows Store/Windows Phone </span>应用开发系列<span style="font-family: Calibri;">-Part 3</span>上传媒体到<span style="font-family: Calibri;">WAMS</span></span></span></a><span style="font-size: small;">中少如何将媒体文件上传到媒体服务，并在基于<span style="font-family: Calibri;">Windows Azure Media Service REST API </span>进行<span style="font-family: Calibri;">Windows Store/Windows Phone </span>应用开发系列<span style="font-family: Calibri;">-Part 3</span>媒体编码中详细介绍了如何对媒体服务中媒体文件创建编码作业对其编码，并查看编码进程。当编码工作结束后，我们就可以进行流媒体发布工作了，这也正是本文包含的内容。</span></p>
<p><span style="font-size: small;">本文将基于前面<span style="font-family: Calibri;">4</span>篇内容进一步讲解如何对编码输出的文件进行流媒体的发布工作。</span></p>
<p><span style="font-size: small;">使用<span style="font-family: Calibri;">REST API</span>发布流媒体，主要流程是：</span></p>
<ol>
<li><span style="font-size: small;">创建具有读取权限的<span style="font-family: Calibri;">AccessPolicy</span></span></li>
<li><span style="font-size: small;">创建用于传输媒体内容的源<span style="font-family: Calibri;">URL</span>，再在此<span style="font-family: Calibri;">URL</span>上构建最终的流媒体<span style="font-family: Calibri;">URL</span></span></li>
</ol>
<p><span style="font-size: small;">请注意，如前文所强调的在使用<span style="font-family: Calibri;">REST API</span>时访问媒体服务中的实体时，必须在<span style="font-family: Calibri;">HTTP</span>请求中添加如下必须的标头字段和值；<span style="font-family: Calibri;">WAMS </span>的原始服务<span style="font-family: Calibri;">URI </span>为</span><a href="https://media.windows.net/"><span style="color: #0563c1; font-family: Calibri; font-size: small;">https://media.windows.net/</span></a><span style="font-size: small;">，成功连接到此<span style="font-family: Calibri;"> URI</span>后，会收到一个<span style="font-family: Calibri;">&ldquo;301 </span>重定向<span style="font-family: Calibri;">&rdquo;</span>响应指向另一个媒体服务<span style="font-family: Calibri;">URI</span>，需要从该响应中提取出新的的媒体服务<span style="font-family: Calibri;">URI</span>，随后的调用都是基于该<span style="font-family: Calibri;"> URI</span>，详细内容参见</span><a href="https://blogs.msdn.com/b/lj/archive/2014/10/08/windows-azure-media-service-rest-api-windows-store-windows-phone-part-2-wams.aspx"><span style="color: #0563c1; font-family: Calibri; font-size: small;">Part2</span></a><span style="font-size: small;">内容。</span></p>
<p><span style="font-size: small;">根据文档</span><a href="https://msdn.microsoft.com/zh-cn/library/azure/hh973616.aspx"><span style="color: #0563c1;"><span style="font-size: small;">媒体服务<span style="font-family: Calibri;"> REST API </span>开发的设置</span></span></a><span style="font-size: small;">可知，每次调用<span style="font-family: Calibri;">WAMS</span>时，客户端必须在请求中包括必需的标头字段和值，列表如下：</span></p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="150">
<p><span style="font-size: small;"><span style="font-family: Calibri;">Header</span></span></p>
</td>
<td valign="top" width="144">
<p><span style="font-size: small;"><span style="font-family: Calibri;">Type</span></span></p>
</td>
<td valign="top" width="282">
<p><span style="font-size: small;"><span style="font-family: Calibri;">Value</span></span></p>
</td>
</tr>
<tr>
<td valign="top" width="150">
<p><span style="font-family: Calibri;">Authorization</span></p>
</td>
<td valign="top" width="144">
<p><span style="font-family: Calibri;">Bearer</span></p>
</td>
<td valign="top" width="282">
<p><span style="font-family: Calibri;">Bearer&nbsp;</span>是唯一接受的授权机制。</p>
<p>该值还必须包括由<span style="font-family: Calibri;"> ACS </span>提供的访问令牌。</p>
</td>
</tr>
<tr>
<td valign="top" width="150">
<p><span style="font-family: Calibri;">x-ms-version</span></p>
</td>
<td valign="top" width="144">
<p><span style="font-family: Calibri;">Decimal</span></p>
</td>
<td valign="top" width="282">
<p><span style="font-family: Calibri;">2.7</span></p>
</td>
</tr>
<tr>
<td valign="top" width="150">
<p><span style="font-family: Calibri;">DataServiceVersion</span></p>
</td>
<td valign="top" width="144">
<p><span style="font-family: Calibri;">Decimal</span></p>
</td>
<td valign="top" width="282">
<p><span style="font-family: Calibri;">3.0</span></p>
</td>
</tr>
<tr>
<td valign="top" width="150">
<p><span style="font-family: Calibri;">MaxDataServiceVersion</span></p>
</td>
<td valign="top" width="144">
<p><span style="font-family: Calibri;">Decimal</span></p>
</td>
<td valign="top" width="282">
<p><span style="font-family: Calibri;">3.0</span></p>
</td>
</tr>
</tbody>
</table>
<p><span style="font-family: Calibri; font-size: small;">&nbsp;</span></p>
<p><span style="font-size: small;">在传输任何媒体内容之前，必须先创建具有读取权限的<span style="font-family: Calibri;">AccessPolicy</span>，然后创建相应的定位符地址，以便指定将要传输的流媒体类型（如微软的自适应流媒体协议<span style="font-family: Calibri;">smooth streaming, apple </span>的<span style="font-family: Calibri;">HLS</span>，国际标准<span style="font-family: Calibri;">MPEG DASH</span>），此处<span style="font-family: Calibri;">AccessPolicy</span>的请求如前文<a href="https://blogs.msdn.com/b/lj/archive/2014/11/28/windows-azure-media-service-rest-api-windows-store-windows-phone-part-3-wams.aspx"><span style="color: #0563c1;">上传文件</span></a>时所用的请求类似，唯一的区别在于构造请求<span style="font-family: Calibri;">body</span>内容时指定<span style="font-family: Calibri;">Permission=1</span>，当然，为了以示区别，也<span style="font-family: Calibri;">AccessPolicy </span>指定不同的<span style="font-family: Calibri;">Name</span>。由于<a href="https://blogs.msdn.com/b/lj/archive/2014/11/28/windows-azure-media-service-rest-api-windows-store-windows-phone-part-3-wams.aspx"><span style="color: #0563c1;">文章<span style="font-family: Calibri;">3</span></span></a>已做讲解，这里省略了细节实现内容。</span></p>
<p><span style="font-size: small;">理论上来说接下来就可以创建用于传输媒体内容的源<span style="font-family: Calibri;">URL</span>了，但是在此操作之前我们需要先获取编码输出文件所在的位置，进而发布此位置中包含的文件。</span></p>
<p><span style="font-size: small;">执行过程可参考如下代码，返回文件所在位置：</span></p>
<p>&nbsp; private async Task&lt;string&gt; GetOutputAssetAsync(string acsToken, string wamsEndpoint, string jobId)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AuthenticationHeaderValue header = CreateBasicAuthenticationHeader(acsToken);&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpClient httpClient = new HttpClient();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.MaxResponseContentBufferSize = int.MaxValue;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("Authorization", header.ToString());</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("x-ms-version", "2.7");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;httpClient.DefaultRequestHeaders.Add("DataServiceVersion", "3.0");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("MaxDataServiceVersion", "3.0");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string url = wamsEndpoint + "Jobs('" + WebUtility.UrlEncode(jobId) + "')/OutputMediaAssets()";&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var response = await httpClient.GetAsync(url);&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string ouputId = null;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (response.IsSuccessStatusCode)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var content = await response.Content.ReadAsStringAsync();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JObject jsonObject = JObject.Parse(content);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var value = jsonObject.Value&lt;JArray&gt;("value");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ouputId = value.First.Value&lt;string&gt;("Id");&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return ouputId;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return null;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p><span style="font-size: small;">现在我们就可以正式创建流媒体地址了，首先创建用于传输媒体内容的源<span style="font-family: Calibri;">URL-locatorURL</span>，再在此<span style="font-family: Calibri;">URL</span>上构建最终的流媒体<span style="font-family: Calibri;">URL</span>，操作很简单，即根据流媒体类型，添加相应的后缀内容即可：</span></p>
<p><span style="font-family: Calibri; font-size: small;">1）</span> <span style="font-size: small;"><span style="font-family: Calibri;">Smooth streaming:&nbsp; locatorURL/<strong>filename.ism/manifest</strong></span></span></p>
<p><span style="font-family: Calibri; font-size: small;">2）</span> <span style="font-size: small;"><span style="font-family: Calibri;">HLS V4: locatorURL/<strong>filename.ism/manifest(format=m3u8-aapl) </strong></span></span></p>
<p><span style="font-family: Calibri; font-size: small;">3）</span> <span style="font-size: small;"><span style="font-family: Calibri;">HLS V3: locatorURL/<strong>filename.ism/manifest(format=m3u8-aapl-v3) </strong></span></span></p>
<p><span style="font-family: Calibri; font-size: small;">4）</span> <span style="font-family: Calibri;"><span style="font-size: small;">MPEG DASH: locatorURL/<strong>filename.ism/manifest(format=mpd-time-csf)</strong></span></span></p>
<p><span style="font-size: small;">由于此处是针对<span style="font-family: Calibri;">windows </span>平台，只支持<span style="font-family: Calibri;">smooth streaming, </span>所以以下代码仅构建<span style="font-family: Calibri;">smooth streaming</span>的<span style="font-family: Calibri;">URL.</span></span></p>
<p>创建用于传输的源<span style="font-family: Calibri;">URL</span>的请求简要总结如下，详情请参见：<a href="https://msdn.microsoft.com/zh-cn/library/azure/jj129578.aspx"><span style="color: #0563c1;">使用<span style="font-family: Calibri;"> Media Services REST API </span>传送资产</span></a></p>
<table style="width: 672px;" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="138">
<p><span style="font-family: Calibri;">EndPoint</span></p>
</td>
<td valign="top" width="534">
<p><a href="https://media.windows.net/API/Locators"><span style="color: #0563c1; font-family: Calibri;">https://media.windows.net/API/Locators</span></a><span style="font-family: Calibri;"> &nbsp;<span style="text-decoration: underline;"><span style="color: #0563c1;">&nbsp;</span></span></span></p>
<p>或重定向后的新的<span style="font-family: Calibri;">URI/Locators <span style="text-decoration: underline;"><span style="color: #0563c1;">&nbsp;</span></span></span></p>
</td>
</tr>
<tr>
<td valign="top" width="138">
<p><strong>HTTP Method</strong></p>
</td>
<td valign="top" width="534">
<p><span style="font-family: Calibri;">GET</span></p>
</td>
</tr>
<tr>
<td valign="top" width="138">
<p><strong>Request Headers</strong></p>
</td>
<td valign="top" width="534">
<p><span style="font-family: Calibri;">DataServiceVersion:&nbsp; 3.0<br />MaxDataServiceVersion: 3.0<br />x-ms-version: 2.7<br />Authorization:&nbsp;&nbsp; Bear + ACSToken</span></p>
</td>
</tr>
<tr>
<td valign="top" width="138">
<p><strong>Request Content Type</strong></p>
</td>
<td valign="top" width="534">
<p><span style="font-family: Calibri;">application/json; odata=verbose</span></p>
</td>
</tr>
<tr>
<td valign="top" width="138">
<p><strong>Request Body Format</strong></p>
</td>
<td valign="top" width="534">
<pre><span style="font-family: Courier New; font-size: x-small;">{<br /> &nbsp;&nbsp;&nbsp; </span><span style="font-size: x-small;">"AccessPolicyId": "&lt; AccessPolicyId &gt;"),<br /> &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&ldquo;AssetId&rdquo;: &ldquo;&lt;encoded output assetId&gt;&rdquo;,</span></pre>
<pre><span style="font-size: x-small;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&ldquo;StartTime&rdquo;: &ldquo;&lt;DateTime.UtcNow &gt;&rdquo;,</span></pre>
<pre><span style="font-size: x-small;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&ldquo;Type&rdquo;: &ldquo;2&rdquo;</span></pre>
<pre><span style="font-size: x-small;">}</span></pre>
</td>
</tr>
</tbody>
</table>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p><span style="font-size: small;">执行过程可参考如下代码，</span></p>
<p>&nbsp; private async Task&lt;string&gt; CreateSStreamingUrlAsync(string acsToken, string wamsEndPoint, string encodingJobId)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string outputAssetId = await GetOutputAssetAsync(acsToken, wamsEndPoint, encodingJobId);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string apID = await CreateAccessPolicyAsync(acsToken, wamsEndPoint, "DownloadPolicy", 1);&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AuthenticationHeaderValue header = CreateBasicAuthenticationHeader(acsToken);&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpClient httpClient = new HttpClient();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.MaxResponseContentBufferSize = int.MaxValue;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("Authorization", header.ToString());</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("x-ms-version", "2.7");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("DataServiceVersion", "3.0");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("MaxDataServiceVersion", "3.0");&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, wamsEndPoint);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String requestBody = "{ \"AccessPolicyId\" : \"" + apID + "\"," +</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " \"AssetId\" : \"" + outputAssetId + "\", " +</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " \"StartTime\" : \"" + DateTime.UtcNow.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss") + "\", " +</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " \"Type\" : " + "2" + "}";&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpContent body = new StringContent(requestBody, Encoding.UTF8, "application/json");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var response = await httpClient.PostAsync(wamsEndPoint + "Locators", body);&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string ssUrl = null; ;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (response.IsSuccessStatusCode)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var content = await response.Content.ReadAsStringAsync();&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlDocument xmlDoc = new XmlDocument();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlDoc.LoadXml(content);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlNodeList elemListBase = xmlDoc.GetElementsByTagName("d:Path");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach (var ele in elemListBase)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ssUrl = ele.InnerText;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ssUrl = ssUrl+MediaNamewithoutExtention + ".ism/manifest";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return ssUrl;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;</p>
<p>&nbsp;<span style="font-size: small;">同时我们可以在portal上发现出现了发布链接，且可以直接播放流媒体内容了，帮住我们检查结果。</span></p>
<p>&nbsp;</p>
<p>&nbsp;<a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/3365.PulishingURL.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/3365.PulishingURL.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/3365.PulishingURL.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/3365.PulishingURL.png" alt="" border="0" /></a></p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/2477.Playing.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/2477.Playing.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/2477.Playing.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/2477.Playing.png" alt="" border="0" /></a></p>
<p>&nbsp;</p>
<p>当然做为<span style="font-family: Calibri;">Windows Store/Phone</span>应用，我们需要使用特定的客户端<span style="font-family: Calibri;">SDK</span>播放流媒体内容，对于<span style="font-family: Calibri;">Windows Store </span>应用，使用<a href="https://visualstudiogallery.msdn.microsoft.com/04423d13-3b3e-4741-a01c-1ae29e84fea6?SRC=Homehttps://visualstudiogallery.msdn.microsoft.com/04423d13-3b3e-4741-a01c-1ae29e84fea6?SRC=Home"><span style="color: #0563c1; font-family: Calibri;">Microsoft Smooth Streaming Client SDK for Windows 8</span></a>；对于<span style="font-family: Calibri;">Windows Phone </span>应用，使用<a href="https://visualstudiogallery.msdn.microsoft.com/b837ddf3-6884-436e-aeb7-35c6151a8933?SRC=Home"><span style="color: #0563c1; font-family: Calibri;">Smooth Streaming Client SDK for Windows Phone 8.1</span></a>，而且文档<a href="https://azure.microsoft.com/en-us/documentation/articles/media-services-build-smooth-streaming-apps/"><span style="color: #0563c1; font-family: Calibri;">How to Build a Smooth Streaming Windows Store Application</span></a>详细讲解了其使用过程。</p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p>通过本系列文章，我们讲解了如何在<span style="font-family: Calibri;">WinRT </span>应用中使用媒体服务，为广大用户提供自适应流媒体体验。</p>]]></content:encoded>
    </item>
    <item>
      <title>基于Windows Azure Media Service REST API 进行Windows Store/Windows Phone 应用开发系列-Part 4媒体编码</title>
      <link>https://docs.microsoft.com/archive/blogs/lj/windows-azure-media-service-rest-api-windows-storewindows-phone-part-4</link>
      <pubDate>Fri, 09 Jan 2015 19:39:00 GMT</pubDate>
      <dc:creator><![CDATA[JennyLi-MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/lj/2015/01/09/windows-azure-media-service-rest-api-windows-storewindows-phone-part-4/</guid>
      <description><![CDATA[在文章基于Windows Azure Media Service REST API 进行Windows Store/Windows Phone 应用开发系列-Part 1...]]></description>
      <content:encoded><![CDATA[<p><span style="font-size: small;">在文章</span><a href="https://blogs.msdn.com/b/lj/archive/2014/10/08/windows-azure-media-service-rest-api-windows-store-windows-phone-part-1.aspx"><span style="color: #0563c1;"><span style="font-size: small;">基于<span style="font-family: Calibri;">Windows Azure Media Service REST API </span>进行<span style="font-family: Calibri;">Windows Store/Windows Phone </span>应用开发系列<span style="font-family: Calibri;">-Part 1 </span>简介</span></span></a><span style="font-size: small;">中介绍了基于<span style="font-family: Calibri;">Windows Azure Media Service(Windows Azure </span>媒体服务，简称<span style="font-family: Calibri;">WAMS)</span>进行应用开发的相关信息及包含的基本流程，在文章</span><a href="https://blogs.msdn.com/b/lj/archive/2014/10/08/windows-azure-media-service-rest-api-windows-store-windows-phone-part-2-wams.aspx"><span style="color: #0563c1;"><span style="font-size: small;">基于<span style="font-family: Calibri;">Windows Azure Media Service REST API </span>进行<span style="font-family: Calibri;">Windows Store/Windows Phone </span>应用开发系列<span style="font-family: Calibri;">-Part 2</span>初始设置链接到<span style="font-family: Calibri;">WAMS</span></span></span></a><span style="font-size: small;">中介绍了如何使用<span style="font-family: Calibri;">REST API</span>进行<span style="font-family: Calibri;">WAMS</span>的链接，然后在</span><a href="https://blogs.msdn.com/b/lj/archive/2014/11/28/windows-azure-media-service-rest-api-windows-store-windows-phone-part-3-wams.aspx"><span style="color: #0563c1;"><span style="font-size: small;">基于<span style="font-family: Calibri;">Windows Azure Media Service REST API </span>进行<span style="font-family: Calibri;">Windows Store/Windows Phone </span>应用开发系列<span style="font-family: Calibri;">-Part 3</span>上传媒体到<span style="font-family: Calibri;">WAMS</span></span></span></a><span style="font-size: small;">中少如何将媒体文件上传到媒体服务，本文将基于前面<span style="font-family: Calibri;">3</span>篇内容进一步讲解如何对已经上传的媒体文件进行编码进而发布流媒体服务。</span></p>
<p><span style="font-size: small;">使用<span style="font-family: Calibri;">REST API</span>对媒体文件进行编码，主要流程是：</span></p>
<ol>
<li><span style="font-size: small;">创建作业</span></li>
<li><span style="font-size: small;">编码过程交由媒体服务完成</span></li>
<li><span style="font-size: small;">监视处理进程</span></li>
</ol>
<p><span style="font-size: small;">请注意，如前文所强调的在使用<span style="font-family: Calibri;">REST API</span>时访问媒体服务中的实体时，必须在<span style="font-family: Calibri;">HTTP</span>请求中添加如下必须的标头字段和值；<span style="font-family: Calibri;">WAMS </span>的原始服务<span style="font-family: Calibri;">URI </span>为</span><a href="https://media.windows.net/"><span style="color: #0563c1; font-family: Calibri; font-size: small;">https://media.windows.net/</span></a><span style="font-size: small;">，成功连接到此<span style="font-family: Calibri;"> URI</span>后，会收到一个<span style="font-family: Calibri;">&ldquo;301 </span>重定向<span style="font-family: Calibri;">&rdquo;</span>响应指向另一个媒体服务<span style="font-family: Calibri;">URI</span>，需要从该响应中提取出新的的媒体服务<span style="font-family: Calibri;">URI</span>，随后的调用都是基于该<span style="font-family: Calibri;"> URI</span>，详细内容参见</span><a href="https://blogs.msdn.com/b/lj/archive/2014/10/08/windows-azure-media-service-rest-api-windows-store-windows-phone-part-2-wams.aspx"><span style="color: #0563c1; font-family: Calibri; font-size: small;">Part2</span></a><span style="font-size: small;">内容。</span></p>
<p><span style="font-size: small;">根据文档</span><a href="https://msdn.microsoft.com/zh-cn/library/azure/hh973616.aspx"><span style="color: #0563c1;"><span style="font-size: small;">媒体服务<span style="font-family: Calibri;"> REST API </span>开发的设置</span></span></a><span style="font-size: small;">可知，每次调用<span style="font-family: Calibri;">WAMS</span>时，客户端必须在请求中包括必需的标头字段和值，列表如下：</span></p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="150">
<p><span style="font-size: small;"><span style="font-family: Calibri;">Header</span></span></p>
</td>
<td valign="top" width="144">
<p><span style="font-size: small;"><span style="font-family: Calibri;">Type</span></span></p>
</td>
<td valign="top" width="282">
<p><span style="font-size: small;"><span style="font-family: Calibri;">Value</span></span></p>
</td>
</tr>
<tr>
<td valign="top" width="150">
<p><span style="font-family: Calibri;">Authorization</span></p>
</td>
<td valign="top" width="144">
<p><span style="font-family: Calibri;">Bearer</span></p>
</td>
<td valign="top" width="282">
<p><span style="font-family: Calibri;">Bearer&nbsp;</span>是唯一接受的授权机制。</p>
<p>该值还必须包括由<span style="font-family: Calibri;"> ACS </span>提供的访问令牌。</p>
</td>
</tr>
<tr>
<td valign="top" width="150">
<p><span style="font-family: Calibri;">x-ms-version</span></p>
</td>
<td valign="top" width="144">
<p><span style="font-family: Calibri;">Decimal</span></p>
</td>
<td valign="top" width="282">
<p><span style="font-family: Calibri;">2.7</span></p>
</td>
</tr>
<tr>
<td valign="top" width="150">
<p><span style="font-family: Calibri;">DataServiceVersion</span></p>
</td>
<td valign="top" width="144">
<p><span style="font-family: Calibri;">Decimal</span></p>
</td>
<td valign="top" width="282">
<p><span style="font-family: Calibri;">3.0</span></p>
</td>
</tr>
<tr>
<td valign="top" width="150">
<p><span style="font-family: Calibri;">MaxDataServiceVersion</span></p>
</td>
<td valign="top" width="144">
<p><span style="font-family: Calibri;">Decimal</span></p>
</td>
<td valign="top" width="282">
<p><span style="font-family: Calibri;">3.0</span></p>
</td>
</tr>
</tbody>
</table>
<p><span style="font-family: Calibri; font-size: small;">&nbsp;</span></p>
<p><span style="font-size: small;">首先创建作业，每个作业可以包含一个或多个任务，具体是什么任务视处理类型而定，如将媒体文件转换为<span style="font-family: Calibri;">MP4</span>文件的任务，或将<span style="font-family: Calibri;">MP4</span>文件编码为<span style="font-family: Calibri;">smooth streaming </span>输出的任务，或者进行编码后的文件进行<a href="https://msdn.microsoft.com/zh-cn/library/azure/jj129580.aspx"><span style="color: #0563c1;">静态封装</span></a>或</span><a href="https://msdn.microsoft.com/zh-cn/library/azure/jj889436.aspx"><span style="color: #0563c1; font-size: small;">动态封装</span></a><span style="font-size: small;">等任务。使用<span style="font-family: Calibri;">REST API</span>可以创建多个作业及其相应的任务，</span></p>
<p><span style="font-size: small;">此处以一个作业一个视频编码任务为例，具体的可选的编码配置可以参见<a href="https://msdn.microsoft.com/zh-cn/library/azure/dn619392.aspx"><span style="color: #0563c1;"><span style="font-family: Calibri;">Media Services Encoder </span>的任务预设</span></a>（如常用的<span style="font-family: Calibri;">H264 Smooth Streaming 720p</span>，<span style="font-family: Calibri;">H264 Adaptive Bitrate MP4 Set 720p</span>）。</span></p>
<p><span style="font-size: small;">创建编码作业请求简要总结如下，详情请参见：<a href="https://msdn.microsoft.com/zh-cn/library/azure/jj129574.aspx"><span style="color: #0563c1;">使用 Media Services REST API 创建编码作业</span></a> </span></p>
<table style="width: 672px;" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="138">
<p><span style="font-family: Calibri;">EndPoint</span></p>
</td>
<td valign="top" width="534">
<p><a href="https://media.windows.net/API/Jobs"><span style="color: #0563c1; font-family: Calibri;">https://media.windows.net/API/Jobs</span></a></p>
<p>或重定向后的新的<span style="font-family: Calibri;">URI/Jobs</span></p>
</td>
</tr>
<tr>
<td valign="top" width="138">
<p><strong>HTTP Method</strong></p>
</td>
<td valign="top" width="534">
<p><span style="font-family: Calibri;">POST</span></p>
</td>
</tr>
<tr>
<td valign="top" width="138">
<p><strong>Request Headers</strong></p>
</td>
<td valign="top" width="534">
<p><span style="font-family: Calibri;">DataServiceVersion: &nbsp;2.0<br />MaxDataServiceVersion: 3.0<br />x-ms-version: 2.7<br />Authorization:&nbsp;&nbsp; Bear + ACSToken</span></p>
</td>
</tr>
<tr>
<td valign="top" width="138">
<p><strong>Request Content Type</strong></p>
</td>
<td valign="top" width="534">
<p><span style="font-family: Calibri;">application/json; odata=verbose</span></p>
</td>
</tr>
<tr>
<td valign="top" width="138">
<p><strong>Request Body Format</strong></p>
</td>
<td valign="top" width="534">
<p><span style="font-family: Calibri;">{<br />&nbsp;&nbsp;&nbsp; "Name": "&lt;Job Name&gt;", (</span>自定义便于理解的作业名，如<span style="font-family: Calibri;">Encoding H264 Broadband 720p)</span><br /><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp; &ldquo;InputMediaAssets&rdquo;: [{</span></p>
<pre><span style="font-size: x-small;">&nbsp;&nbsp;&nbsp; "__metadata":{&ldquo;uri&rdquo;: &ldquo;<strong>https://media.windows.net</strong>/api/Assets(&lsquo;<strong>AssetID&rsquo;</strong>)&rdquo;}}],(注意请换为重定向后的URI)</span></pre>
<pre><span style="font-size: x-small;">&nbsp;&nbsp;&nbsp; &ldquo;Tasks&rdquo;:[{</span></pre>
<pre><span style="font-size: x-small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &ldquo;Configration&rdquo;: &ldquo;&lt;encoding preset name&gt;&rdquo;&nbsp;&nbsp; (如H264 Broadband 720p)</span></pre>
<pre><span style="font-size: x-small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &ldquo;MediaProcessorId&rdquo;: &rdquo;nb:mpid:UUID:70bdc2c3-ebf4-42a9-8542-5afc1e55d217&rdquo;</span></pre>
<pre><span style="font-size: x-small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &ldquo;TaskBody&rdquo;: "&lt;?xml version=\"1.0\" encoding=\"utf-8\"?&gt;</span></pre>
<pre><span style="font-size: x-small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;taskBody&gt;</span></pre>
<pre><span style="font-size: x-small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;inputAsset&gt;JobInputAsset(0)&lt;/inputAsset&gt;</span></pre>
<pre><span style="font-size: x-small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;outputAsset&gt;JobOutputAsset(0)&lt;/outputAsset&gt;</span></pre>
<pre><span style="font-size: x-small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/taskBody&gt;" }]</span><br />
<span style="font-size: x-small;">}</span><span style="font-size: x-small;">&nbsp;</span></pre>
</td>
</tr>
</tbody>
</table>
<p><span style="font-family: Calibri;">&nbsp;</span>创建编码作业的代码参考如下，其中processorId 可以直接取自<a href="https://msdn.microsoft.com/en-us/library/azure/jj129574.aspx#create_a_job"><span style="color: #0563c1;">MSDN</span></a> 文档： nb:mpid:UUID:70bdc2c3-ebf4-42a9-8542-5afc1e55d217，或者通过发送相应的请求获得。</p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp; private async Task&lt;bool&gt; EncodeSmooth(string acsToken, string assetId, string jobName, string wamsEndpoint, string processorId)</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AuthenticationHeaderValue header = CreateBasicAuthenticationHeader(acsToken);</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpClient httpClient = new HttpClient();</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.MaxResponseContentBufferSize = int.MaxValue;</span><span style="font-family: Calibri;">&nbsp;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("Authorization", header.ToString());</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("x-ms-version", "2.7");</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("DataServiceVersion", "2.0");</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("MaxDataServiceVersion", "3.0");&nbsp;&nbsp;</span></p>
<p>&nbsp;</p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var assetURI = wamsEndpoint+"Assets('" + assetId + "')";</span></p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String requestBody = "{ \"Name\" : \"" + jobName + "\"," +</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " \"InputMediaAssets\" : [{\"__metadata\" : {\"uri\" : \"" + assetURI + "\"}}]," +</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" \"Tasks\" : [{\"Configuration\" : \"H264 Smooth Streaming 720p\"," +</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " \"MediaProcessorId\" : \"" + processorId + "\"," +</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " \"TaskBody\" : \"&lt;?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?&gt;&lt;taskBody&gt;&lt;inputAsset&gt;JobInputAsset(0)&lt;/inputAsset&gt;&lt;outputAsset&gt;JobOutputAsset(0)&lt;/outputAsset&gt;&lt;/taskBody&gt;\"}]}";</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpContent body = new StringContent(requestBody, Encoding.UTF8, "application/json");</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var response = await httpClient.PostAsync(wamsEndpoint+"Jobs", body);</span></p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; if (response.IsSuccessStatusCode)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var content = await response.Content.ReadAsStringAsync();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlDocument xmlDoc = new XmlDocument();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlDoc.LoadXml(content);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlNodeList elemListBase = xmlDoc.GetElementsByTagName("d:Id");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string jobId = null;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach (var ele in elemListBase)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jobId = ele.InnerText;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return jobId;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return null;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p><span style="font-size: small;">获取<span style="font-family: Calibri;">ProcessorID </span>的代码可以参考如下，注意，此处的<span style="font-family: Calibri;">processorName</span>针对应用场景，可以是<span style="font-family: Calibri;">Windows Azure Media Encoder, </span>或者是<span style="font-family: Calibri;">Windows Azure Media Packager(</span>在<a href="https://msdn.microsoft.com/en-us/library/azure/jj129580.aspx"><span style="color: #0563c1; font-family: Calibri;">Static Packaging</span></a>场景会用到<span style="font-family: Calibri;">)</span>。</span></p>
<p>&nbsp;&nbsp; private async Task&lt;string&gt; GetProcessorId(string acsToken, string wamsEndPoint, string processorName)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AuthenticationHeaderValue header = CreateBasicAuthenticationHeader(acsToken);&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpClient httpClient = new HttpClient();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.MaxResponseContentBufferSize = int.MaxValue;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("Authorization", header.ToString());</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("x-ms-version", "2.7");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("DataServiceVersion", "3.0");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("MaxDataServiceVersion", "3.0");</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, wamsEndPoint);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string uri = Uri.EscapeUriString("Name eq "+"\'" +processorName +"\'");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string endPoint = wamsEndPoint + "MediaProcessors()?$filter="+uri;</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var response = await httpClient.GetAsync(endPoint);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string processorID = null;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (response.IsSuccessStatusCode)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var content = await response.Content.ReadAsStringAsync();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlDocument xmlDoc = new XmlDocument();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlDoc.LoadXml(content);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlNodeList elemList = xmlDoc.GetElementsByTagName("d:Id");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach (var ele in elemList)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; processorID = ele.InnerText;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return processorID;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p><span style="font-size: small;">创建好编码工作后，剩余的编码任务交由媒体服务负责完成，编码时间依赖于媒体文件的大小，在编码完成之后才能进行流媒体发布，但是客户端如何才能知道server端编码结束了呢？这里我们也可以对编码进程进行查询。查询作业状态的请求简要总结如下，详情请参见：<a href="https://msdn.microsoft.com/zh-cn/library/azure/jj129574.aspx"><span style="color: #0563c1;">使用 Media Services REST API 创建编码作业</span></a> </span></p>
<table style="width: 672px;" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="138">
<p><span style="font-family: Calibri;">EndPoint</span></p>
</td>
<td valign="top" width="534">
<p><a href="https://media.windows.net/API/Jobs(jobId)/State"><span style="color: #0563c1; font-family: Calibri;">https://media.windows.net/API/Jobs(jobId)/State</span></a><span style="font-family: Calibri;"> <span style="text-decoration: underline;"><span style="color: #0563c1;">&nbsp;</span></span></span></p>
<p>或重定向后的新的<span style="font-family: Calibri;">URI/Jobs(jobId)/State &nbsp;&nbsp;(</span>注意对<span style="font-family: Calibri;">jobId</span>进行<span style="font-family: Calibri;">Url</span>编码<span style="font-family: Calibri;">)</span></p>
</td>
</tr>
<tr>
<td valign="top" width="138">
<p><strong>HTTP Method</strong></p>
</td>
<td valign="top" width="534">
<p><span style="font-family: Calibri;">GET</span></p>
</td>
</tr>
<tr>
<td valign="top" width="138">
<p><strong>Request Headers</strong></p>
</td>
<td valign="top" width="534">
<p><span style="font-family: Calibri;">DataServiceVersion:&nbsp; 3.0<br />MaxDataServiceVersion: 3.0<br />x-ms-version: 2.7<br />Authorization:&nbsp;&nbsp; Bear + ACSToken</span></p>
</td>
</tr>
<tr>
<td valign="top" width="138">
<p><strong>Request Content Type</strong></p>
</td>
<td valign="top" width="534">
<p><span style="font-family: Calibri;">application/json; odata=verbose</span></p>
</td>
</tr>
</tbody>
</table>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p><span style="font-size: small;">执行代码参考如下，根据返回信息确定编码状态，如2-表示processing，3-表示finished，那么返回值为3时表示编码工作完成，即可进行后续的流媒体发布工作啦。</span></p>
<p>&nbsp; private async Task&lt;string&gt; GetJobStateAsync(string acsToken, string wamsEndpoint, string jobId)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AuthenticationHeaderValue header = CreateBasicAuthenticationHeader(acsToken);&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpClient httpClient = new HttpClient();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.MaxResponseContentBufferSize = int.MaxValue;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("Authorization", header.ToString());</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("x-ms-version", "2.7");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("DataServiceVersion", "3.0");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("MaxDataServiceVersion", "3.0");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string url = wamsEndpoint + "Jobs('" + WebUtility.UrlEncode(jobId) + "')/State";&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var response = await httpClient.GetAsync(url);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (response.IsSuccessStatusCode)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var content = await response.Content.ReadAsStringAsync();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JObject jsonObject = JObject.Parse(content);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string jobState = jsonObject.Value&lt;string&gt;("value");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return jobState;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return null;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p><span style="font-size: small;">同时我们可以查看 Azure Porta以了解编码进展情况，如下截图所示编码已经完成：</span></p>
<p>&nbsp;<a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/5661.Encoding.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/5661.Encoding.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/5661.Encoding.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/5661.Encoding.png" alt="" border="0" /></a></p>
<p><span style="font-size: small;">&nbsp;</span></p>
<p><span style="font-size: small;">完成文件的编码后后，便可以进行后续流媒体的发布，将在后续文章中详细讲述，敬请期待。</span></p>]]></content:encoded>
    </item>
    <item>
      <title>基于Windows Azure Media Service REST API 进行Windows Store/Windows Phone 应用开发系列-Part 3上传媒体到WAMS</title>
      <link>https://docs.microsoft.com/archive/blogs/lj/windows-azure-media-service-rest-api-windows-storewindows-phone-part-3wams</link>
      <pubDate>Fri, 28 Nov 2014 02:52:00 GMT</pubDate>
      <dc:creator><![CDATA[JennyLi-MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/lj/2014/11/28/windows-azure-media-service-rest-api-windows-storewindows-phone-part-3wams/</guid>
      <description><![CDATA[在文章 基于Windows Azure Media Service REST API 进行Windows Store/Windows Phone 应用开发系列-Part 1...]]></description>
      <content:encoded><![CDATA[<p><span style="font-size: small;">在文章 <a href="https://blogs.msdn.com/b/lj/archive/2014/10/08/windows-azure-media-service-rest-api-windows-store-windows-phone-part-1.aspx"><span style="color: #0563c1;">基于Windows Azure Media Service REST API 进行Windows Store/Windows Phone 应用开发系列-Part 1 简介</span></a>中介绍了基于Windows Azure Media Service(Windows Azure 媒体服务，简称WAMS)进行应用开发的相关信息及包含的基本流程，紧接着在文章<a href="https://blogs.msdn.com/b/lj/archive/2014/10/08/windows-azure-media-service-rest-api-windows-store-windows-phone-part-2-wams.aspx"><span style="color: #0563c1;">基于Windows Azure Media Service REST API 进行Windows Store/Windows Phone 应用开发系列-Part 2初始设置链接到WAMS</span></a>中介绍了如何使用REST API链接到媒体服务，本文将基于此对如何上传媒体到媒体服务进行详细讲解。</span></p>
<p><span style="font-size: small;">使用<span style="font-family: Calibri;">REST API</span>将媒体文件上传到媒体服务包含许多步骤，主要流程是：</span></p>
<ol>
<li><span style="font-size: small;">创建资产（<span style="font-family: Calibri;">ASSET</span>）</span></li>
<li><span style="font-size: small;">对资产进行加密（可选项）&mdash;本文暂时不予以考虑</span></li>
<li><span style="font-size: small;">将媒体文件上传到<span style="font-family: Calibri;">blob storage</span></span></li>
</ol>
<p><span style="font-size: small;">请注意，在使用<span style="font-family: Calibri;">REST API</span>时访问媒体服务时，必须在<span style="font-family: Calibri;">HTTP</span>请求中添加如下必须的<span style="font-family: Calibri;">header</span>；<span style="font-family: Calibri;">WAMS </span>的根<span style="font-family: Calibri;"> URI </span>为</span><a href="https://media.windows.net/"><span style="color: #0563c1; font-family: Calibri; font-size: small;">https://media.windows.net/</span></a><span style="font-size: small;">，成功连接到此<span style="font-family: Calibri;"> URI</span>后，会收到一个&ldquo;<span style="font-family: Calibri;">301 </span>重定向&rdquo;响应并提取出新的媒体服务<span style="font-family: Calibri;">URI</span>，随后调用新都是基于该<span style="font-family: Calibri;"> URI</span>，详细内容参见<a href="https://blogs.msdn.com/b/lj/archive/2014/10/08/windows-azure-media-service-rest-api-windows-store-windows-phone-part-2-wams.aspx"><span style="color: #0563c1; font-family: Calibri;">Part2</span></a>内容。</span></p>
<p><span style="font-size: small;">根据文档</span><a href="https://msdn.microsoft.com/zh-cn/library/azure/hh973616.aspx"><span style="color: #0563c1;"><span style="font-size: small;">媒体服务<span style="font-family: Calibri;"> REST API </span>开发的设置</span></span></a><span style="font-size: small;">可知，每次调用<span style="font-family: Calibri;">WAMS</span>时，客户端必须在请求中包括必需的标头，列表如下：</span></p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="150">
<p><span style="font-size: small;"><span style="font-family: Calibri;">Header</span></span></p>
</td>
<td valign="top" width="144">
<p><span style="font-size: small;"><span style="font-family: Calibri;">Type</span></span></p>
</td>
<td valign="top" width="282">
<p><span style="font-size: small;"><span style="font-family: Calibri;">Value</span></span></p>
</td>
</tr>
<tr>
<td valign="top" width="150">
<p><span style="font-family: Calibri;">Authorization</span></p>
</td>
<td valign="top" width="144">
<p><span style="font-family: Calibri;">Bearer</span></p>
</td>
<td valign="top" width="282">
<p><span style="font-family: Calibri;">Bearer&nbsp;</span>是唯一接受的授权机制。</p>
<p>该值还必须包括由<span style="font-family: Calibri;"> ACS </span>提供的访问令牌。</p>
</td>
</tr>
<tr>
<td valign="top" width="150">
<p><span style="font-family: Calibri;">x-ms-version</span></p>
</td>
<td valign="top" width="144">
<p><span style="font-family: Calibri;">Decimal</span></p>
</td>
<td valign="top" width="282">
<p><span style="font-family: Calibri;">2.7</span></p>
</td>
</tr>
<tr>
<td valign="top" width="150">
<p><span style="font-family: Calibri;">DataServiceVersion</span></p>
</td>
<td valign="top" width="144">
<p><span style="font-family: Calibri;">Decimal</span></p>
</td>
<td valign="top" width="282">
<p><span style="font-family: Calibri;">3.0</span></p>
</td>
</tr>
<tr>
<td valign="top" width="150">
<p><span style="font-family: Calibri;">MaxDataServiceVersion</span></p>
</td>
<td valign="top" width="144">
<p><span style="font-family: Calibri;">Decimal</span></p>
</td>
<td valign="top" width="282">
<p><span style="font-family: Calibri;">3.0</span></p>
</td>
</tr>
</tbody>
</table>
<p><span style="font-family: Calibri; font-size: small;">&nbsp;</span><span style="font-size: small;">如</span><a href="https://blogs.msdn.com/b/lj/archive/2014/10/08/windows-azure-media-service-rest-api-windows-store-windows-phone-part-1.aspx"><span style="color: #0563c1; font-family: Calibri;">Part 1</span></a>中描述：资产（<span style="font-family: Calibri;">ASSET</span>）是包含媒体信息的逻辑实体，可能包含了一个或多个需要处理的数字文件如<span style="font-family: Calibri;">audio</span>，<span style="font-family: Calibri;">video</span>等。<a href="https://msdn.microsoft.com/zh-cn/library/azure/hh974277.aspx#asset_entity_properties"><span style="color: #0563c1;">资产实体</span></a>是对资产的抽象，包含了一系列的属性如<span style="font-family: Calibri;">Id, State</span>等，为便于处理，我们定义<span style="font-family: Calibri;">Asset</span>类用于表示媒体服务中的一个资产：</p>
<p>创建资产：在媒体服务中创建一个新的资产</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="138">
<p><span style="font-family: Calibri;">EndPoint</span></p>
</td>
<td valign="top" width="438">
<p><a href="https://media.windows.net/API/Assets"><span style="color: #0563c1; font-family: Calibri;">https://media.windows.net/API/Assets</span></a></p>
<p>或<span style="font-family: Calibri;">redirection</span>后的新的<span style="font-family: Calibri;">URI/Assets</span></p>
</td>
</tr>
<tr>
<td valign="top" width="138">
<p><strong>HTTP Method</strong></p>
</td>
<td valign="top" width="438">
<p><span style="font-family: Calibri;">POST</span></p>
</td>
</tr>
<tr>
<td valign="top" width="138">
<p><strong>Request Headers</strong></p>
</td>
<td valign="top" width="438">
<p><span style="font-family: Calibri;">DataServiceVersion: &nbsp;3.0<br />MaxDataServiceVersion: 3.0<br />x-ms-version: 2.7<br />Authorization:&nbsp;&nbsp; Bear + ACSToken</span></p>
</td>
</tr>
<tr>
<td valign="top" width="138">
<p><strong>Request Content Type</strong></p>
</td>
<td valign="top" width="438">
<p><span style="font-family: Calibri;">application/json;odata=verbose</span></p>
</td>
</tr>
<tr>
<td valign="top" width="138">
<p><strong>Request Body Format</strong></p>
</td>
<td valign="top" width="438">
<p><span style="font-family: Calibri;">{<br />&nbsp;&nbsp;&nbsp; "Name": "&lt;Asset Name&gt;", (</span>通常使用媒体文件名<span style="font-family: Calibri;">,</span>本文省略加密操作<span style="font-family: Calibri;">)</span><br /><span style="font-family: Calibri;">format&gt;"<br />}<br /><br />e.g.<br />{<br />&nbsp;&nbsp;&nbsp; "Name": "&lt;filename&gt;", (</span>此处常用媒体文件的名字<span style="font-family: Calibri;">)<br />}</span></p>
</td>
</tr>
</tbody>
</table>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p>通常根据媒体文件名创建<span style="font-family: Calibri;">asset, </span>如下代码根据文件名在媒体服务中创建相应的资产实体，代码执行成功后可以提取相应的<span style="font-family: Calibri;">Id</span>值（做为<span style="font-family: Calibri;">AssetId</span>）如<span style="font-family: Calibri;">nb:cid:UUID:636363d9-7c66-42ca-add4-0a8c4d4464f6</span>。</p>
<p><span style="font-family: Calibri;">(</span>为便于描述，本文先假设上传位于媒体库中名为<span style="font-family: Calibri;">interview3.wmv</span>的文件，以<a href="https://blogs.msdn.com/b/lj/archive/2014/10/08/windows-azure-media-service-rest-api-windows-store-windows-phone-part-2-wams.aspx"><span style="color: #0563c1; font-family: Calibri; font-size: small;">Part2</span></a>链接媒体服务的内容为基础<span style="font-family: Calibri;">)</span></p>
<p>private string AssetId;</p>
<p>private string AccessPolicyId;</p>
<p>private string UploadUrl;</p>
<p>private string UploadEndpoint;</p>
<p>private static readonly string mediaFileName = "interview3.wmv";&nbsp;</p>
<p>private async Task&lt;string&gt; CreateAssetAsync(string acsToken, string wamsEndPoint, string mediaName)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AuthenticationHeaderValue header = CreateBasicAuthenticationHeader(acsToken);&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpClient httpClient = new HttpClient();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.MaxResponseContentBufferSize = int.MaxValue;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("Authorization", header.ToString());</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("x-ms-version", "2.7");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("DataServiceVersion", "3.0");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("MaxDataServiceVersion", "3.0");&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, wamsEndPoint);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string assetCreateRequestPayloadFormat = @"{0} ""Name"": {1} {2} {3} {4}";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string requestBody = string.Format(CultureInfo.InvariantCulture, assetCreateRequestPayloadFormat, "{","\"", mediaName,"\"", "}");&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpContent body = new StringContent(requestBody, Encoding.UTF8, "application/json");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var response = await httpClient.PostAsync(wamsEndPoint + "Assets", body);&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string assetId = null;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (response.IsSuccessStatusCode)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var content = await response.Content.ReadAsStringAsync();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlDocument xmlDoc = new XmlDocument();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlDoc.LoadXml(content);&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlNodeList elemList = xmlDoc.GetElementsByTagName("d:Id");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach (var ele in elemList)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; assetId = ele.InnerText;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return assetId;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p><span style="font-size: small;">此时再去创建该资产下的资产文件，获取资产实体下对应的资产文件的ID, 以便后续过程中将上传的媒体文件更新到该ID下</span>（MergeAssetFilesAsync）<span style="font-family: Calibri;">:</span></p>
<p>&nbsp;&nbsp; private async Task&lt;string&gt; CreateAssetFilesAsync(string acsToken, string wamsEndPoint, string assetId, string mediaFileName)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AuthenticationHeaderValue header = CreateBasicAuthenticationHeader(acsToken);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpClient httpClient = new HttpClient();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.MaxResponseContentBufferSize = int.MaxValue;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("Authorization", header.ToString());</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("x-ms-version", "2.7");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("DataServiceVersion", "3.0");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("MaxDataServiceVersion", "3.0");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String requestBody = "{ \"Name\" : \"" + mediaFileName + "\"," +</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " \"ContentFileSize\" : \"" + "0" + "\", " +</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " \"ParentAssetId\" : \"" + assetId + "\", " +</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " \"MimeType\" : \"" + "video/x-ms-wmv" + "\"}";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpContent body = new StringContent(requestBody, Encoding.UTF8, "application/json");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var response = await httpClient.PostAsync(wamsEndPoint + "Files", body);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string assetFileId = null;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (response.IsSuccessStatusCode)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var content = await response.Content.ReadAsStringAsync();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlDocument xmlDoc = new XmlDocument();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlDoc.LoadXml(content);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlNodeList elemList = xmlDoc.GetElementsByTagName("d:Id");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach (var ele in elemList)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; assetFileId = ele.InnerText;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return assetFileId;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p><span style="font-size: small;">如</span><a href="https://blogs.msdn.com/b/lj/archive/2014/10/08/windows-azure-media-service-rest-api-windows-store-windows-phone-part-1.aspx"><span style="color: #0563c1; font-family: Calibri;">Part 1</span></a>中描述，每个<span style="font-family: Calibri;">WAMS </span>账户都有一个或多个相关联的<span style="font-family: Calibri;">Azure Storage </span>账户，用于存储关联的<span style="font-family: Calibri;">WAMS </span>账户控制的媒体内容，在将媒体文件上传至<span style="font-family: Calibri;">Blob Storage</span>时要求对资产设置相应的写入权限，然后提取用于上传的<span style="font-family: Calibri;">Storage URL</span>，最后使用<span style="font-family: Calibri;"> Azure Storage REST APIs</span>进行传输。</p>
<p>将任何文件上载到<span style="font-family: Calibri;"> BLOB </span>存储之前，需要设置用于对资产执行写入操作的访问策略权限。为此，需要向<span style="font-family: Calibri;"> AccessPolicy </span>实体集发送一个<span style="font-family: Calibri;"> HTTP POST </span>请求，创建<span style="font-family: Calibri;">AccessPolicy </span>请求简要总结如下：</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="138">
<p><span style="font-family: Calibri;">EndPoint</span></p>
</td>
<td valign="top" width="438">
<pre><a href="https://media.windows.net/API/AccessPolicies"><span style="color: #0563c1; font-size: x-small;">https://media.windows.net/API/AccessPolicies</span></a><span style="font-size: x-small;"> &nbsp;</span></pre>
<p>或<span style="font-family: Calibri;">redirection</span>后的新的<span style="font-family: Calibri;">URI/AccessPolicies</span></p>
</td>
</tr>
<tr>
<td valign="top" width="138">
<p><strong>HTTP Method</strong></p>
</td>
<td valign="top" width="438">
<p><span style="font-family: Calibri;">POST</span></p>
</td>
</tr>
<tr>
<td valign="top" width="138">
<p><strong>Request Headers</strong></p>
</td>
<td valign="top" width="438">
<p><span style="font-family: Calibri;">DataServiceVersion: &nbsp;3.0<br />MaxDataServiceVersion: 3.0<br />x-ms-version: 2.7<br />Authorization:&nbsp;&nbsp; Bear + ACSToken</span></p>
</td>
</tr>
<tr>
<td valign="top" width="138">
<p><strong>Request Content Type</strong></p>
</td>
<td valign="top" width="438">
<p><span style="font-family: Calibri;">application/json;odata=verbose</span></p>
</td>
</tr>
<tr>
<td valign="top" width="138">
<p><strong>Request Body Format</strong></p>
</td>
<td valign="top" width="438">
<p><span style="font-family: Calibri;">{<br />&nbsp;&nbsp;&nbsp; "Name": "NewUploadPolicy", </span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp; <span style="font-size: small;">"DurationInMinutes" : "300",</span></span></p>
<pre><span style="font-size: x-small;">&nbsp;&nbsp;&nbsp; "Permissions" : 2</span></pre>
<p><span style="font-family: Calibri;">format&gt;"<br />}</span></p>
</td>
</tr>
</tbody>
</table>
<p><span style="font-family: Calibri;">&nbsp;</span><span style="font-size: small;">执行过程可参考如下代码, 此处是写的权限（</span>Permissions=&rdquo;2&rdquo;<span style="font-size: small;">），在 <a href="https://blogs.msdn.com/b/lj/archive/2015/01/10/windows-azure-media-service-rest-api-windows-store-windows-phone-part-5.aspx"><span style="color: #0563c1;">文章5媒体的发布过程</span></a>中，同样需要指定资产&ldquo;读&rdquo;的权限（</span>Permissions=&rdquo;1&rdquo;<span style="font-size: small;">）,执行成功后，根据返回内容获得相应的AccessPolicyId， 如："nb:pid:UUID:58fcf51e-5219-4fea-8536-6c295d2c388a"。</span><span style="font-family: Calibri;">&nbsp;</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ///apName</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// for upload-NewUploadPolicy</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// for download - DownloadPolicy</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// accessType 2- upload(write), 1- read</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;param name="acsToken"&gt;&lt;/param&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;param name="wamsEndPoint"&gt;&lt;/param&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;param name="policyName"&gt;&lt;/param&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;returns&gt;&lt;/returns&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private async Task&lt;string&gt; CreateAccessPolicyAsync(string acsToken, string wamsEndPoint, string apName, int accessType)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AuthenticationHeaderValue header = CreateBasicAuthenticationHeader(acsToken);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpClient httpClient = new HttpClient();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.MaxResponseContentBufferSize = int.MaxValue;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("Authorization", header.ToString());</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("x-ms-version", "2.7");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("DataServiceVersion", "3.0");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("MaxDataServiceVersion", "3.0");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, wamsEndPoint);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String requestBody = "{ \"Name\" : \"" + apName + "\"," +</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " \"DurationInMinutes\" : \"" + "300" + "\", " +</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " \"Permissions\" : " + accessType.ToString() + "}";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpContent body = new StringContent(requestBody, Encoding.UTF8, "application/json");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var response = await httpClient.PostAsync(wamsEndPoint + "AccessPolicies", body);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string accessPolicyId = null;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (response.IsSuccessStatusCode)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var content = await response.Content.ReadAsStringAsync();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlDocument xmlDoc = new XmlDocument();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlDoc.LoadXml(content);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlNodeList elemList = xmlDoc.GetElementsByTagName("d:Id");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach (var ele in elemList)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; accessPolicyId = ele.InnerText;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return accessPolicyId;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p>创建<span style="font-family: Calibri;"> AccessPolicy </span>后，将该<span style="font-family: Calibri;">Id</span>链接到某个定位符实体，该实体将为你提供用于将文件上载到<span style="font-family: Calibri;"> BLOB </span>存储的<span style="font-family: Calibri;"> URL </span>路径，创建上传<span style="font-family: Calibri;">URL</span>的请求简要总结如下：</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="138">
<p><span style="font-family: Calibri;">EndPoint</span></p>
</td>
<td valign="top" width="438">
<pre><a href="https://media.windows.net/API/Locators"><span style="color: #0563c1; font-size: x-small;">https://media.windows.net/API/Locators</span></a><span style="font-size: x-small;"> &nbsp;</span></pre>
<p>或<span style="font-family: Calibri;">redirection</span>后的新的<span style="font-family: Calibri;">URI/Locators</span></p>
</td>
</tr>
<tr>
<td valign="top" width="138">
<p><strong>HTTP Method</strong></p>
</td>
<td valign="top" width="438">
<p><span style="font-family: Calibri;">POST</span></p>
</td>
</tr>
<tr>
<td valign="top" width="138">
<p><strong>Request Headers</strong></p>
</td>
<td valign="top" width="438">
<p><span style="font-family: Calibri;">DataServiceVersion: &nbsp;3.0<br />MaxDataServiceVersion: 3.0<br />x-ms-version: 2.7<br />Authorization:&nbsp;&nbsp; Bear + ACSToken</span></p>
</td>
</tr>
<tr>
<td valign="top" width="138">
<p><strong>Request Content Type</strong></p>
</td>
<td valign="top" width="438">
<p><span style="font-family: Calibri;">application/json;odata=verbose</span></p>
</td>
</tr>
<tr>
<td valign="top" width="138">
<p><strong>Request Body Format</strong></p>
</td>
<td valign="top" width="438">
<pre><span style="font-size: x-small;">{<br /> &nbsp;&nbsp;&nbsp; " AccessPolicyId": &ldquo;&lt; AccessPolicyId&gt;&rdquo;,</span></pre>
<p><span style="font-family: Calibri;">&nbsp;&nbsp; &nbsp;"AssetId" : &ldquo;&lt;AssetId&gt;&rdquo;,</span></p>
<pre><span style="font-size: x-small;">&nbsp;&nbsp;&nbsp; "StartTime" : &lt; DateTime.UtcNow.AddMinutes(-5) &gt;&rdquo;,（必须为YYYY-MM-DDTHH:mm:ss 格式）</span></pre>
<pre><span style="font-size: x-small;">&nbsp; &nbsp;&nbsp;&nbsp;&ldquo;Type&rdquo;: &ldquo;&lt;1&gt;&rdquo;</span></pre>
<p><span style="font-family: Calibri;">format&gt;"<br />}</span></p>
<p><span style="font-family: Calibri;">e.g:</span></p>
<p><span style="font-family: Calibri;">{"AccessPolicyId" : "nb:pid:UUID:58fcf51e-5219-4fea-8536-6c295d2c388a", "AssetId" : "nb:cid:UUID:636363d9-7c66-42ca-add4-0a8c4d4464f6",&nbsp; "StartTime" : "2014-11-28T10:39:58",&nbsp; </span></p>
<p><span style="font-family: Calibri;">"Type" : 1</span></p>
<p><span style="font-family: Calibri;">}</span></p>
</td>
</tr>
</tbody>
</table>
<p><span style="font-family: Calibri;">&nbsp;</span>执行过程可参考如下代码，执行成功后，根据返回内容构造相应的上传<span style="font-family: Calibri;">URL</span>，注意必须将要上载的文件的文件名添加到在获取得到的<span style="font-family: Calibri;">URL</span>中，如：<a href="https://myappsstorage.blob.core.windows.net/asset-636363d9-7c66-42ca-add4-0a8c4d4464f6/azure.wmv?sv=2012-02-12&amp;sr=c&amp;si=8561f64e-0392-47f6-a178-8397f6ee4352&amp;sig=JjDaBdvxHqWsA%2FWrLMLkAqQjl92v03vwdOrqVIAjkV8%3D&amp;st=2014-11-28T10%3A39%3A58Z&amp;se=2014-11-28T15%3A39%3A58Z"><span style="color: #0563c1; font-family: Calibri;">https://myappsstorage.blob.core.windows.net/asset-636363d9-7c66-42ca-add4-0a8c4d4464f6/<strong>azure.wmv</strong>?sv=2012-02-12&amp;sr=c&amp;si=8561f64e-0392-47f6-a178-8397f6ee4352&amp;sig=JjDaBdvxHqWsA%2FWrLMLkAqQjl92v03vwdOrqVIAjkV8%3D&amp;st=2014-11-28T10%3A39%3A58Z&amp;se=2014-11-28T15%3A39%3A58Z</span></a>。</p>
<p>&nbsp; private async Task CreateUploadURLAsync(string acsToken, string wamsEndPoint, string accessPolicyId, string assetId)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AuthenticationHeaderValue header = CreateBasicAuthenticationHeader(acsToken);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpClient httpClient = new HttpClient();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.MaxResponseContentBufferSize = int.MaxValue;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("Authorization", header.ToString());</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("x-ms-version", "2.7");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("DataServiceVersion", "3.0");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("MaxDataServiceVersion", "3.0");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, wamsEndPoint);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String requestBody = "{ \"AccessPolicyId\" : \"" + <strong>accessPolicyId</strong> + "\"," +</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " \"AssetId\" : \"" + <strong>assetId</strong>+ "\", " +</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " \"StartTime\" : \"" + DateTime.UtcNow.AddMinutes(-5).ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss") + "\", " +&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " \"Type\" : " + "1" + "}";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpContent body = new StringContent(requestBody, Encoding.UTF8, "application/json");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var response = await httpClient.PostAsync(wamsEndPoint + "Locators", body);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (response.IsSuccessStatusCode)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var content = await response.Content.ReadAsStringAsync();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlDocument xmlDoc = new XmlDocument();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlDoc.LoadXml(content);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlNodeList elemListBase = xmlDoc.GetElementsByTagName("d:BaseUri");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlNodeList elemListSV = xmlDoc.GetElementsByTagName("d:ContentAccessComponent");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string baseUrl=null;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string sv=null;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach (var ele in elemListBase)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; baseUrl = ele.InnerText;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach (var ele in elemListSV)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sv = ele.InnerText;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>UploadUrl</strong> = baseUrl + "/" +Path.GetFileName(MediaFileName) +&nbsp; sv;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>UploadEndpoint</strong> = baseUrl.Substring(0, baseUrl.IndexOf("/asset"));</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;</p>
<p>获得上传地址且设置好访问权限后，即可使用存储<span style="font-family: Calibri;"> REST API </span>将具体的文件上载到<span style="font-family: Calibri;"> Azure BLOB </span>存储容器，上传文件请求简要总结如下：</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="138">
<p><span style="font-family: Calibri;">EndPoint</span></p>
</td>
<td valign="top" width="438">
<p>上传地址（<span style="font-family: Calibri;">blob storage SAS </span>定位符）</p>
</td>
</tr>
<tr>
<td valign="top" width="138">
<p><strong>HTTP Method</strong></p>
</td>
<td valign="top" width="438">
<p><span style="font-family: Calibri;">PUT</span></p>
</td>
</tr>
<tr>
<td valign="top" width="138">
<p><strong>Request Headers</strong><strong></strong></p>
</td>
<td valign="top" width="438">
<pre><strong><span style="font-size: x-small;">x-ms-version: 2011-08-18</span></strong></pre>
<pre><strong><span style="font-size: x-small;">x-ms-date: 2011-01-17</span></strong></pre>
<pre><span style="font-size: x-small;"><strong>x-ms-blob-type: BlockBlob</strong><strong></strong></span></pre>
</td>
</tr>
<tr>
<td valign="top" width="138">
<p><strong>Request Content Type</strong></p>
</td>
<td valign="top" width="438">
<pre><span style="font-size: x-small;"><strong>application/octet-stream</strong></span></pre>
</td>
</tr>
<tr>
<td valign="top" width="138">
<p><strong>Request Body Format</strong></p>
</td>
<td valign="top" width="438">
<p><span style="font-family: Calibri;">{<br />&nbsp; </span>媒体文件二进制数据<span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp; </span></p>
<p><span style="font-family: Calibri;">}</span></p>
</td>
</tr>
</tbody>
</table>
<p><span style="font-family: Calibri;">&nbsp;</span><span style="font-size: small;">执行过程可参考如下代码，需要注意的是二进制文件的添加，此处仅以本地<span style="font-family: Calibri;">Video</span>库</span><span style="font-family: Calibri;">(</span>Windows.Storage.KnownFolders.VideosLibrary<span style="font-family: Calibri;">)</span><span style="font-size: small;">中的一个名为<span style="font-family: Calibri;">interview3.wmv</span>媒体文件为例，可以做相应修改，如让用户选择要上传的文件（<span style="font-family: Calibri;">OpenFilePicker</span>）或自带摄像头拍摄的视频，执行成功返回<span style="font-family: Calibri;">201</span>创建成功</span>。</p>
<p>&nbsp;&nbsp;private async Task&lt;bool&gt; UploadFileAsync(string acsToken, string uploadEndPoint,string uploadUrl)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpClientHandler handler = new HttpClientHandler { MaxRequestContentBufferSize = 10000000 };</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpClient httpClient = new HttpClient(handler);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("x-ms-version", "2011-08-18");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("x-ms-date", "2011-01-17");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("x-ms-blob-type", "BlockBlob");&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StorageFolder library = Windows.Storage.KnownFolders.VideosLibrary;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var videoFile = await library.GetFileAsync(MediaFileName);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var props = await videoFile.GetBasicPropertiesAsync();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var stream = await videoFile.OpenStreamForReadAsync();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ContentSize = props.Size;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StreamContent streamContent = new StreamContent(stream, (int)props.Size);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpResponseMessage response = await httpClient.PutAsync(uploadUrl, streamContent);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (response.IsSuccessStatusCode)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;</p>
<p><span style="font-size: small;">请注意到这一步为止，媒体文件已经上传至Blob Storage，但是还没有更新到我们的资产实体中，需要再发送一个更新请求才能完成整个媒体文件的上传工作，相应的执行过程可参考如下代码。</span></p>
<p>private async Task MergeAssetFilesAsync(string acsToken, string wamsEndPoint,string assetId, string assetFileId, string mediaFileName)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AuthenticationHeaderValue header = CreateBasicAuthenticationHeader(acsToken);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String requestBody = "{ \"Name\" : \"" + mediaFileName + "\"," +</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " \"ContentFileSize\" : \"" + ContentSize + "\", " +</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " \"ParentAssetId\" : \"" + assetId + "\", " +</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " \"Id\" : \"" + assetFileId + "\", " +</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " \"MimeType\" : \"" + "video/x-ms-wmv" + "\"}";&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var request = (HttpWebRequest)HttpWebRequest.Create(wamsEndPoint + "Files('" + assetFileId + "')");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; request.Method = "MERGE";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; request.ContentType = "application/json;odata=verbose";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; request.Accept = "application/json;odata=verbose";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; request.Headers["DataServiceVersion"] = "3.0";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;request.Headers["MaxDataServiceVersion"] = "3.0";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; request.Headers["x-ms-version"] = "2.7";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; request.Headers["Authorization"] = header.ToString();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var requestBytes = Encoding.UTF8.GetBytes(requestBody);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var requestStream = await request.GetRequestStreamAsync();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; await requestStream.WriteAsync(requestBytes, 0, requestBytes.Length);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; await requestStream.FlushAsync();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var response = await request.GetResponseAsync();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p>完成文件的上传后，我们可以在<span style="font-family: Calibri;">Portal</span>上看到该文件的大小，同时在页面底部的<span style="font-family: Calibri;">Encode</span>按钮现在也可以使用了，之后便可以进行后续媒体的操作如编码，将在后续文章中详细讲述，敬请期待。</p>
<p>&nbsp; <a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/5078.Upload-sucess.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/5078.Upload_2D00_sucess.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/5078.Upload-sucess.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/5078.Upload_2D00_sucess.png" alt="" border="0" /></a></p>
<p>&nbsp;</p>]]></content:encoded>
    </item>
    <item>
      <title>基于Windows Azure Media Service REST API 进行Windows Store/Windows Phone 应用开发系列-Part 2初始设置链接到WAMS</title>
      <link>https://docs.microsoft.com/archive/blogs/lj/windows-azure-media-service-rest-api-windows-storewindows-phone-part-2</link>
      <pubDate>Tue, 07 Oct 2014 23:12:00 GMT</pubDate>
      <dc:creator><![CDATA[JennyLi-MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/lj/2014/10/07/windows-azure-media-service-rest-api-windows-storewindows-phone-part-2/</guid>
      <description><![CDATA[在文章基于Windows Azure Media Service REST API 进行Windows Store/Windows Phone 应用开发系列-Part 1...]]></description>
      <content:encoded><![CDATA[<p><span style="font-size: small;">在文章</span><a href="https://blogs.msdn.com/b/lj/archive/2014/10/08/windows-azure-media-service-rest-api-windows-store-windows-phone-part-1.aspx"><span style="color: #0563c1;"><span style="font-size: small;">基于<span style="font-family: Calibri;">Windows Azure Media Service REST API </span>进行<span style="font-family: Calibri;">Windows Store/Windows Phone </span>应用开发系列<span style="font-family: Calibri;">-Part 1 </span>简介</span></span></a><span style="font-size: small;">中介绍了基于<span style="font-family: Calibri;">Windows Azure Media Service(Windows Azure </span>媒体服务，简称<span style="font-family: Calibri;">WAMS)</span>进行应用开发的相关信息及包含的基本流程，本文将对如何使用<span style="font-family: Calibri;">REST API</span>进行<span style="font-family: Calibri;">WAMS</span>的链接进行详细讲解。</span></p>
<p><span style="font-size: small;"><span style="font-family: Calibri;">WAMS</span>接受基于<span style="font-family: Calibri;"> OData </span>的<span style="font-family: Calibri;"> HTTP </span>请求并能够以详细<span style="font-family: Calibri;"> JSON </span>或<span style="font-family: Calibri;"> atom+pub </span>做出响应。由于<span style="font-family: Calibri;">WAMS</span>遵循<span style="font-family: Calibri;"> Azure </span>设计准则，因此在连接到<span style="font-family: Calibri;"> WAMS</span>时，每个客户端必须使用一组必需的<span style="font-family: Calibri;"> HTTP </span>标头。根据文档</span><a href="https://msdn.microsoft.com/zh-cn/library/azure/hh973616.aspx"><span style="color: #0563c1;"><span style="font-size: small;">媒体服务<span style="font-family: Calibri;"> REST API </span>开发的设置</span></span></a><span style="font-size: small;">可知，每次调用<span style="font-family: Calibri;">WAMS</span>时，客户端必须在请求中包括一组必需标头，</span><a title="折叠" href="javascript:void(0)"><span style="font-size: small;">媒体服务支持的标准<span style="font-family: Calibri;"> HTTP </span>请求必须的标头</span></a><span style="font-size: small;">列表如下：</span></p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="150">
<p><span style="font-size: small;"><span style="font-family: Calibri;">Header</span></span></p>
</td>
<td valign="top" width="144">
<p><span style="font-size: small;"><span style="font-family: Calibri;">Type</span></span></p>
</td>
<td valign="top" width="282">
<p><span style="font-size: small;"><span style="font-family: Calibri;">Value</span></span></p>
</td>
</tr>
<tr>
<td valign="top" width="150">
<p><span style="font-family: Calibri;">Authorization</span></p>
</td>
<td valign="top" width="144">
<p><span style="font-family: Calibri;">Bearer</span></p>
</td>
<td valign="top" width="282">
<p><span style="font-family: Calibri;">Bearer&nbsp;</span>是唯一接受的授权机制。</p>
<p>该值还必须包括由<span style="font-family: Calibri;"> ACS </span>提供的访问令牌。</p>
</td>
</tr>
<tr>
<td valign="top" width="150">
<p><span style="font-family: Calibri;">x-ms-version</span></p>
</td>
<td valign="top" width="144">
<p><span style="font-family: Calibri;">Decimal</span></p>
</td>
<td valign="top" width="282">
<p><span style="font-family: Calibri;">2.7</span></p>
</td>
</tr>
<tr>
<td valign="top" width="150">
<p><span style="font-family: Calibri;">DataServiceVersion</span></p>
</td>
<td valign="top" width="144">
<p><span style="font-family: Calibri;">Decimal</span></p>
</td>
<td valign="top" width="282">
<p><span style="font-family: Calibri;">3.0</span></p>
</td>
</tr>
<tr>
<td valign="top" width="150">
<p><span style="font-family: Calibri;">MaxDataServiceVersion</span></p>
</td>
<td valign="top" width="144">
<p><span style="font-family: Calibri;">Decimal</span></p>
</td>
<td valign="top" width="282">
<p><span style="font-family: Calibri;">3.0</span></p>
</td>
</tr>
</tbody>
</table>
<p><span style="font-family: Calibri; font-size: small;">&nbsp;</span></p>
<p><span style="font-size: small;">若要直接通过<span style="font-family: Calibri;"> REST API </span>访问<span style="font-family: Calibri;"> WAMS</span>，必须从<span style="font-family: Calibri;"> ACS </span>检索一个访问令牌，并在向<span style="font-family: Calibri;">WAMS</span>提出每个<span style="font-family: Calibri;"> HTTP </span>请求期间使用该令牌<span style="font-family: Calibri;">;</span></span><span style="font-family: Calibri;"> <span style="font-size: small;">WAMS </span></span><span style="font-size: small;">的根<span style="font-family: Calibri;"> URI </span>为</span><a href="https://media.windows.net/"><span style="color: #0563c1; font-family: Calibri; font-size: small;">https://media.windows.net/</span></a><span style="font-size: small;">，先连接到此<span style="font-family: Calibri;"> URI</span>，如果在响应中收到&ldquo;<span style="font-family: Calibri;">301 </span>重定向&rdquo;，则应随后调用新的<span style="font-family: Calibri;"> URI</span>。所以访问<span style="font-family: Calibri;"> WAMS</span>时需要两项内容：由<span style="font-family: Calibri;"> Azure </span>访问控制服务<span style="font-family: Calibri;"> (ACS) </span>提供的访问令牌<span style="font-family: Calibri;">(access token)</span>和<span style="font-family: Calibri;"> WAMS</span>自身的<span style="font-family: Calibri;"> URI</span>。在创建这些请求时，可以使用任何方法，前提是在调用<span style="font-family: Calibri;"> WAMS</span>时指定了正确的标头<span style="font-family: Calibri;">(Header)</span>值，并且传入了正确的访问令牌。</span></p>
<p><a href="https://msdn.microsoft.com/zh-cn/library/azure/jj129576.aspx"><span style="color: #0563c1;"><span style="font-size: small;">使用<span style="font-family: Calibri;"> Media Services REST API </span>连接到<span style="font-family: Calibri;"> Media Services</span></span></span></a><span style="font-size: small;">的常见流程是：</span></p>
<ol>
<li>&nbsp;<span style="font-size: small;">获取访问令牌；</span></li>
<li><span style="font-size: small;">连接到<span style="font-family: Calibri;">WAMS</span>的<span style="font-family: Calibri;"> URI-</span></span><a href="https://media.windows.net/"><span style="color: #0563c1; font-family: Calibri; font-size: small;">https://media.windows.net</span></a><span style="font-size: small;"><span style="font-family: Calibri;">:&nbsp; </span>成功连接到该<span style="font-family: Calibri;">URI</span>后，将收到一个<span style="font-family: Calibri;"> <strong>301 </strong></span>重定向响应，指定另一个<span style="font-family: Calibri;">WAMS </span>的<span style="font-family: Calibri;">URI</span>。开发者必须对这个新<span style="font-family: Calibri;"> URI </span>进行后续调用。还可能会收到包含<span style="font-family: Calibri;"> ODATA API </span>元数据说明的<span style="font-family: Calibri;">&nbsp;HTTP/1.1 200&nbsp;</span>响应；</span></li>
<li><span style="font-size: small;">将后续<span style="font-family: Calibri;">API</span>调用发布到新的<span style="font-family: Calibri;">URL</span>。</span></li>
</ol>
<p><span style="font-size: small;">首先来看获取访问令牌的过程，<span style="font-family: Calibri;">HTTP</span>请求的<span style="font-family: Calibri;">header</span>及<span style="font-family: Calibri;">body</span>内容：</span></p>
<p style="padding-left: 30px;"><span style="font-family: Calibri;"><strong>POST</strong> https://wamsprodglobal001acs.accesscontrol.windows.net/v2/OAuth2-13 HTTP/1.1</span></p>
<p style="padding-left: 30px;"><span style="font-family: Calibri;">Content-Type: application/x-www-form-urlencoded</span></p>
<p style="padding-left: 30px;"><span style="font-family: Calibri;">Host: wamsprodglobal001acs.accesscontrol.windows.net</span></p>
<p style="padding-left: 30px;"><span style="font-family: Calibri;"><strong>Content-Length</strong>: 120</span></p>
<p style="padding-left: 30px;"><span style="font-family: Calibri;">Expect: 100-continue</span></p>
<p style="padding-left: 30px;"><span style="font-family: Calibri;">Connection: Keep-Alive</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: Calibri;">grant_type=client_credentials&amp;<strong>client_id</strong>=client id value&amp;<strong>client_secret</strong>=URL-encoded client secret value&amp;scope=urn%3aWindowsAzureMediaServices</span></p>
<p><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 其中<span style="font-family: Calibri;">client_id</span>和<span style="font-family: Calibri;">client_secret</span>对应媒体服务的账户名称和编码后的密钥。</span></p>
<p><span style="font-size: small;">为便于解析响应的<span style="font-family: Calibri;">JSON</span>和<span style="font-family: Calibri;">HTML </span>内容，<span style="font-family: Calibri;">Nuget </span>添加工具<span style="font-family: Calibri;">Json.Net </span>和<span style="font-family: Calibri;">HtmlAgilityPack</span></span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; <a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/3036.Json_HtmlAgilityPack.jpg" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/3036.Json_5F00_HtmlAgilityPack.jpg"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/3036.Json_HtmlAgilityPack.jpg" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/3036.Json_5F00_HtmlAgilityPack.jpg" alt="" border="0" /></a></p>
<p><span style="font-family: Calibri; font-size: small;">&nbsp;</span></p>
<p><span style="font-size: small;">由于<span style="font-family: Calibri;">HttpWebRequest </span>部分函数在<span style="font-family: Calibri;">WinRT</span>下已被弃用，导致在<span style="font-family: Calibri;">WinRT</span>下无法对一些<span style="font-family: Calibri;">header</span>值进行修改如<span style="font-family: Calibri;">Content-Length</span>，我们在此使用包含丰富的异步支持的</span><a href="https://msdn.microsoft.com/en-us/library/system.net.http.httpclient%28VS.110%29.aspx"><span style="color: #0563c1; font-family: Calibri; font-size: small;">HttpClient</span></a><span style="font-size: small;"><span style="text-decoration: underline;"><span style="color: #0563c1;">类</span></span>。</span></p>
<p><span style="font-size: small;">先定义一些常用变量及函数（</span>CreateBasicAuthenticationHeader<span style="font-size: small;">）：</span></p>
<p><span style="font-family: Calibri;">static string accountName = "MediaServiceAccountName";</span></p>
<p><span style="font-family: Calibri;">static string accountKey = "MediaServiceAccountKey";</span></p>
<p><span style="font-family: Calibri;">private const string acsEndpoint = "https://wamsprodglobal001acs.accesscontrol.windows.net/v2/OAuth2-13";</span></p>
<p><span style="font-family: Calibri;">private const string acsRequestBodyFormat = "grant_type=client_credentials&amp;client_id={0}&amp;client_secret={1}&amp;scope=urn%3aWindowsAzureMediaServices";</span><span style="font-family: Calibri;">&nbsp;</span></p>
<p><span style="font-family: Calibri;">private string WAMSEndpoint = "https://media.windows.net/";</span></p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p>&nbsp;private static AuthenticationHeaderValue CreateBasicAuthenticationHeader(string acsToken)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return new AuthenticationHeaderValue("Bearer", acsToken);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p><span style="font-family: Calibri; font-size: small;">&nbsp;</span></p>
<p><span style="font-size: small;">获取<span style="font-family: Calibri;">access token</span>的执行过程可参考如下代码：</span></p>
<p><span style="font-family: Calibri;">&nbsp; </span>&nbsp; private async Task&lt;string&gt; GetAccessTokenAsync(string accountName, string accountKey)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpClient httpClient = new HttpClient();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.MaxResponseContentBufferSize = int.MaxValue;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string requestBody = string.Format(CultureInfo.InvariantCulture, acsRequestBodyFormat, accountName, WebUtility.UrlEncode(accountKey));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpContent body = new StringContent(requestBody);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; body.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var response =await httpClient.PostAsync(acsEndpoint, body);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (response.IsSuccessStatusCode)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var content = await response.Content.ReadAsStringAsync();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JObject jsonObject = JObject.Parse(content);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string acsToken = jsonObject.Value&lt;string&gt;("access_token");&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return acsToken;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return null;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>执行成功后，获得<span style="font-family: Calibri;">ACS token</span>如下：</p>
<p>&nbsp;&nbsp;&nbsp; <a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/8546.ACSToken.jpg" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/8546.ACSToken.jpg"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/8546.ACSToken.jpg" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/8546.ACSToken.jpg" alt="" border="0" /></a>&nbsp;</p>
<p>获得<span style="font-family: Calibri;">ACS token</span>后，再链接到媒体服务的原始<span style="font-family: Calibri;">URI </span><a href="https://media.windows.net/"><span style="color: #0563c1; font-family: Calibri;">https://media.windows.net/</span></a>获取重定向响应以提取新的媒体服务<span style="font-family: Calibri;">URI, </span>抓取<span style="font-family: Calibri;">Fiddler trace</span>可以看到在客户端链接到<a href="https://media.windows.net/"><span style="color: #0563c1; font-family: Calibri;">https://media.windows.net/</span></a>后，会返回一个<span style="font-family: Calibri;">301</span>响应，包含了新的媒体服务<span style="font-family: Calibri;">URI</span>如下，需用从响应内容中解析出该<span style="font-family: Calibri;">URI</span>，可以使用工具<span style="font-size: small;"><span style="font-family: Calibri;">HtmlAgilityPack</span>。获取到新的媒体服务<span style="font-family: Calibri;"> URI</span>如：<span style="font-family: Calibri;">https://wamshknclus001rest-hs.cloudapp.net/api/</span>。</span></p>
<p><span style="font-family: Calibri;">&nbsp;</span>&lt;html&gt;</p>
<p>&nbsp; &lt;head&gt;&lt;title&gt;Object moved&lt;/title&gt;&lt;/head&gt;</p>
<p>&nbsp; &lt;body&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;h2&gt;Object moved to &lt;a href="<strong>https://wamshknclus001rest-hs.cloudapp.net/api</strong>/"&gt;here&lt;/a&gt;.&lt;/h2&gt;</p>
<p>&nbsp;&nbsp; &lt;/body&gt;</p>
<p>&lt;/html&gt;</p>
<p>&nbsp;&nbsp;&nbsp; <a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/3681.connectWAMS_301_200.jpg" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/3681.connectWAMS_5F00_301_5F00_200.jpg"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/3681.connectWAMS_301_200.jpg" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/3681.connectWAMS_5F00_301_5F00_200.jpg" alt="" border="0" /></a><span style="font-family: Calibri;">&nbsp;</span></p>
<p>&nbsp;</p>
<p>&nbsp;private async Task&lt;string&gt; ConnectMediaServiceAsync(string acsToken)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AuthenticationHeaderValue header = CreateBasicAuthenticationHeader(acsToken);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var handler = new HttpClientHandler()</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AllowAutoRedirect = false</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpClient httpClient = new HttpClient(handler);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.MaxResponseContentBufferSize = int.MaxValue;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("Authorization", header.ToString());</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("x-ms-version", "2.7");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("DataServiceVersion", "3.0");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; httpClient.DefaultRequestHeaders.Add("MaxDataServiceVersion", "3.0");</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, WAMSEndpoint);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var response = await httpClient.SendAsync(request);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //after connecting to https://media.windows.net, you will receive a 301 redirect specifying another Media Services URI.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // You must make subsequent calls to the new URI.&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string wamsEndPointFinal = WAMSEndpoint;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (response.StatusCode == HttpStatusCode.Moved || response.StatusCode == HttpStatusCode.MovedPermanently)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var htmlcontent = await response.Content.ReadAsStringAsync();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HtmlDocument htmlDocument = new HtmlDocument();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; htmlDocument.LoadHtml(htmlcontent);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var inputs_a = htmlDocument.DocumentNode.Descendants("a");&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string newLocation = null;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach (var input in inputs_a)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newLocation = input.Attributes["href"].Value;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (newLocation!=null)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wamsEndPointFinal = newLocation;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return wamsEndPointFinal;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p>完成以上设置，便可以进行后续媒体的上载，将在后续文章中详细讲述，敬请期待。</p>]]></content:encoded>
    </item>
    <item>
      <title>基于Windows Azure Media Service REST API 进行Windows Store/Windows Phone 应用开发系列-Part 1 简介</title>
      <link>https://docs.microsoft.com/archive/blogs/lj/windows-azure-media-service-rest-api-windows-storewindows-phone-part-1</link>
      <pubDate>Tue, 07 Oct 2014 23:01:00 GMT</pubDate>
      <dc:creator><![CDATA[JennyLi-MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/lj/2014/10/07/windows-azure-media-service-rest-api-windows-storewindows-phone-part-1/</guid>
      <description><![CDATA[在介绍基于Windows Azure Media Service REST API进行在Windows Store应用或Windows Phone应用的开发之前，我们首先对Windows Azure...]]></description>
      <content:encoded><![CDATA[<p>在介绍基于Windows Azure Media Service REST API进行在Windows Store应用或Windows Phone应用的开发之前，我们首先对Windows Azure Media Service进行简要介绍，以便于快速理解媒体服务的使用及开发过程。</p>
<p>Windows Azure Media Service (Windows Azure 媒体服务，简称WAMS)是基于Windows Azure平台的灵活、可靠、可自定义的媒体服务。该服务为用户提供媒体上传、编码及视频下载、点播和实时播放等功能。</p>
<p>Azure 的管理门户针对WAMS提供丰富的UI操作，管理媒体服务的账户、内容、作业、点播流、编码及媒体处理器等。每个WAMS账户创建在一个特定的Windows Azure 数据中心，每个账户有一个帐户名称及账户密钥，在使用WAMS 的REST API或.NET API时，需要使用该账户名称及密钥发送验证请求及调用API进行后续编码、内容发布等。每个WAMS 账户都有一个或多个相关联的Azure Storage 账户，用于存储关联的WAMS 账户控制的媒体内容。用户可以登录https://www.windowsazure.cn/ 进行登记注册，成为Azure用户，登录后即可使用媒体服务。</p>
<p>在使用WAMS前，我们先来快速了解一些常用术语，部分内容可以参见 MSDN 文档<a href="https://msdn.microsoft.com/library/azure/hh973632.aspx">Azure Media Services 概述</a>：</p>
<p><strong><a href="https://msdn.microsoft.com/zh-cn/library/azure/hh974277.aspx">资产</a></strong><strong>（</strong><strong>Asset</strong><strong>）</strong>&mdash;&mdash; 资产是包含媒体信息的逻辑实体，它可能包含了一个或多个需要处理的数字文件（audio, video等）。</p>
<p><strong>传送（</strong><strong>Delivery</strong><strong>）</strong>&mdash;&mdash; 传送/发布处理过的媒体，可能是以实时传送的方式或点播的方式发布到客户端，或者从cloud端获取/下载指定的媒体文件，或者部署媒体资产到其他的server端如Azure CDN server 等。</p>
<p><strong>文件（</strong><strong>File</strong><strong>）</strong>&mdash;&mdash; 一个文件表示待处理的包含audio/video的blob对象<strong> </strong>，文件都是存储在Azure 的blob&nbsp; storage里。一个文件总是与一个资产（asset）相关联，一个资产能够包含一个或多个文件。</p>
<p><strong>引入</strong><strong>/</strong><strong>上载（</strong><strong>Ingestion</strong><strong>/uploading</strong><strong>）</strong>&mdash;&mdash; 表示将资产上传给媒体服务的过程 。该过程包含上传文件到blob storage及对资产进行加密保护。</p>
<p><strong><a href="https://msdn.microsoft.com/zh-cn/library/azure/hh974289.aspx">作业（Job）</a></strong>&mdash;&mdash; 一个作业表示包含一组任务的逻辑实体，即对资产和作业进行相关处理的过程如编码，该过程包含一个或多个任务，简言之即一个作业就是一组任务的集合，例如，有一个作业：将一个文件转换成多种格式的&ldquo;编码&rdquo;作业，则该作业包含多个任务，每个任务负责将该文件转换成一个特定的文件格式。</p>
<p><strong>管理（</strong><strong>Manage</strong><strong>）</strong>&mdash;&mdash; 表示对媒体服务中的资产进行管理的过程，如枚举、删除、编辑资产，管理资产密钥，管理DRM 密钥等。</p>
<p><strong>处理（</strong><strong>Processing</strong><strong>）</strong>&mdash;&mdash; WAMS非常重要的操作，该操作包含对资产进行处理如编码、输出转码后新建的资产，对资产进行复合使用，创建编码作业、创建作业模板、检查作业状态、取消作业等。</p>
<p><strong>任务（</strong><strong>Task</strong><strong>）</strong>&mdash;&mdash; 表示对资产或作业的一项独立操作，一个任务总是与一个作业相关联，一个作业包含一个或多个任务 。</p>
<p><strong>访问策略（</strong><strong>Access Policies</strong><strong>）</strong>&mdash;&mdash; 访问策略决定了客户端具有的对给定资产的访问权限和持续时间，包含的访问类型： read/write/delete/list/none。</p>
<p><a href="https://msdn.microsoft.com/zh-cn/library/azure/hh974308.aspx">定位符（Locator）</a>&mdash;&mdash; 一个特殊的URL, 在一定时间段内有效的用于访问资产的链接，通常与访问策略一同使用。</p>
<p>客户端使用WAMS的基本流程包含4步：</p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </strong><strong>客户端初始设置链接到</strong><strong>WAMS-&gt;</strong><strong>媒体引入到</strong><strong>WAMS&ndash;&gt;WAMS </strong><strong>进行处理</strong><strong>&ndash;&gt;</strong><strong>媒体发布</strong><strong></strong></p>
<ol>
<li>客户端初始设置链接到WAMS: 配置客户端使用API访问WAMS 端点；</li>
<li>媒体引入到WAMS：上传一个或多个媒体文件到Azure Blob storage，即上文提及的资产；</li>
<li>WAMS进行处理：WAMS进行所需的处理，如编码，创建转码后的输出资产等；</li>
<li>媒体发布：创建定位符（URLs），用于输出资产的发布，可供下载或点播发布媒体流。</li>
</ol>
<p>接下来，将基于WAMS 提供过的REST API进行进行windows store、window phone 的应用开发，整个开发过程严格按照使用WAMS的4个基本过程。首先是进行WAMS链接的过程：<a href="https://blogs.msdn.com/b/lj/archive/2014/10/08/windows-azure-media-service-rest-api-windows-store-windows-phone-part-2-wams.aspx">将在基于Windows Azure Media Service REST API 进行Windows Store/Windows Phone 应用开发系列-Part 2初始设置链接到WAMS</a>进行详细讲解。</p>
<p>若感兴趣，还可以从WAMS的学习入口点<a href="https://msdn.microsoft.com/zh-cn/library/azure/hh973629">媒体服务</a>了解更多的信息。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>]]></content:encoded>
    </item>
    <item>
      <title>使用Windows Azure Mobile Service 进行Azure Active Directory 身份验证</title>
      <link>https://docs.microsoft.com/archive/blogs/lj/windows-azure-mobile-service-azure-active-directory</link>
      <pubDate>Fri, 26 Sep 2014 03:41:00 GMT</pubDate>
      <dc:creator><![CDATA[JennyLi-MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/lj/2014/09/26/windows-azure-mobile-service-azure-active-directory/</guid>
      <description><![CDATA[Windows Azure Mobile Service (WAMS) 对移动应用提供了多项功能，如数据交互/存储、用户身份认证、推送消息及调度作业（scheduled...]]></description>
      <content:encoded><![CDATA[<p><span style="font-family: Calibri;">Windows Azure Mobile Service (WAMS) </span>对移动应用提供了多项功能，如数据交互<span style="font-family: Calibri;">/</span>存储、用户身份认证、推送消息及调度作业（<span style="font-family: Calibri;">scheduled jobs</span>）等，本文结合<span style="font-family: Calibri;">WAMS</span>的身份认证功能介绍如何获取更多的用户信息如用户名用于应用显示。</p>
<p>微软官方文档<a href="https://azure.microsoft.com/en-us/documentation/articles/mobile-services-windows-store-dotnet-get-started-users/"><span style="color: #0563c1; font-family: Calibri;">Get started with authentication in Mobile Services</span></a>详细介绍了如何使用所支持的<span style="font-family: Calibri;">identity provider </span>如<a href="https://azure.microsoft.com/en-us/documentation/articles/mobile-services-how-to-register-microsoft-authentication/" target="_blank"><span style="font-family: Calibri;">Microsoft Account</span></a>、<a href="https://azure.microsoft.com/en-us/documentation/articles/mobile-services-how-to-register-facebook-authentication/" target="_blank"><span style="font-family: Calibri;">Facebook login</span></a>、<a href="https://azure.microsoft.com/en-us/documentation/articles/mobile-services-how-to-register-twitter-authentication/" target="_blank"><span style="font-family: Calibri;">Twitter login</span></a>、<a href="https://azure.microsoft.com/en-us/documentation/articles/mobile-services-how-to-register-google-authentication/" target="_blank"><span style="font-family: Calibri;">Google login</span></a>及<a href="https://azure.microsoft.com/en-us/documentation/articles/mobile-services-how-to-register-active-directory-authentication/" target="_blank"><span style="font-family: Calibri;">Azure Active Directory</span></a>（<span style="font-family: Calibri;">AAD</span>）对移动应用提供身份验证功能，并且可以通过采用日志<a href="https://blogs.msdn.com/b/carlosfigueira/archive/2013/12/12/expanded-login-scopes-in-azure-mobile-services.aspx"><span style="color: #0563c1; font-family: Calibri;">Expanded login scopes in Azure Mobile Services</span></a>介绍的<span style="font-family: Calibri;">API</span>获取用户<span style="font-family: Calibri;">ID</span>信息，该文档介绍了如何通过<span style="font-family: Calibri;">Graph API</span>获得<a href="https://azure.microsoft.com/en-us/documentation/articles/mobile-services-how-to-register-microsoft-authentication/" target="_blank"><span style="font-family: Calibri;">Microsoft Account</span></a>、<a href="https://azure.microsoft.com/en-us/documentation/articles/mobile-services-how-to-register-facebook-authentication/" target="_blank"><span style="font-family: Calibri;">Facebook login</span></a>或<a href="https://azure.microsoft.com/en-us/documentation/articles/mobile-services-how-to-register-google-authentication/" target="_blank"><span style="font-family: Calibri;">Google login</span></a>账号的用户信息，那么针对<a href="https://azure.microsoft.com/en-us/documentation/articles/mobile-services-how-to-register-active-directory-authentication/" target="_blank"><span style="font-family: Calibri;">Azure Active Directory</span></a>账号，该如何获取呢？<span style="font-family: Calibri;">AAD</span>也提供了丰富的<span style="font-family: Calibri;">Graph API</span>，可以用于获得用户信息。接下来我们以一个简单的<span style="font-family: Calibri;">Windows Store APP</span>为例详细讲解如何使用<a href="https://azure.microsoft.com/en-us/documentation/articles/mobile-services-how-to-register-active-directory-authentication/" target="_blank"><span style="font-family: Calibri;">Azure Active Directory</span></a>进行用户身份认证并获取<span style="font-family: Calibri;">ID</span>信息。<span style="font-family: Calibri;">&nbsp;</span></p>
<p>首先在<a href="https://manage.windowsazure.com/"><span style="font-family: Calibri;">Azure Management Portal</span></a>上创建一个<span style="font-family: Calibri;">Azure Mobile Service</span>，如名为<span style="font-family: Calibri;">wamsaad,</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/6332.01.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/6332.01.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/6332.01.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/6332.01.png" alt="" border="0" /></a></span></p>
<p>点击新建的<span style="font-family: Calibri;">Mobile Service </span>的<span style="font-family: Calibri;">IDENTITY </span>标签，滚动到<span style="font-family: Calibri;">windows azure active directory</span>，拷贝<span style="font-family: Calibri;">APP URL</span>的值<span style="font-family: Calibri;">-</span>如<span style="font-family: Calibri;">https://wamsaad.azure-mobile.net/login/aad</span>，将用于后续<span style="font-family: Calibri;">Active Directory </span>配置。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/1682.02.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/1682.02.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/1682.02.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/1682.02.png" alt="" border="0" /></a><span style="font-family: Calibri;">&nbsp;&nbsp; </span></p>
<p>切换到<span style="font-family: Calibri;">Active Directory</span>，创建一个新的<span style="font-family: Calibri;">AAD domain </span>如名为<span style="font-family: Calibri;">icesmart</span>，<a href="mailto:添加了两名用户test1@icesmart.onmicrosoft.com"><span style="font-size: small;">添加了两名用户<span style="font-family: Calibri;">test1@icesmart.onmicrosoft.com</span></span></a><a href="mailto:和test2@icesmart.onmicrosoft.com">和<span style="font-family: Calibri;">test2@icesmart.onmicrosoft.com</span></a>，当作测试账号。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/0640.03.PNG" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/0640.03.PNG"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/0640.03.PNG" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/0640.03.PNG" alt="" border="0" /></a><span style="font-family: Calibri;">&nbsp;</span></p>
<p>点击<span style="font-family: Calibri;">icesmart </span>的<span style="font-family: Calibri;">APPLICATIONS</span>标签，然后点击<span style="font-family: Calibri;">ADD</span>按钮添加一个应用，在弹出的对话框选择<span style="font-family: Calibri;">&ldquo;Add and application my organization is developing&rdquo;</span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/6076.04.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/6076.04.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/6076.04.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/6076.04.png" alt="" border="0" /></a></span><span style="font-family: Calibri;">&nbsp;</span></p>
<p>在<span style="font-family: Calibri;">Add Application</span>向导窗口添加一个新的应用，如名为<span style="font-family: Calibri;"> wamsaad</span>，选择类型为<span style="font-family: Calibri;">Web Application And/OR Web API</span>，在<span style="font-family: Calibri;">SIGN-ON URL</span>里，使用前文提及的<span style="font-family: Calibri;">mobile service </span>提供的<span style="font-family: Calibri;">active directory </span>身份认证的<span style="font-family: Calibri;">APP URL</span>值（<span style="font-family: Calibri;">https://wamsaad.azure-mobile.net/login/aad</span>），在<span style="font-family: Calibri;">APP ID URI</span>同样使用一个唯一的<span style="font-family: Calibri;">URI</span>，如<span style="font-family: Calibri;">https://wamsaad.azure-mobile.net/login/sso</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/2843.05.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/2843.05.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/2843.05.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/2843.05.png" alt="" border="0" /></a><span style="font-family: Calibri;">&nbsp;</span></p>
<p>应用添加完毕后，点击<span style="font-family: Calibri;">CONFIGURE</span>标签，拷贝<span style="font-family: Calibri;">CLIENT ID</span>值，粘贴到前文新建的<span style="font-family: Calibri;">Mobile Service wamsadd</span>的<span style="font-family: Calibri;">IDENTITY</span>标签下的<span style="font-family: Calibri;">windows azure active directory CLIEND ID</span>区域</p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/8357.06.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/8357.06.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/8357.06.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/8357.06.png" alt="" border="0" /></a></span></p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/5734.07.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/5734.07.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/5734.07.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/5734.07.png" alt="" border="0" /></a></span><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p>&nbsp;</p>
<p>点击新建的<span style="font-family: Calibri;">AAD application-wamsaad</span>，在<span style="font-family: Calibri;">CONFIGURE</span>标签下，点击页面底部的<span style="font-family: Calibri;">&ldquo;MANAGE MANIFEST&rdquo;</span>按钮下载<span style="font-family: Calibri;">manifest </span>文件，打开该文件将<strong>"appPermissions"</strong><strong>: [],</strong> 内容替换为如下内容后保存该文件，再点击<span style="font-family: Calibri;">&ldquo;MANAGE MANIFEST&rdquo;</span>按钮上传该文件</p>
<p>"appPermissions": [</p>
<p>&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "claimValue": "user_impersonation",</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "description": "Allow the application access to the mobile service",</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "directAccessGrantTypes": [],</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "displayName": "Have full access to the mobile service",</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "impersonationAccessGrantTypes": [</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "impersonated": "User",</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;"impersonator": "Application"</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ],</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "isDisabled": false,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "origin": "Application",</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "permissionId": "b69ee3c9-c40d-4f2a-ac80-961cd1534e40",</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "resourceScopeType": "Personal",</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "userConsentDescription": "Allow the application full access to the mobile service on your behalf",</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "userConsentDisplayName": "Have full access to the mobile service"</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>],</p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/5050.08-Manifest.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/5050.08_2D00_Manifest.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/5050.08-Manifest.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/5050.08_2D00_Manifest.png" alt="" border="0" /></a></span><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p>同时在该标签下<span style="font-family: Calibri;">Keys</span>区域，选择创建一个<span style="font-family: Calibri;">key</span>如<span style="font-family: Calibri;">1</span>年有效期，然后点击下端的<span style="font-family: Calibri;">SAVE</span>按钮，会生成一个<span style="font-family: Calibri;">Key</span>，注意保存该<span style="font-family: Calibri;">Key</span>，在使用<span style="font-family: Calibri;">Graph API</span>时会用到，当离开该页面时，<span style="font-family: Calibri;">key</span>值会被隐藏</p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/7215.09-Key.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/7215.09_2D00_Key.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/7215.09-Key.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/7215.09_2D00_Key.png" alt="" border="0" /></a></span></p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p>再在该页面上的<span style="font-family: Calibri;">permissions to other applications </span>区域做相应配置，依次选择<span style="font-family: Calibri;">Windows Azure Active Directory, Read directory data</span>等</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/6646.010-permission.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/6646.010_2D00_permission.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/6646.010-permission.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/6646.010_2D00_permission.png" alt="" border="0" /></a>&nbsp;&nbsp;&nbsp;<span style="font-family: Calibri;">&nbsp;</span></p>
<p>在<span style="font-family: Calibri;">Azure Mobile Service-wamsaad</span>端，点击<span style="font-family: Calibri;">API</span>标签，然后点击<span style="font-family: Calibri;">&ldquo;CREATE&rdquo;</span>按钮就创建一个<span style="font-family: Calibri;">API </span>如<span style="font-family: Calibri;">getUserInfo</span>，其<span style="font-family: Calibri;">SCRIPT</span>类容可参见<a href="https://gist.github.com/mattchenderson/a0e29f780d3e75e9b954"><span style="color: #0563c1;">文档</span></a>，替换自己的<span style="font-family: Calibri;">clientID, key</span>及<span style="font-family: Calibri;">AAD domain</span>值如<span style="font-family: Calibri;">icesmart.onmicrosoft.com</span>，该<span style="font-family: Calibri;">API</span>用于与<span style="font-family: Calibri;">AAD</span>通信，获得基本的<span style="font-family: Calibri;">Graph </span>数据；在移动设备端如<span style="font-family: Calibri;">Windows Store/Phone App</span>中，调用该<span style="font-family: Calibri;">API</span>，当用户使用<span style="font-family: Calibri;">AAD</span>账号登录后，<span style="font-family: Calibri;">App</span>获得用户数据，结果如下截图显示。</p>
<p>public class UserDetails</p>
<p>{</p>
<p>&nbsp;&nbsp;&nbsp; public String userPrincipalName { get; set; }</p>
<p>&nbsp;&nbsp;&nbsp; public String displayName { get; set; }</p>
<p>&nbsp;&nbsp;&nbsp; public String usageLocation { get; set; }</p>
<p>}</p>
<p>private MobileServiceUser user;</p>
<p>private static MobileServiceClient MobileService = new MobileServiceClient(</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "https://wamsaad.azure-mobile.net/", "Application Key");</p>
<p><span style="font-family: Calibri;">&nbsp;</span></p>
<p>&nbsp;&nbsp; private async System.Threading.Tasks.Task LoginAAD()</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (MobileService.CurrentUser == null)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string message;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; user = await MobileService.LoginAsync("aad");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var result = await MobileService.InvokeApiAsync("getuserinfo", HttpMethod.Get, null);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; UserDetails currentUser = JsonConvert.DeserializeObject&lt;UserDetails&gt;(result.ToString());&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; message = string.Format("Welcome, {0}! You are now logged in.", result.ToString() + currentUser.userPrincipalName);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch (InvalidOperationException)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;message = "You must log in. Login Required";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p><span style="font-family: Calibri;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/7245.012-WinStoreResult.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/7245.012_2D00_WinStoreResult.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/7245.012-WinStoreResult.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/7245.012_2D00_WinStoreResult.png" alt="" border="0" /></a></span></p>
<p>&nbsp;</p>]]></content:encoded>
    </item>
    <item>
      <title>Windows Phone App 的本地自动测试</title>
      <link>https://docs.microsoft.com/archive/blogs/lj/windows-phone-app</link>
      <pubDate>Tue, 12 Aug 2014 02:30:38 GMT</pubDate>
      <dc:creator><![CDATA[JennyLi-MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/lj/2014/08/12/windows-phone-app/</guid>
      <description><![CDATA[在上一篇blog 使用WACK 验证Windows Store App中，我们了解到为了加速Windows Store App的上架过程，强烈建议开发者使用Windows App Cert...]]></description>
      <content:encoded><![CDATA[<p><span style="font-size: small;">在上一篇blog <a href="https://blogs.msdn.com/b/lj/archive/2014/08/12/wack-windows-store-app.aspx"><span style="color: #0563c1;">使用WACK 验证Windows Store App</span></a>中，我们了解到为了加速Windows Store App的上架过程，强烈建议开发者使用Windows App Cert Kit-即WACK工具对APP进行测试验证，确保通过WACK测试之后再进行APP提交，因为Store对APP的审核过程也包含了WACK的测试过程。那么对于Windows Phone App，是否也遵循类似的审核逻辑呢？答案是肯定的，Windows Phone App的上架过程与Windows Store App的上架过程类似，只不过自动测试工具根据Windows Phone App的版本有所差别，本文将针对Windows Phone App的本地测试验证进行总结介绍。</span></p>
<p><span style="font-size: small;">我们从一个应用实例来看该测试过程的意义：有开发者发现对于Windows Phone OS 7.1的APP, 出于对用户安全隐私的考虑（如一些银行类的应用），其并没有在WMAppManifest.xml文件中声明使用ID_CAP_MEDIALIB（应用对媒体库的访问权限控制），但是当APP发布到Store后，App require 列表中却添加了Photo, music and video libraries内容，导致APP用户抱怨其安全隐患。这是为什么呢？原因在于Store在审核APP时，会使用一个工具对APP进行静态分析并自动添加所需要的Capabilities, 即若APP包含了使用媒体库的组件（如使用Microsoft.Xna.Framework.Media.MediaPlayer），那么ID_CAP_MEDIALIB会被自动添加。那么这个分析工具是什么呢？它即是<a href="https://msdn.microsoft.com/en-us/library/windowsphone/develop/hh394032(v=vs.105).aspx"><span style="color: #0563c1;">Store Test Kit</span></a>。这个工具集成在Windows Phone SDK8.0中，开发者可以使用Store Test Kit对使用某API的AP进行测试以判定其是否是依赖于某个capability。例如需要判别</span><span style="font-size: small;">Microsoft.Xna.Framework.Media.</span><span style="font-size: small;">MediaPlayer </span><span style="font-size: small;">类是否使用ID_CAP_MEDIALIB，使用Store Test Kit测试发现MediaPlayer 需要ID_CAP_MEDIALIB，简要过程为（基于Visual Studio 2012）：</span></p>
<p>1)&nbsp; 创建一个新的基于Windows Phone 7.1 OS的Project</p>
<p>2)&nbsp; 添加code, code中包含调用相应的API</p>
<p>3)&nbsp; &nbsp;&ldquo;Release&rdquo;编译APP</p>
<p>4)&nbsp; 运行<a href="https://msdn.microsoft.com/en-us/library/windowsphone/develop/hh394032(v=vs.105).aspx"><span style="color: #0563c1;">Store Test Kit</span></a>（右击该project，选择&ldquo;Open Store Test Kit&rdquo;即可）</p>
<p>5)&nbsp; 在Automated Tests 标签下，点击 &ldquo;Run Tests&rdquo; 按钮进行测试，发现需要用到ID_CAP_MEDIALIB</p>
<p><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/5543.01.jpg" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/5543.01.jpg"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/5543.01.jpg" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/5543.01.jpg" alt="" border="0" /></a></span></p>
<p>&nbsp;<span style="font-size: small;">针对这种场景，可以使用其他的类做替代，如若是需要播放音乐（<a href="https://msdn.microsoft.com/en-us/library/bb195053.aspx"><span style="color: #0563c1;">playing a sound</span></a>），可以使用<a href="https://msdn.microsoft.com/en-us/library/microsoft.xna.framework.audio.soundeffect.aspx"><span style="color: #0563c1;">Soundeffect</span></a>类，使用Store Test Kit发现不要求ID_CAP_MEDIALIB；或者若是需要添加背景音乐，可以参考 sample <a href="https://go.microsoft.com/fwlink/p/?LinkId=219073"><span style="color: #0563c1;">Background Audio Player Sample</span></a>，在文档中<a href="https://msdn.microsoft.com/en-us/library/windowsphone/develop/hh202978(v=vs.105).aspx"><span style="color: #0563c1;">How to play background audio for Windows Phone</span></a>有所提及，Store Test Kit测试发现同样不要求ID_CAP_MEDIALIB。</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/2625.02.jpg" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/2625.02.jpg"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/2625.02.jpg" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/2625.02.jpg" alt="" border="0" /></a></p>
<p><span style="font-size: small;">以上仅以一个简单的实例说明使用Store Test Kit进行Capability的需求判别，当然该工具还包含许多其他内容的测试，可以详细参见<a href="https://msdn.microsoft.com/library/windows/apps/hh394032(v=vs.105).aspx"><span style="color: #0563c1;">MSDN 文档</span></a>。该工具对Windows Phone OS 7.1 及Windows Phone 8.0 OS的APP进行测试，对于Windows Phone 8.1 OS的APP， 我们使用WACK工具。</span></p>
<p><span style="font-size: small;">使用最新版本的WACK（3.3）对Windows Phone 8.1 App进行测试，需要首先在Visual Studio 2013中创建Package，然后运行最新版本的Windows Cert App Kit, 过程大致与<a href="https://blogs.msdn.com/b/lj/archive/2014/08/12/wack-windows-store-app.aspx"><span style="color: #0563c1;">使用WACK 验证Windows Store App</span></a>描述的UI运行WACK 对Windows Store App的审核过程类似，选择Validate Windows Phone App，在后续弹出的APP选择框中从文件系统对应Windows Phone 8.1 App package 文件，WACK对Windows Phone 的测试内容大致包含10个测试项，可以详见<a href="https://msdn.microsoft.com/en-in/library/windows/apps/dn629257.aspx"><span style="color: #0563c1;">MSDN 文档</span></a>。</span></p>
<p><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/8814.03.jpg" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/8814.03.jpg"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/8814.03.jpg" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/8814.03.jpg" alt="" border="0" /></a></span></p>
<p><span style="font-size: small;">&nbsp;</span></p>
<p><span style="font-size: small;">除了使用UI方式，我们也可以通过命令行的方式，同<a href="https://blogs.msdn.com/b/lj/archive/2014/08/12/wack-windows-store-app.aspx"><span style="color: #0563c1;">使用WACK 验证Windows Store App</span></a>介绍的命令行方式大致相同，同样使用C:\Program Files (x86)\Windows Kits\8.1\App Certification Kit目录下的<strong>appcert.exe</strong>工具，只不过运行的命令只能使用package的目录方式。过程如下：</span></p>
<p>1)&nbsp; 以Administrator权限运行cmd.exe</p>
<p>2)&nbsp; 运行如下命令：</p>
<p>&nbsp; &nbsp;cd C:\Program Files (x86)\Windows Kits\8.1\App Certification Kit</p>
<p>&nbsp;&nbsp;&nbsp; appcert.exe<strong> </strong>reset&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; appcert.exe test -apptype <strong>windowsphoneapp</strong> -appxpackagepath [path\xxx.appx] -reportoutputpath [report file name ]</p>
<p>例如：appcert test -apptype windowsphoneapp -appxpackagepath C:\Input\MyApp.appx -reportoutputpath c:\Output\MyReport.xml</p>
<p>Demo演示截图如下：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/0486.06.jpg" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/0486.06.jpg"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/61/0486.06.jpg" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-61/0486.06.jpg" alt="" border="0" /></a>&nbsp;</p>
<p><span style="font-size: small;">本文简要总结对Windows Phone App的本地验证，对于Windows Phone OS 7.1/8.0的APP，使用Windows Phone SDK8.0包含的Store Test Kit, 对于Windows Phone OS8.1的APP，则使用WACK工具进行测试，可以采用UI方式，也可以采用命令行方式，根据测试结果进行APP project 的修复，确保APP通过Store Test Kit 或WACK 测试，再进行APP提交，以加快APP的成功发布过程。</span></p>]]></content:encoded>
    </item>
  </channel>
</rss>