使用 PlayReady 动态通用加密Use PlayReady dynamic common encryption

Note

Google Widevine 内容保护服务目前在 Azure 中国区域不可用。Google Widevine content protection services are currently unavailable in the Azure China regions.

Note

要完成本教程,需要一个 Azure 帐户。To complete this tutorial, you need an Azure account. 有关详细信息,请参阅 1 元试用For details, see Azure 1rmb Trial. 不会向媒体服务 v2 添加任何新特性或新功能。No new features or functionality are being added to Media Services v2.
查看最新版本:媒体服务 v3Check out the latest version, Media Services v3. 另请参阅从 v2 到 v3 的迁移指南Also, see migration guidance from v2 to v3

概述Overview

可以使用媒体服务传送受 PlayReady 数字版权管理 (DRM) 保护的 MPEG-DASH 流、平滑流式处理流和 HTTP 实时流式处理 (HLS) 流。You can use Media Services to deliver MPEG-DASH, Smooth Streaming, and HTTP Live Streaming (HLS) streams protected with PlayReady digital rights management (DRM). PlayReady 是按通用加密 (ISO/IEC 23001-7 CENC) 规范加密的。PlayReady is encrypted per the common encryption (ISO/IEC 23001-7 CENC) specification.

媒体服务提供了用于传送 PlayReady DRM 许可证的服务。Media Services provides a service for delivering PlayReady DRM licenses. 媒体服务还提供可用于配置权限和限制的 API,这样当用户播放受保护的内容时,便可通过 PlayReady DRM 运行时强制实施这些权限和限制。Media Services also provides APIs that you can use to configure the rights and restrictions that you want the PlayReady DRM runtime to enforce when a user plays back protected content. 当用户请求受 DRM 保护的内容时,播放器应用程序会从媒体服务许可证服务请求许可证。When a user requests DRM-protected content, the player application requests a license from the Media Services license service. 如果播放器应用程序获得授权,媒体服务许可证服务会向该播放器颁发许可证。If the player application is authorized, the Media Services license service issues a license to the player. PlayReady 许可证包含客户端播放器用来对内容进行解密和流式传输的解密密钥。A PlayReady license contains the decryption key that can be used by the client player to decrypt and stream the content.

媒体服务支持通过多种方式对发出密钥请求的用户进行授权。Media Services supports multiple ways of authorizing users who make key requests. 内容密钥授权策略可能有一种或多种授权限制:开放或令牌限制。The content key authorization policy can have one or more authorization restrictions, either open or token restrictions. 令牌限制策略必须附带由安全令牌服务 (STS) 颁发的令牌。The token-restricted policy must be accompanied by a token issued by a security token service (STS). 媒体服务支持采用简单 Web 令牌 (SWT) 格式和 JSON Web 令牌 (JWT) 格式的令牌。Media Services supports tokens in the simple web token (SWT) and JSON Web Token (JWT) formats.

有关详细信息,请参阅配置内容密钥授权策略For more information, see Configure the content key's authorization policy.

为了充分利用动态加密,资产需包含一组多码率 MP4 文件或多码率平滑流源文件。To take advantage of dynamic encryption, you need an asset that contains a set of multi-bitrate MP4 files or multi-bitrate Smooth Streaming source files. 还需要为资产配置传送策略(在本主题后面部分介绍)。You also need to configure the delivery policies for the asset (described later in this topic). 然后,根据在流式处理 URL 中指定的格式,按需流式处理服务器会确保使用选定的协议来传送流。Then, based on the format specified in the streaming URL, the on-demand streaming server ensures that the stream is delivered in the protocol you selected. 因此,可存储只使用单一存储格式的文件并为其付费。As a result, you store and pay for the files in only a single storage format. 媒体服务会根据客户端的每个请求生成并提供适当的 HTTP 响应。Media Services builds and serves the appropriate HTTP response based on each request from a client.

