导出 (0) 打印
全部展开

快速入门:使用 Media Services .NET SDK

更新时间: 2014年8月

本主题为 Microsoft Azure Media Services新开发人员提供了一个操作实例。它介绍基本的媒体服务工作流以及媒体服务开发所需的最常见编程对象和任务。若要大致了解媒体服务开发过程和编程对象模型,请参阅Azure Media Services 概述

此处提供了包含本教程代码的 C# Visual Studio 项目:下载

本操作实例演示如何执行以下操作:

note备注
示例

Tip提示
也可以选择使用 Azure Media Services .NET SDK Extensions 完成本主题中所描述的任务。媒体服务 .NET SDK Extensions 是一组扩展方法和帮助器函数,可简化你的代码,并令使用 媒体服务 进行开发变得更加容易。有关详细信息,请参阅快速入门:使用 Media Services .NET SDK Extensions

本操作实例和基于 Microsoft Azure Media Services SDK 的开发需要以下必备组件。

  • 新的或现有 Azure 订阅中的媒体服务帐户。请参阅主题 How to Create a Media Services Account(如何创建 Media Services 帐户)。

  • 操作系统:Windows 7、Windows 2008 R2 或 Windows 8。

  • .NET Framework 4。

  • Visual Studio 2013、Visual Studio 2012 或 Visual Studio 2010 SP1(专业版、高级版、旗舰版或速成版)。

  1. 在 Visual Studio 2013、Visual Studio 2012 或 Visual Studio 2010 SP1 中创建一个新的 C# 控制台应用程序。输入“名称”、“位置”和“解决方案名称”,然后单击“确定”。

  2. 添加对 媒体服务 及其依赖 DLL 的引用。

    媒体服务 SDK 与多个库(例如,Azure Storage SDK for .NETWCF Data Services for OData)存在依赖关系。你可以使用 windowsazure.mediaservices nuget 将 媒体服务 SDK 安装并添加到你的项目中,这样即可自动将所有依赖项安装并添加到你的项目中。

    此外,你还可以从 GitHub 获取最新的 媒体服务 SDK 资料,构建解决方案,并添加对客户端项目的引用。请注意,会自动下载并提取所有必需的依赖项。

    无论哪种方法,你都不必手动下载依赖项。

    若要使用 windowsazure.mediaservices NuGet 程序包添加必要的引用,请执行以下操作:

    1. 确保已安装最新版本的 NuGet。

      有关更多信息和安装说明,请参见 NuGet

    2. 在“解决方案资源管理器”中,右键单击项目名称,然后选择“管理 NuGet 程序包...”。

      随即显示“管理 NuGet 包”对话框。

    3. 在“联机”库中,搜索 MediaServices,选择 Azure Media Services .NET SDK,然后单击“安装”按钮。

      此时将修改项目并添加对 Media Services 程序集的引用。

    4. 若要升级更干净的开发环境,请考虑启用 NuGet Package Restore。有关详细信息,请参阅 NuGet Package Restore(NuGet 程序包还原)。

  3. 添加对 System.Configuration .NET 程序集的引用。

    若要使用“管理引用”对话框添加引用,请执行以下操作:

    1. 在“解决方案资源管理器”中,右键单击项目名称。然后,选择“添加”和“引用”。

      此时将出现“管理引用”对话框。

    2. 在 .NET Framework 程序集下,找到并选择 System.Configuration 程序集。

    3. “确定”

  4. appSettings 部分添加到 app.config 文件,然后设置 媒体服务 帐户名和帐户密钥的值。你在帐户设置期间已获得了媒体服务帐户名和帐户密钥。

    note备注
    在 Visual Studio 2013 和 Visual Studio 2012 中,默认情况下已添加 App.config 文件。在 Visual Studio 2010 中,你必须手动添加应用程序配置文件。

    Tip提示
    若要查找名称和密钥值,请转到 Azure 门户,选择你的 Media Service 帐户,然后单击该门户窗口底部的“管理密钥”图标。单击每个文本框旁边的图标将值复制到系统剪贴板中。

    <?xml version="1.0"?>
    <configuration>
      <appSettings>
          <add key="MediaServicesAccountName" value="YouMediaServicesAccountName" />
          <add key="MediaServicesAccountKey" value="YouMediaServicesAccountKey" />
      </appSettings>
    </configuration>
    
  5. 在本地计算机上创建一个文件夹并将 .wmv 和 .mp4 文件复制到此文件夹。在此示例中,假定该文件夹名为 Media 且位于 MediaServicesGettingStarted 项目目录下。附带本操作实例的项目包含具有 .wmv 和 .mp4 文件的 Media 目录。

  6. 使用以下代码覆盖 Program.cs 文件开头已有的 using 语句。

    using System;
    using System.Linq;
    using System.Configuration;
    using System.IO;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Collections.Generic;
    using Microsoft.WindowsAzure;
    using Microsoft.WindowsAzure.MediaServices.Client;
    