如果开发人员要让自己开发的应用程序能够传送受多个 DRM(例如 PlayReady)保护的媒体,本文可以提供帮助。This article is useful to developers who work on applications that deliver media protected with multiple DRMs, such as PlayReady. 本文介绍如何使用授权策略来配置 PlayReady 许可证传送服务,确保只有经过授权的客户端才能接收 PlayReady 许可证。The article shows you how to configure the PlayReady license delivery service with authorization policies so that only authorized clients can receive PlayReady licenses. 此外,还介绍如何通过 DASH 使用 PlayReady DRM 进行动态加密。It also shows how to use dynamic encryption with PlayReady DRM over DASH.

Note

创建媒体服务帐户后,一个处于“已停止”状态的默认流式处理终结点会添加到帐户。When your Media Services account is created, a default streaming endpoint is added to your account in the "Stopped" state. 若要开始流式传输内容并利用动态打包和动态加密,传出流式传输内容的流式处理终结点必须处于“正在运行”状态。To start streaming your content and take advantage of dynamic packaging and dynamic encryption, the streaming endpoint from which you want to stream content must be in the "Running" state.

下载示例Download the sample

可以从 GitHub 上的 Azure 示例下载本文所述的示例。You can download the sample described in this article from Azure samples on GitHub.

配置动态通用加密和 DRM 许可证传送服务Configure dynamic common encryption and DRM license delivery services

使用媒体服务许可证传送服务和动态加密通过 PlayReady 来保护资产时,请执行下述常规步骤:Perform the following general steps when you protect your assets with PlayReady by using the Media Services license delivery service and also by using dynamic encryption:

  1. 创建资产并将文件上传到资产。Create an asset, and upload files into the asset.

  2. 将包含文件的资产编码为自适应比特率 MP4 集。Encode the asset that contains the file to the adaptive bitrate MP4 set.

  3. 创建内容密钥并将其与编码资产相关联。Create a content key, and associate it with the encoded asset. 在媒体服务中,内容密钥包含资产的加密密钥。In Media Services, the content key contains the asset's encryption key.

  4. 配置内容密钥授权策略。Configure the content key's authorization policy. 必须配置内容密钥授权策略。You must configure the content key authorization policy. 客户端必须符合该策略才能将内容密钥传送到客户端。The client must meet the policy before the content key is delivered to the client.

    创建内容密钥授权策略时,必须指定传送方法 (PlayReady) 和限制(开放或令牌)。When you create the content key authorization policy, you must specify the delivery method (PlayReady) and the restrictions (open or token). 还必须指定特定于密钥传送类型的信息,以便定义将密钥传送到客户端的方法(PlayReady 许可证模板)。You also must specify information specific to the key delivery type that defines how the key is delivered to the client (PlayReady license template).

  5. 为资产配置传送策略。Configure the delivery policy for an asset. 传送策略配置包括传送协议(例如,MPEG-DASH、HLS、平滑流式处理或所有这些协议)。The delivery policy configuration includes the delivery protocol (for example, MPEG-DASH, HLS, Smooth Streaming, or all). 配置还包括动态加密类型(例如通用加密)和 PlayReady 许可证获取 URL。The configuration also includes the type of dynamic encryption (for example, common encryption) and the PlayReady license acquisition URL.

    可以对同一资产上的不同协议应用不同的策略。You can apply a different policy to each protocol on the same asset. 例如,可以将 PlayReady 加密应用到平滑流/DASH,将 AES 信封应用到 HLS。For example, you can apply PlayReady encryption to Smooth/DASH and an AES envelope to HLS. 传送策略中未定义的任何协议(例如,如果添加的单个策略仅将 HLS 指定为协议)都无法进行流式处理。Any protocols that aren't defined in a delivery policy (for example, if you add a single policy that specifies only HLS as the protocol) are blocked from streaming. 如果根本没有定义任何资产传送策略,则属例外。The exception is if you have no asset delivery policy defined at all. 此时,允许所有明文形式的协议。Then, all protocols are allowed in the clear.

  6. 创建 OnDemand 定位符以获取流式处理 URL。Create an OnDemand locator to get a streaming URL.