若要以编程方式连接到 Media Services,你必须在以前设置了一个 Azure 帐户,并在该帐户上配置了 Media Services。以下主题详细介绍了如何连接到 Media Services 帐户:使用 Media Services SDK 连接到 Media Services.

以下代码演示了如何从 App.config 文件中读取连接值以及如何创建 CloudMediaContext 对象以便连接到 Media Services。

  1. 将默认的 Program 类定义替换为以下代码。

    class Program
    {
        // Read values from the App.config file.
        private static readonly string _mediaServicesAccountName = 
            ConfigurationManager.AppSettings["MediaServicesAccountName"];
        private static readonly string _mediaServicesAccountKey =
            ConfigurationManager.AppSettings["MediaServicesAccountKey"];
    
        // Field for service context.
        private static CloudMediaContext _context = null;
        private static MediaServicesCredentials _cachedCredentials = null;
    
        static void Main(string[] args)
        {
            // Create and cache the Media Services credentials in a static class variable.
            _cachedCredentials = new MediaServicesCredentials(
                            _mediaServicesAccountName,
                            _mediaServicesAccountKey);
            // Used the chached credentials to create CloudMediaContext.
            _context = new CloudMediaContext(_cachedCredentials);
           . . .
        }
    }
    
    
    
note备注
示例

本部分中的代码执行以下操作:

  1. 创建一个空资产

    在创建资产时,可以指定三种用于加密资产的不同选项。

    • AssetCreationOptions.None。如果要创建未加密资产,则必须设置此选项。

    • AssetCreationOptions.CommonEncryptionProtected。如果有常用加密 (CENC) 保护的文件,请指定此选项。示例为一组已经由 PlayReady 加密的文件。

    • AssetCreationOptions.StorageEncrypted。加密明文输入文件,然后将其上载到 Azure 存储空间。

      note备注
      请注意,媒体服务提供磁盘上的存储加密,而不是通过数字权限管理器 (DRM) 等线路提供加密。

  2. 创建一个我们希望上传到存储并且与资产关联的 AssetFile 实例。

  3. 创建 AccessPolicy 实例以定义资产的访问权限和持续时间。

  4. 创建提供资产访问权限的 SAS Locator 实例。

  5. 将单个媒体文件上载到媒体服务。创建和上载过程也称为引入资产。

static public IAsset CreateAssetAndUploadSingleFile(AssetCreationOptions assetCreationOptions, string singleFilePath)
{
    var assetName = "UploadSingleFile_" + DateTime.UtcNow.ToString();
    var asset = CreateEmptyAsset(assetName, assetCreationOptions);

    var fileName = Path.GetFileName(singleFilePath);

    var assetFile = asset.AssetFiles.Create(fileName);

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

    var accessPolicy = _context.AccessPolicies.Create(assetName, TimeSpan.FromDays(30),
                                                        AccessPermissions.Write | AccessPermissions.List);

    var locator = _context.Locators.CreateLocator(LocatorType.Sas, asset, accessPolicy);

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

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

    locator.Delete();
    accessPolicy.Delete();

    return asset;
}

static private IAsset CreateEmptyAsset(string assetName, AssetCreationOptions assetCreationOptions)
{
    var asset = _context.Assets.Create(assetName, assetCreationOptions);

    Console.WriteLine("Asset name: " + asset.Name);
    Console.WriteLine("Time created: " + asset.Created.Date.ToString());

    return asset;
}

note备注
示例