可以在文章末尾找到完整的 .NET 示例。You can find a complete .NET example at the end of the article.

下图演示了上述工作流。The following image demonstrates the workflow previously described. 在图中,使用令牌进行了身份验证。Here, the token is used for authentication.

使用 PlayReady 进行保护

本文余下部分提供了详细说明、代码示例和主题链接,介绍了如何完成上述任务。The remainder of this article provides detailed explanations, code examples, and links to topics that show you how to achieve the tasks previously described.

当前限制Current limitations

如果添加或更新资产传送策略,则必须删除任何关联的定位符并创建新的定位符。If you add or update an asset delivery policy, you must delete any associated locator and create a new locator.

创建资产并将文件上传到资产Create an asset and upload files into the asset

为了对视频进行管理、编码和流式处理,必须首先将内容上传到媒体服务中。To manage, encode, and stream your videos, you must first upload your content into Media Services. 上传完成后,相关内容即安全地存储在云中供后续处理和流式处理。After it's uploaded, your content is stored securely in the cloud for further processing and streaming.

有关详细信息,请参阅将文件上传到媒体服务帐户For more information, see Upload files into a Media Services account.

将包含文件的资产编码为自适应比特率 MP4 集Encode the asset that contains the file to the adaptive bitrate MP4 set

使用动态加密时,可创建一项资产,其中包含一组多码率 MP4 文件或多比特率平滑流式处理源文件。With dynamic encryption, you create an asset that contains a set of multi-bitrate MP4 files or multi-bitrate Smooth Streaming source files. 然后,按需流式处理服务器会确保你以选定的协议按清单和分段请求中的指定格式接收流。Then, based on the specified format in the manifest and fragment request, the on-demand streaming server ensures that you receive the stream in the protocol you selected. 然后即可存储只使用单一存储格式的文件并为其付费。Then, you store and pay for the files in only a single storage format. 媒体服务会根据客户端的请求生成并提供适当的响应。Media Services builds and serves the appropriate response based on requests from a client. 有关详细信息,请参阅动态打包概述For more information, see Dynamic packaging overview.

有关如何编码的说明,请参阅使用 Media Encoder Standard 对资产进行编码For instructions on how to encode, see Encode an asset by using Media Encoder Standard.

创建内容密钥并将其与编码资产相关联Create a content key and associate it with the encoded asset

在媒体服务中,内容密钥包含用于加密资产的密钥。In Media Services, the content key contains the key that you want to encrypt an asset with.

有关详细信息,请参阅创建内容密钥For more information, see Create a content key.

配置内容密钥授权策略Configure the content key's authorization policy

媒体服务支持通过多种方式对发出密钥请求的用户进行身份验证。Media Services supports multiple ways of authenticating users who make key requests. 必须配置内容密钥授权策略。You must configure the content key authorization policy. 客户端(播放器)必须符合该策略才能将密钥传送到客户端。The client (player) must meet the policy before the key is delivered to the client. 内容密钥授权策略可能有一种或多种授权限制:开放或令牌限制。The content key authorization policy can have one or more authorization restrictions, either open or token restrictions.

有关详细信息,请参阅配置内容密钥授权策略For more information, see Configure a content key authorization policy.

配置资产传送策略Configure an asset delivery policy

为资产配置传送策略。Configure the delivery policy for your asset. 资产传送策略配置包括:Some things that the asset delivery policy configuration includes are:

  • DRM 许可证获取 URL。The DRM license acquisition URL.
  • 资产传送协议(例如 MPEG-DASH、HLS、平滑流式处理或所有这些协议)。The asset delivery protocol (for example, MPEG-DASH, HLS, Smooth Streaming, or all).
  • 动态加密类型(在本示例中为“通用加密”)。The type of dynamic encryption (in this case, common encryption).