在媒体服务中,你可以创建以各种方式处理媒体内容的作业:编码、加密、进行格式转换等。媒体服务作业始终会包含一个或多个任务,这些任务指定处理工作的详细信息。本部分定义了一种方法,用于创建一个编码任务,然后运行一个使用 Azure Media Encoder 执行该任务的作业。此任务使用预设字符串来指定要执行的编码类型。若要查看可用的预设编码值,请参阅 Media Services Encoder 系统预设。媒体服务支持与 Microsoft Expression Encoder 相同的媒体文件输入和输出格式。有关受支持格式的列表,请参阅Supported File Types for Media Services

  1. 将以下 CreateEncodingJob 方法定义添加到你的类中。此方法完成编码作业所必需的几个步骤:

    • 声明一个新作业。

    • 声明一个媒体处理器来处理该作业。媒体处理器是一个处理编码、加密、格式转换和其他相关处理作业的组件。有几种类型的媒体处理器可供使用(可以使用 _context.MediaProcessors 循环访问它们)。本操作实例后面部分介绍的 GetLatestMediaProcessorByName 方法将返回 Azure Media Encoder 处理器。

    • 声明一个新任务。每个作业都有一个或多个任务。请注意,在这个任务中,你向其传递了一个友好名称、一个媒体处理器实例、一个任务配置字符串以及一些任务创建选项。配置字符串可指定编码设置。例如,H264 Broadband 720p 设置将生成一个 MP4 文件。有关此预设及其他预设的详细信息,请参阅 Media Services Encoder 系统预设

    • 向该任务添加输入资产。在此示例中,输入资产是你在上一部分创建的资产。

    • 向该任务添加输出资产。对于输出资产,请指定一个友好名称、一个指示在作业完成后是否在服务器上保存输出的布尔值,以及一个指示不为存储和传输加密输出的 AssetCreationOptions.None 值。

    • 提交作业。

      提交作业是执行编码作业的最后必需步骤。



    本方法执行其他有用但可选的任务,如跟踪作业进度和记录作业详细信息。

    static public IAsset CreateEncodingJob(IAsset asset, string preset)
    {
        // Declare a new job.
        IJob job = _context.Jobs.Create(preset + " encoding job");
        // Get a media processor reference, and pass to it the name of the 
        // processor to use for the specific task.
        IMediaProcessor processor = GetLatestMediaProcessorByName("Azure Media Encoder");
    
        // Create a task with the encoding details, using a string preset.
        ITask task = job.Tasks.AddNew(preset + " encoding task",
            processor,
            preset, 
            Microsoft.WindowsAzure.MediaServices.Client.TaskOptions.ProtectedConfiguration);
    
        // Specify the input asset to be encoded.
        task.InputAssets.Add(asset);
        // Add an output asset to contain the results of the job. 
        // This output is specified as AssetCreationOptions.None, which 
        // means the output asset is not encrypted. 
        task.OutputAssets.AddNew("Output asset",
            AssetCreationOptions.None);
    
        // Use the following event handler to check job progress.  
        job.StateChanged += new
                EventHandler<JobStateChangedEventArgs>(StateChanged);
    
        // Launch the job.
        job.Submit();
    
        // Optionally log job details. This displays basic job details
        // to the console and saves them to a JobDetails-{JobId}.txt file 
        // in your output folder.
        LogJobDetails(job.Id);
    
        // Check job execution and wait for job to finish. 
        Task progressJobTask = job.GetExecutionProgressTask(CancellationToken.None);
        progressJobTask.Wait();
    
        // If job state is Error the event handling 
        // method for job progress should log errors.  Here we check 
        // for error state and exit if needed.
        if (job.State == JobState.Error)
        {
            throw new Exception("\nExiting method due to job error.");
        }
    
        return job.OutputMediaAssets[0];
    }
    
note备注
示例

若要对文件进行流式处理,你需要创建一个 OnDemandOrigin 定位符,定位符提供了访问资产中包含的文件的进入点。Media Services 支持两种类型的定位符:OnDemandOrigin 定位符,用于对媒体进行流式处理(例如,MPEG DASH、HLS 或平滑流式处理);访问签名 (SAS) URL 定位符,用于下载媒体文件。

若要生成完整 URL,你应创建 OnDemandOrigin定位符并附加所需的流格式。例如:

 

平滑流式处理

{media services account name}.origin.mediaservices.net/{locator ID}/{filename}.ism/Manifest

可以使用 http://smf.cloudapp.net/healthmonitor 播放器来测试平滑流式处理。

使用常见流格式媒体的 DASH 实时配置文件清单

{media services account name}.origin.mediaservices.net/{locator ID}/{filename}.ism/Manifest(format=mpd-time-csf) 

可以使用 http://dashif.org/reference/players/javascript/ 播放器来测试平滑流式处理。

Apple HTTP 实时流 (HLS)

{media services account name}.origin.mediaservices.net/{locator ID}/{filename}.ism/Manifest(format=m3u8-aapl)

以下示例演示了基于 OnDemandOrigin 定位符路径的平滑流式处理、HLS 和 DASH URL。

http://test001.origin.mediaservices.windows.net/fecebb23-46f6-490d-8b70-203e86b0df58/BigBuckBunny.ism/Manifest
http://test001.origin.mediaservices.windows.net/fecebb23-46f6-490d-8b70-203e86b0df58/BigBuckBunny.ism/Manifest(format=m3u8-aapl)
http://test001.origin.mediaservices.windows.net/fecebb23-46f6-490d-8b70-203e86b0df58/BigBuckBunny.ism/Manifest(format=mpd-time-csf)

有关详细信息,请参阅传送内容

以下方法获取指向点播源服务加清单文件的 URL。获得该 URL 后,可以如上所述构建完整流 URL。

static public string GetStreamingOriginLocatorURL(IAsset assetToStream)
{
    // Get a reference to the streaming manifest file from the  
    // collection of files in the asset. 
    var theManifest =
                        from f in assetToStream.AssetFiles
                        where f.Name.EndsWith(".ism")
                        select f;

    // Cast the reference to a true IAssetFile type. 
    IAssetFile manifestFile = theManifest.First();

    // Create a 30-day readonly 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, 
        assetToStream,
        policy,
        DateTime.UtcNow.AddMinutes(-5));

    // Display the base path to the streaming asset on the origin server.
    Console.WriteLine("Streaming asset base path on origin: ");
    Console.WriteLine(originLocator.Path);
    Console.WriteLine();

    // Create a full URL to the manifest file. 
    return originLocator.Path + manifestFile.Name;
}
note备注
示例

若要将文件下载到计算机,首先需要创建一个 SAS 定位符。定位符提供了访问资产中包含的文件的进入点。Media Services 支持两种类型的定位符:OnDemandOrigin 定位符,用于对媒体进行流式处理(例如,MPEG DASH、HLS 或平滑流式处理);访问签名 (SAS) URL 定位符,用于下载媒体文件。若要构建 URL,你需要将文件名嵌入到主机和 SAS 签名之间。

以下示例演示了基于 SAS 定位符的 URL:

https://test001.blob.core.windows.net/asset-ca7a4c3f-9eb5-4fd8-a898-459cb17761bd/BigBuckBunny.mp4?sv=2012-02-12&se=2014-05-03T01%3A23%3A50Z&sr=c&si=7c093e7c-7dab-45b4-beb4-2bfdff764bb5&sig=msEHP90c6JHXEOtTyIWqD7xio91GtVg0UIzjdpFscHk%3D

有关详细信息,请参阅传送内容

以下方法将文件下载到指定的输出位置。

static public IAsset DownloadAssetToLocal(IAsset asset, string outputFolder)
{
    IAccessPolicy accessPolicy = _context.AccessPolicies.Create("File Download Policy", TimeSpan.FromDays(30), AccessPermissions.Read);
    ILocator locator = _context.Locators.CreateLocator(LocatorType.Sas, asset, accessPolicy);
    BlobTransferClient blobTransfer = new BlobTransferClient
    {
        NumberOfConcurrentTransfers = 10,
        ParallelTransferThreadCount = 10
    };

    Console.WriteLine("Files will be downloaded to:");
    Console.WriteLine("{0}", outputFolder);
    Console.WriteLine();

    var downloadTasks = new List<Task>();
    foreach (IAssetFile outputFile in asset.AssetFiles)
    {
        // Use the following event handler to check download progress.
        outputFile.DownloadProgressChanged += DownloadProgress;

        string localDownloadPath = Path.Combine(outputFolder, outputFile.Name);

        downloadTasks.Add(outputFile.DownloadAsync(Path.GetFullPath(localDownloadPath), blobTransfer, locator, CancellationToken.None));

        outputFile.DownloadProgressChanged -= DownloadProgress;
    }

    Task.WaitAll(downloadTasks.ToArray());

    return asset;
}

static private void DownloadProgress(object sender, DownloadProgressChangedEventArgs e)
{
    Console.WriteLine(string.Format("{0} % download progress. ", e.Progress));
}