有关详细信息,请参阅配置资产传送策略For more information, see Configure an asset delivery policy.

创建 OnDemand 流式处理定位符以获取流式处理 URLCreate an OnDemand streaming locator to get a streaming URL

需要为用户提供平滑流式处理、DASH 或 HLS 的流式处理 URL。You need to provide your user with the streaming URL for Smooth Streaming, DASH, or HLS.

Note

如果添加或更新资产的传送策略,则必须删除现有的定位符并创建新的定位符。If you add or update your asset's delivery policy, you must delete any existing locator and create a new locator.

有关如何发布资产和生成流 URL 的说明,请参阅 生成流 URLFor instructions on how to publish an asset and build a streaming URL, see Build a streaming URL.

获取测试令牌Get a test token

获取用于密钥授权策略的基于令牌限制的测试令牌。Get a test token based on the token restriction that was used for the key authorization policy.

// Deserializes a string containing an XML representation of a TokenRestrictionTemplate
// back into a TokenRestrictionTemplate class instance.
TokenRestrictionTemplate tokenTemplate =
TokenRestrictionTemplateSerializer.Deserialize(tokenTemplateString);

// Generate a test token based on the data in the given TokenRestrictionTemplate.
//The GenerateTestToken method returns the token without the word "Bearer" in front,
//so you have to add it in front of the token string.
string testToken = TokenRestrictionTemplateSerializer.GenerateTestToken(tokenTemplate);
Console.WriteLine("The authorization token is:\nBearer {0}", testToken);

可以使用 Azure 媒体服务播放器来测试流。You can use the Azure Media Services Player to test your stream.

创建和配置 Visual Studio 项目Create and configure a Visual Studio project

  1. 设置开发环境,并根据使用 .NET 进行媒体服务开发中所述,在 app.config 文件中填充连接信息。Set up your development environment, and populate the app.config file with connection information, as described in Media Services development with .NET.

  2. 将以下元素添加到 app.config 文件中定义的 appSettingsAdd the following elements to appSettings defined in your app.config file:

    <add key="Issuer" value="http://testissuer.com"/>
    <add key="Audience" value="urn:test"/>
    

示例Example

以下示例演示了用于 .NET 的媒体服务 SDK 3.5.2 版中引入的功能。The following sample demonstrates functionality that was introduced in the Media Services SDK for .NET version 3.5.2.

使用本部分中所示的代码覆盖 Program.cs 文件中的代码。Overwrite the code in your Program.cs file with the code shown in this section.

Note

不同媒体服务策略的策略数限制为 1 百万个(例如,Locator 策略或 ContentKeyAuthorizationPolicy 的情况就是如此)。There is a limit of 1 million policies for different Media Services policies (for example, for Locator policy or ContentKeyAuthorizationPolicy). 如果始终使用相同的天数/访问权限,则使用相同的策略 ID。If you always use the same days/access permissions, use the same policy ID. 例如,适用于需要长期保留使用的定位符的策略(非上传策略)。An example is policies for locators that are intended to remain in place for a long time (non-upload policies).

有关详细信息,请参阅使用媒体服务 .NET SDK 管理资产和相关的实体For more information, see Manage assets and related entities with the Media Services .NET SDK.

请务必将变量更新为指向输入文件所在的文件夹。Make sure to update variables to point to folders where your input files are located.

using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Threading;
using Microsoft.WindowsAzure.MediaServices.Client;
using Microsoft.WindowsAzure.MediaServices.Client.ContentKeyAuthorization;
using Microsoft.WindowsAzure.MediaServices.Client.DynamicEncryption;
using Newtonsoft.Json;