note备注
示例

本部分包含该主题中所述的完整代码列表。

note备注
  • 确保更新以下变量,以便指向输入(MP4 和 WMV)文件所在的文件夹以及希望输出到的目标位置。

    private static readonly string _supportFiles =
        Path.GetFullPath(@"../..\Media");
    
    // Paths to support files (within the above base path). You can use 
    // the provided sample media files from the "supportFiles" folder, or 
    // provide paths to your own media files below to run these samples.
    private static readonly string _singleWMVInputFilePath =
        Path.GetFullPath(_supportFiles + @"\interview1.wmv");
    
    private static readonly string _singleMP4InputFilePath =
        Path.GetFullPath(_supportFiles + @"\BigBuckBunny.mp4");
    
    private static readonly string _outputFilesFolder =
        Path.GetFullPath(_supportFiles + @"\OutputFiles");
    

using System;
using System.Linq;
using System.Configuration;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.MediaServices.Client;
 
namespace MediaServicesGettingStarted
    {
    class Program
    {
        private static readonly string _supportFiles =
            Path.GetFullPath(@"../..\Media");

        // Paths to support files (within the above base path). You can use 
        // the provided sample media files from the "supportFiles" folder, or 
        // provide paths to your own media files below to run these samples.
        private static readonly string _singleWMVInputFilePath =
            Path.GetFullPath(_supportFiles + @"\interview1.wmv");

        private static readonly string _singleMP4InputFilePath =
            Path.GetFullPath(_supportFiles + @"\BigBuckBunny.mp4");

        private static readonly string _outputFilesFolder =
            Path.GetFullPath(_supportFiles + @"\OutputFiles");
        // Read values from the App.config file.
        private static readonly string _mediaServicesAccountName = 
            ConfigurationManager.AppSettings["MediaServicesAccountName"];
        private static readonly string _mediaServicesAccountKey =
            ConfigurationManager.AppSettings["MediaServicesAccountKey"];

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

        static void Main(string[] args)
        {
            // Create and cache the Media Services credentials in a static class variable.
            _cachedCredentials = new MediaServicesCredentials(
                            _mediaServicesAccountName,
                            _mediaServicesAccountKey);
            // Used the chached credentials to create CloudMediaContext.
            _context = new CloudMediaContext(_cachedCredentials);

            IAsset singleWMVAsset = CreateAssetAndUploadSingleFile(AssetCreationOptions.None, 
                _singleWMVInputFilePath);

            // EncodeToH264 creates a job with one task
            // that converts a mezzanine file (in this case interview1.wmv)
            // into an MP4 file (in this case, "H264 Broadband 720p").
            IAsset MP4Asset = CreateEncodingJob(singleWMVAsset, "H264 Broadband 720p");

            // BuildSasUrlForMP4File creates a SAS Locator
            // and builds the SAS Url that can be used to 
            // progressively download the MP4 file.
            string fullSASURL = BuildSasUrlForMP4File(MP4Asset);

            Console.WriteLine("Progressive download URL: {0}", fullSASURL);

            // Download all the files in the asset locally
            // (that includes the mainifest.xml file).
            DownloadAssetToLocal(MP4Asset, _outputFilesFolder);

            Console.WriteLine();

            IAsset singleMP4Asset = CreateAssetAndUploadSingleFile(AssetCreationOptions.None,
                                                     _singleMP4InputFilePath);
            // EncodeToAdaptiveBitrate creates a job with one task
            // that encodes a mezzanine file (in this case BigBuckBunny.mp4)
            // into an adaptive bitrate MP4 set (in this case, "H264 Adaptive Bitrate MP4 Set 720p").
            IAsset adaptiveBitrateAsset = CreateEncodingJob(singleMP4Asset, "H264 Adaptive Bitrate MP4 Set 720p");

            // Get the Streaming Origin Locator URL.
            string streamingURL = GetStreamingOriginLocatorURL(adaptiveBitrateAsset);

            // Add Smooth Streaming, HLS, and DASH format to the streaming URL.  
            // NOTE: To be able to play these streams based on the 
            // adaptiveBitrateAsset asset, you MUST have at least one
            // On-demand Streaming reserved unit. 
            // For more information, see: 
            //    Dynamic Packaging (http://msdn.microsoft.com/en-us/library/azure/jj889436.aspx)
            Console.WriteLine("Smooth Streaming format:");
            Console.WriteLine("{0}", streamingURL + "/Manifest");
            Console.WriteLine("Apple HLS format:");
            Console.WriteLine("{0}", streamingURL + "/Manifest(format=m3u8-aapl)");
            Console.WriteLine("MPEG DASH format:");
            Console.WriteLine("{0}", streamingURL + "/Manifest(format=mpd-time-csf)"); 

        }

        static public IAsset CreateAssetAndUploadSingleFile(AssetCreationOptions assetCreationOptions, string singleFilePath)
        {
            var assetName = "UploadSingleFile_" + DateTime.UtcNow.ToString();
            var asset = CreateEmptyAsset(assetName, assetCreationOptions);

            var fileName = Path.GetFileName(singleFilePath);

            var assetFile = asset.AssetFiles.Create(fileName);

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

            var accessPolicy = _context.AccessPolicies.Create(assetName, TimeSpan.FromDays(30),
                                                                AccessPermissions.Write | AccessPermissions.List);

            var locator = _context.Locators.CreateLocator(LocatorType.Sas, asset, accessPolicy);

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

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

            locator.Delete();
            accessPolicy.Delete();

            return asset;
        }

        static private IAsset CreateEmptyAsset(string assetName, AssetCreationOptions assetCreationOptions)
        {
            var asset = _context.Assets.Create(assetName, assetCreationOptions);

            Console.WriteLine("Asset name: " + asset.Name);
            Console.WriteLine("Time created: " + asset.Created.Date.ToString());

            return asset;
        }

        static public IAsset CreateEncodingJob(IAsset asset, string preset)
        {
            // Declare a new job.
            IJob job = _context.Jobs.Create(preset + " encoding job");
            // Get a media processor reference, and pass to it the name of the 
            // processor to use for the specific task.
            IMediaProcessor processor = GetLatestMediaProcessorByName("Azure Media Encoder");

            // Create a task with the encoding details, using a string preset.
            ITask task = job.Tasks.AddNew(preset + " encoding task",
                processor,
                preset, 
                Microsoft.WindowsAzure.MediaServices.Client.TaskOptions.ProtectedConfiguration);

            // Specify the input asset to be encoded.
            task.InputAssets.Add(asset);
            // Add an output asset to contain the results of the job. 
            // This output is specified as AssetCreationOptions.None, which 
            // means the output asset is not encrypted. 
            task.OutputAssets.AddNew("Output asset",
                AssetCreationOptions.None);

            // Use the following event handler to check job progress.  
            job.StateChanged += new
                    EventHandler<JobStateChangedEventArgs>(StateChanged);

            // Launch the job.
            job.Submit();

            // Optionally log job details. This displays basic job details
            // to the console and saves them to a JobDetails-{JobId}.txt file 
            // in your output folder.
            LogJobDetails(job.Id);

            // Check job execution and wait for job to finish. 
            Task progressJobTask = job.GetExecutionProgressTask(CancellationToken.None);
            progressJobTask.Wait();

            // If job state is Error the event handling 
            // method for job progress should log errors.  Here we check 
            // for error state and exit if needed.
            if (job.State == JobState.Error)
            {
                throw new Exception("\nExiting method due to job error.");
            }

            return job.OutputMediaAssets[0];
        }
    
        static public string GetStreamingOriginLocatorURL(IAsset assetToStream)
        {
            // Get a reference to the streaming manifest file from the  
            // collection of files in the asset. 
            var theManifest =
                                from f in assetToStream.AssetFiles
                                where f.Name.EndsWith(".ism")
                                select f;

            // Cast the reference to a true IAssetFile type. 
            IAssetFile manifestFile = theManifest.First();

            // Create a 30-day readonly 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, 
                assetToStream,
                policy,
                DateTime.UtcNow.AddMinutes(-5));

            // Display the base path to the streaming asset on the origin server.
            Console.WriteLine("Streaming asset base path on origin: ");
            Console.WriteLine(originLocator.Path);
            Console.WriteLine();

            // Create a full URL to the manifest file. Use this for playback
            // in smooth streaming and HLS media clients. 
            return originLocator.Path + manifestFile.Name;
        }

        static public string BuildSasUrlForMP4File(IAsset asset)
        {
            // Declare an access policy for permissions on the asset. 
            // You can call an async or sync create method. 
            IAccessPolicy policy =
                _context.AccessPolicies.Create("My 30 days readonly policy",
                    TimeSpan.FromDays(30),
                    AccessPermissions.Read);

            // Create a SAS locator to enable direct access to the asset 
            // in blob storage. You can call a sync or async create method.  
            // You can set the optional startTime param as 5 minutes 
            // earlier than Now to compensate for differences in time  
            // between the client and server clocks. 

            ILocator locator = _context.Locators.CreateLocator(LocatorType.Sas,
                asset,
                policy,
                DateTime.UtcNow.AddMinutes(-5));

            var mp4File = asset.AssetFiles.ToList().
                           Where(f => f.Name.EndsWith(".mp4", StringComparison.OrdinalIgnoreCase)).
                           FirstOrDefault();


            // Take the locator path, add the file name, and build 
            // a full SAS URL to access this file. This is the only 
            // code required to build the full URL.
            var uriBuilder = new UriBuilder(locator.Path);
            uriBuilder.Path += "/" + mp4File.Name;

            Console.WriteLine("Full URL to file: ");
            Console.WriteLine(uriBuilder.Uri.AbsoluteUri);
            Console.WriteLine();

            //Return the SAS URL.
            return uriBuilder.Uri.AbsoluteUri;
        }

        static public IAsset DownloadAssetToLocal(IAsset asset, string outputFolder)
        {
            IAccessPolicy accessPolicy = _context.AccessPolicies.Create("File Download Policy", TimeSpan.FromDays(30), AccessPermissions.Read);
            ILocator locator = _context.Locators.CreateLocator(LocatorType.Sas, asset, accessPolicy);
            BlobTransferClient blobTransfer = new BlobTransferClient
            {
                NumberOfConcurrentTransfers = 10,
                ParallelTransferThreadCount = 10
            };

            Console.WriteLine("Files will be downloaded to:");
            Console.WriteLine("{0}", outputFolder);
            Console.WriteLine();

            var downloadTasks = new List<Task>();
            foreach (IAssetFile outputFile in asset.AssetFiles)
            {
                // Use the following event handler to check download progress.
                outputFile.DownloadProgressChanged += DownloadProgress;

                string localDownloadPath = Path.Combine(outputFolder, outputFile.Name);

                downloadTasks.Add(outputFile.DownloadAsync(Path.GetFullPath(localDownloadPath), blobTransfer, locator, CancellationToken.None));

                outputFile.DownloadProgressChanged -= DownloadProgress;
            }

            Task.WaitAll(downloadTasks.ToArray());

            return asset;
        }

        static private void DownloadProgress(object sender, DownloadProgressChangedEventArgs e)
        {
            Console.WriteLine(string.Format("{0} % download progress. ", e.Progress));
        }


        static private IMediaProcessor GetLatestMediaProcessorByName(string mediaProcessorName)
        {
            // The possible strings that can be passed into the 
            // method for the mediaProcessor parameter:
            //   Azure Media Encoder
            //   Azure Media Packager
            //   Azure Media Encryptor
            //   Storage Decryption

            var processor = _context.MediaProcessors.Where(p => p.Name == mediaProcessorName).
                ToList().OrderBy(p => new Version(p.Version)).LastOrDefault();

            if (processor == null)
                throw new ArgumentException(string.Format("Unknown media processor", mediaProcessorName));

            return processor;
        }

        static private void StateChanged(object sender, JobStateChangedEventArgs e)
        {
            Console.WriteLine("Job state changed event:");
            Console.WriteLine("  Previous state: " + e.PreviousState);
            Console.WriteLine("  Current state: " + e.CurrentState);

            switch (e.CurrentState)
            {
                case JobState.Finished:
                    Console.WriteLine();
                    Console.WriteLine("********************");
                    Console.WriteLine("Job is finished.");
                    Console.WriteLine("Please wait while local tasks or downloads complete...");
                    Console.WriteLine("********************");
                    Console.WriteLine();
                    Console.WriteLine();
                    break;
                case JobState.Canceling:
                case JobState.Queued:
                case JobState.Scheduled:
                case JobState.Processing:
                    Console.WriteLine("Please wait...\n");
                    break;
                case JobState.Canceled:
                case JobState.Error:
                    // Cast sender as a job.
                    IJob job = (IJob)sender;
                    // Display or log error details as needed.
                    LogJobStop(job.Id);
                    break;
                default:
                    break;
            }
        }

        static private void LogJobStop(string jobId)
        {
            StringBuilder builder = new StringBuilder();
            IJob job = GetJob(jobId);

            builder.AppendLine("\nThe job stopped due to cancellation or an error.");
            builder.AppendLine("***************************");
            builder.AppendLine("Job ID: " + job.Id);
            builder.AppendLine("Job Name: " + job.Name);
            builder.AppendLine("Job State: " + job.State.ToString());
            builder.AppendLine("Job started (server UTC time): " + job.StartTime.ToString());
            builder.AppendLine("Media Services account name: " + _mediaServicesAccountName);
            // Log job errors if they exist.  
            if (job.State == JobState.Error)
            {
                builder.Append("Error Details: \n");
                foreach (ITask task in job.Tasks)
                {
                    foreach (ErrorDetail detail in task.ErrorDetails)
                    {
                        builder.AppendLine("  Task Id: " + task.Id);
                        builder.AppendLine("    Error Code: " + detail.Code);
                        builder.AppendLine("    Error Message: " + detail.Message + "\n");
                    }
                }
            }
            builder.AppendLine("***************************\n");
            // Write the output to a local file and to the console. The template 
            // for an error output file is:  JobStop-{JobId}.txt
            string outputFile = _outputFilesFolder + @"\JobStop-" + JobIdAsFileName(job.Id) + ".txt";
            WriteToFile(outputFile, builder.ToString());
            Console.Write(builder.ToString());
        }

        static private void LogJobDetails(string jobId)
        {
            StringBuilder builder = new StringBuilder();
            IJob job = GetJob(jobId);

            builder.AppendLine("\nJob ID: " + job.Id);
            builder.AppendLine("Job Name: " + job.Name);
            builder.AppendLine("Job submitted (client UTC time): " + DateTime.UtcNow.ToString());
            builder.AppendLine("Media Services account name: " + _mediaServicesAccountName);

            // Write the output to a local file and to the console. The template 
            // for an error output file is:  JobDetails-{JobId}.txt
            string outputFile = _outputFilesFolder + @"\JobDetails-" + JobIdAsFileName(job.Id) + ".txt";
            WriteToFile(outputFile, builder.ToString());
            Console.Write(builder.ToString());
        }

        static void WriteToFile(string outFilePath, string fileContent)
        {
            StreamWriter sr = File.CreateText(outFilePath);
            sr.Write(fileContent);
            sr.Close();
        }

        static private string JobIdAsFileName(string jobID)
        {
            return jobID.Replace(":", "_");
        }
        static IJob GetJob(string jobId)
        {
            // Use a Linq select query to get an updated 
            // reference by Id. 
            var jobInstance =
                from j in _context.Jobs
                where j.Id == jobId
                select j;
            // Return the job reference as an Ijob. 
            IJob job = jobInstance.FirstOrDefault();

            return job;
        }
        static IAsset GetAsset(string assetId)
        {
            // Use a LINQ Select query to get an asset.
            var assetInstance =
                from a in _context.Assets
                where a.Id == assetId
                select a;
            // Reference the asset as an IAsset.
            IAsset asset = assetInstance.FirstOrDefault();

            return asset;
        }

        //////////////////////////////////////////////////
        // Delete tasks
        //////////////////////////////////////////////////

        static void DeleteAsset(IAsset asset)
        {
            // Delete Asset's locators before
            // deleting the asset.
            foreach (var l in asset.Locators)
            {
                Console.WriteLine("Deleting the Locator {0}", l.Id); 
                l.Delete();
            }

            Console.WriteLine("Deleting the Asset {0}", asset.Id);
            // delete the asset
            asset.Delete();
        }

        static void DeleteAllAccessPoliciesInThisAccount(string existingPolicyId)
        {
            // To delete a specific access policy, get a reference to the policy.  
            // based on the policy Id passed to the method.
            var policy = _context.AccessPolicies.
                Where(p => p.Id == existingPolicyId).FirstOrDefault();

            Console.WriteLine("Deleting policy {0}", existingPolicyId);
            policy.Delete();

        }
    }
}

运行程序(按 F5)。

本操作实例演示了构建简单媒体服务应用程序所需完成的一系列编程任务。你学习了基本的媒体服务编程任务,包括获取服务器上下文、创建资产、编码资产,以及下载或访问服务器上的资产。有关更高级的开发任务,请参阅以下部分:

显示:
© 2014 Microsoft