namespace DynamicEncryptionWithDRM
{
    class Program
    {
        // Read values from the App.config file.
        private static readonly string _AADTenantDomain =
            ConfigurationManager.AppSettings["AMSAADTenantDomain"];
        private static readonly string _RESTAPIEndpoint =
            ConfigurationManager.AppSettings["AMSRESTAPIEndpoint"];
        private static readonly string _AMSClientId =
            ConfigurationManager.AppSettings["AMSClientId"];
        private static readonly string _AMSClientSecret =
            ConfigurationManager.AppSettings["AMSClientSecret"];

        private static readonly Uri _sampleIssuer =
            new Uri(ConfigurationManager.AppSettings["Issuer"]);
        private static readonly Uri _sampleAudience =
            new Uri(ConfigurationManager.AppSettings["Audience"]);

        // Field for service context.
        private static CloudMediaContext _context = null;

        private static readonly string _mediaFiles =
            Path.GetFullPath(@"../..\Media");

        private static readonly string _singleMP4File =
            Path.Combine(_mediaFiles, @"BigBuckBunny.mp4");

        static void Main(string[] args)
        {
            AzureAdTokenCredentials tokenCredentials =
                new AzureAdTokenCredentials(_AADTenantDomain,
                    new AzureAdClientSymmetricKey(_AMSClientId, _AMSClientSecret),
                    AzureEnvironments.AzureChinaCloudEnvironment);

            var tokenProvider = new AzureAdTokenProvider(tokenCredentials);

            _context = new CloudMediaContext(new Uri(_RESTAPIEndpoint), tokenProvider);

            bool tokenRestriction = false;
            string tokenTemplateString = null;

            IAsset asset = UploadFileAndCreateAsset(_singleMP4File);
            Console.WriteLine("Uploaded asset: {0}", asset.Id);

            IAsset encodedAsset = EncodeToAdaptiveBitrateMP4Set(asset);
            Console.WriteLine("Encoded asset: {0}", encodedAsset.Id);

            IContentKey key = CreateCommonTypeContentKey(encodedAsset);
            Console.WriteLine("Created key {0} for the asset {1} ", key.Id, encodedAsset.Id);
            Console.WriteLine("PlayReady License Key delivery URL: {0}", key.GetKeyDeliveryUrl(ContentKeyDeliveryType.PlayReadyLicense));
            Console.WriteLine();

            if (tokenRestriction)
                tokenTemplateString = AddTokenRestrictedAuthorizationPolicy(key);
            else
                AddOpenAuthorizationPolicy(key);

            Console.WriteLine("Added authorization policy: {0}", key.AuthorizationPolicyId);
            Console.WriteLine();

            CreateAssetDeliveryPolicy(encodedAsset, key);
            Console.WriteLine("Created asset delivery policy. \n");
            Console.WriteLine();

            if (tokenRestriction && !String.IsNullOrEmpty(tokenTemplateString))
            {
                // Deserializes a string containing an XML representation of a TokenRestrictionTemplate
                // back into a TokenRestrictionTemplate class instance.
                TokenRestrictionTemplate tokenTemplate =
                    TokenRestrictionTemplateSerializer.Deserialize(tokenTemplateString);

                // Generate a test token based on the data in the given TokenRestrictionTemplate.
                // Note that you need to pass the key ID GUID because 
                // TokenClaim.ContentKeyIdentifierClaim was specified during the creation of TokenRestrictionTemplate.
                Guid rawkey = EncryptionUtils.GetKeyIdAsGuid(key.Id);
                string testToken = TokenRestrictionTemplateSerializer.GenerateTestToken(tokenTemplate, null, rawkey,
                                            DateTime.UtcNow.AddDays(365));
                Console.WriteLine("The authorization token is:\nBearer {0}", testToken);
                Console.WriteLine();
            }

            // You can use the https://amsplayer.azurewebsites.net/azuremediaplayer.html player to test streams.
            // Note that DASH works on Internet Explorer 11 (via PlayReady), Microsoft Edge (via PlayReady).

            string url = GetStreamingOriginLocator(encodedAsset);
            Console.WriteLine("Encrypted DASH URL: {0}/manifest(format=mpd-time-csf)", url);

            Console.ReadLine();
        }

        static public IAsset UploadFileAndCreateAsset(string singleFilePath)
        {
            if (!File.Exists(singleFilePath))
            {
                Console.WriteLine("File does not exist.");
                return null;
            }

            var assetName = Path.GetFileNameWithoutExtension(singleFilePath);
            IAsset inputAsset = _context.Assets.Create(assetName, AssetCreationOptions.None);

            var assetFile = inputAsset.AssetFiles.Create(Path.GetFileName(singleFilePath));

            Console.WriteLine("Created assetFile {0}", assetFile.Name);

            Console.WriteLine("Upload {0}", assetFile.Name);

            assetFile.Upload(singleFilePath);
            Console.WriteLine("Done uploading {0}", assetFile.Name);

            return inputAsset;
        }

        static public IAsset EncodeToAdaptiveBitrateMP4Set(IAsset inputAsset)
        {
            var encodingPreset = "Adaptive Streaming";

            IJob job = _context.Jobs.Create(String.Format("Encoding into Mp4 {0} to {1}",
                        inputAsset.Name,
                        encodingPreset));

            var mediaProcessors =
            _context.MediaProcessors.Where(p => p.Name.Contains("Media Encoder Standard")).ToList();

            var latestMediaProcessor =
            mediaProcessors.OrderBy(mp => new Version(mp.Version)).LastOrDefault();

            ITask encodeTask = job.Tasks.AddNew("Encoding", latestMediaProcessor, encodingPreset, TaskOptions.None);
            encodeTask.InputAssets.Add(inputAsset);
            encodeTask.OutputAssets.AddNew(String.Format("{0} as {1}", inputAsset.Name, encodingPreset), AssetCreationOptions.StorageEncrypted);

            job.StateChanged += new EventHandler<JobStateChangedEventArgs>(JobStateChanged);
            job.Submit();
            job.GetExecutionProgressTask(CancellationToken.None).Wait();

            return job.OutputMediaAssets[0];
        }


        static public IContentKey CreateCommonTypeContentKey(IAsset asset)
        {

            Guid keyId = Guid.NewGuid();
            byte[] contentKey = GetRandomBuffer(16);

            IContentKey key = _context.ContentKeys.Create(
                        keyId,
                        contentKey,
                        "ContentKey",
                        ContentKeyType.CommonEncryption);

            // Associate the key with the asset.
            asset.ContentKeys.Add(key);

            return key;
        }

        static public void AddOpenAuthorizationPolicy(IContentKey contentKey)
        {

            // Create ContentKeyAuthorizationPolicy with open restrictions
            // and create an authorization policy.         

            List<ContentKeyAuthorizationPolicyRestriction> restrictions = new List<ContentKeyAuthorizationPolicyRestriction>
                {
                new ContentKeyAuthorizationPolicyRestriction
                {
                    Name = "Open",
                    KeyRestrictionType = (int)ContentKeyRestrictionType.Open,
                    Requirements = null
                }
                };

            // Configure PlayReady license template.
            string PlayReadyLicenseTemplate = ConfigurePlayReadyLicenseTemplate();

            IContentKeyAuthorizationPolicyOption PlayReadyPolicy =
            _context.ContentKeyAuthorizationPolicyOptions.Create("",
                ContentKeyDeliveryType.PlayReadyLicense,
                restrictions, PlayReadyLicenseTemplate);

            IContentKeyAuthorizationPolicy contentKeyAuthorizationPolicy = _context.
                ContentKeyAuthorizationPolicies.
                CreateAsync("Deliver Common Content Key with no restrictions").
                Result;


            contentKeyAuthorizationPolicy.Options.Add(PlayReadyPolicy);
            // Associate the content key authorization policy with the content key.
            contentKey.AuthorizationPolicyId = contentKeyAuthorizationPolicy.Id;
            contentKey = contentKey.UpdateAsync().Result;
        }

        public static string AddTokenRestrictedAuthorizationPolicy(IContentKey contentKey)
        {
            string tokenTemplateString = GenerateTokenRequirements();

            List<ContentKeyAuthorizationPolicyRestriction> restrictions = new List<ContentKeyAuthorizationPolicyRestriction>
                {
                new ContentKeyAuthorizationPolicyRestriction
                {
                    Name = "Token Authorization Policy",
                    KeyRestrictionType = (int)ContentKeyRestrictionType.TokenRestricted,
                    Requirements = tokenTemplateString,
                }
                };

            // Configure PlayReady license template.
            string PlayReadyLicenseTemplate = ConfigurePlayReadyLicenseTemplate();

            IContentKeyAuthorizationPolicyOption PlayReadyPolicy =
            _context.ContentKeyAuthorizationPolicyOptions.Create("Token option",
                ContentKeyDeliveryType.PlayReadyLicense,
                restrictions, PlayReadyLicenseTemplate);

            IContentKeyAuthorizationPolicy contentKeyAuthorizationPolicy = _context.
                ContentKeyAuthorizationPolicies.
                CreateAsync("Deliver Common Content Key with token restrictions").
                Result;

            contentKeyAuthorizationPolicy.Options.Add(PlayReadyPolicy);

            // Associate the content key authorization policy with the content key.
            contentKey.AuthorizationPolicyId = contentKeyAuthorizationPolicy.Id;
            contentKey = contentKey.UpdateAsync().Result;

            return tokenTemplateString;
        }

        static private string GenerateTokenRequirements()
        {
            TokenRestrictionTemplate template = new TokenRestrictionTemplate(TokenType.SWT);

            template.PrimaryVerificationKey = new SymmetricVerificationKey();
            template.AlternateVerificationKeys.Add(new SymmetricVerificationKey());
            template.Audience = _sampleAudience.ToString();
            template.Issuer = _sampleIssuer.ToString();
            template.RequiredClaims.Add(TokenClaim.ContentKeyIdentifierClaim);

            return TokenRestrictionTemplateSerializer.Serialize(template);
        }

        static private string ConfigurePlayReadyLicenseTemplate()
        {
            // The following code configures the PlayReady license template by using .NET classes
            // and returns the XML string.

            //The PlayReadyLicenseResponseTemplate class represents the template for the response sent back to the end user.
            //It contains a field for a custom data string between the license server and the application
            //(which might be useful for custom app logic) as well as a list of one or more license templates.
            PlayReadyLicenseResponseTemplate responseTemplate = new PlayReadyLicenseResponseTemplate();

            // The PlayReadyLicenseTemplate class represents a license template you can use to create PlayReady licenses
            // to be returned to end users.
            //It contains the data on the content key in the license and any rights or restrictions to be
            //enforced by the PlayReady DRM runtime when you use the content key.
            PlayReadyLicenseTemplate licenseTemplate = new PlayReadyLicenseTemplate();
            //Configure whether the license is persistent (saved in persistent storage on the client)
            //or nonpersistent (held in memory only while the player uses the license).  
            licenseTemplate.LicenseType = PlayReadyLicenseType.Nonpersistent;

            // AllowTestDevices controls whether test devices can use the license or not.  
            // If true, the MinimumSecurityLevel property of the license
            // is set to 150. If false (the default), the MinimumSecurityLevel property of the license is set to 2,000.
            licenseTemplate.AllowTestDevices = true;

            // You also can configure the PlayRight in the PlayReady license by using the PlayReadyPlayRight class.
            // It grants the user the ability to play back the content subject to the zero or more restrictions
            // configured in the license and on the PlayRight itself (for playback-specific policy).
            // Much of the policy on the PlayRight has to do with output restrictions,
            // which control the types of outputs that the content can be played over and
            // any restrictions that must be put in place when you use a given output.
            // For example, if DigitalVideoOnlyContentRestriction is enabled,
            // the DRM runtime allows the video to be displayed only over digital outputs
            //(analog video outputs aren't allowed to pass the content).

            //IMPORTANT: These types of restrictions can be very powerful but also can affect the consumer experience.
            // If output protections are too restrictive, 
            // content might be unplayable on some clients. For more information, see the PlayReady Compliance Rules document.

            // For example:
            //licenseTemplate.PlayRight.AgcAndColorStripeRestriction = new AgcAndColorStripeRestriction(1);

            responseTemplate.LicenseTemplates.Add(licenseTemplate);

            return MediaServicesLicenseTemplateSerializer.Serialize(responseTemplate);
        }

        static public void CreateAssetDeliveryPolicy(IAsset asset, IContentKey key)
        {
            // Get the PlayReady license service URL.
            Uri acquisitionUrl = key.GetKeyDeliveryUrl(ContentKeyDeliveryType.PlayReadyLicense);

            Dictionary<AssetDeliveryPolicyConfigurationKey, string> assetDeliveryPolicyConfiguration =
            new Dictionary<AssetDeliveryPolicyConfigurationKey, string>
            {
                    {AssetDeliveryPolicyConfigurationKey.PlayReadyLicenseAcquisitionUrl, acquisitionUrl.ToString()}

            };

            // In this case, we specify only the DASH streaming protocol in the delivery policy.
            // All other protocols are blocked from streaming.
            var assetDeliveryPolicy = _context.AssetDeliveryPolicies.Create(
                "AssetDeliveryPolicy",
            AssetDeliveryPolicyType.DynamicCommonEncryption,
            AssetDeliveryProtocol.Dash,
            assetDeliveryPolicyConfiguration);


            // Add AssetDelivery Policy to the asset.
            asset.DeliveryPolicies.Add(assetDeliveryPolicy);

        }

        /// <summary>
        /// Gets the streaming origin locator.
        /// </summary>
        /// <param name="assets"></param>
        /// <returns></returns>
        static public string GetStreamingOriginLocator(IAsset asset)
        {

            // Get a reference to the streaming manifest file from the 
            // collection of files in the asset.

            var assetFile = asset.AssetFiles.ToList().Where(f => f.Name.ToLower().
                         EndsWith(".ism")).
                         FirstOrDefault();

            // Create a 30-day read-only access policy.
            IAccessPolicy policy = _context.AccessPolicies.Create("Streaming policy",
            TimeSpan.FromDays(30),
            AccessPermissions.Read);

            // Create a locator to the streaming content on an origin.
            ILocator originLocator = _context.Locators.CreateLocator(LocatorType.OnDemandOrigin, asset,
            policy,
            DateTime.UtcNow.AddMinutes(-5));

            // Create a URL to the manifest file.
            return originLocator.Path + assetFile.Name;
        }

        static private void JobStateChanged(object sender, JobStateChangedEventArgs e)
        {
            Console.WriteLine(string.Format("{0}\n  State: {1}\n  Time: {2}\n\n",
            ((IJob)sender).Name,
            e.CurrentState,
            DateTime.UtcNow.ToString(@"yyyy_M_d__hh_mm_ss")));
        }

        static private byte[] GetRandomBuffer(int length)
        {
            var returnValue = new byte[length];

            using (var rng =
            new System.Security.Cryptography.RNGCryptoServiceProvider())
            {
                rng.GetBytes(returnValue);
            }

            return returnValue;
        }
    }
}

后续步骤Next steps

媒体服务 v3(最新版本)Media Services v3 (latest)

查看最新版本的 Azure 媒体服务!Check out the latest version of Azure Media Services!

媒体服务 v2(旧版)Media Services v2 (legacy)

另请参阅See also