Windows Azure
使用 Windows Azure 媒体服务分摊视频内容工作
Bruno Terkaly
Ricardo Villalobos
预计未来几年,一个不容置疑的发展趋势是视频内容流将以惊人的速度增长。 根据 Cisco Visual Networking Index (VNI) 2011 的数据,与此活动有关的 Internet 通信到 2015 年将翻两番。 出现这种现象有很多因素,其中包括: 存储成本缩减、可扩展的云计算和存储资源、高带宽网络以及大量支持视频的设备,如平板电脑和智能手机设备。 创建、编码和分发视频从来没有像今天这样切实可行且经济实惠,甚至对普通的业余爱好者也是如此。
在传送视频内容和使用著作权法保护视频内容方面也取得了重大的成果。 我们很多人都目睹了音乐产业所发生的巨大变革,产业重心从大唱片公司开始转向基于 Internet 的媒体公司。 现在,各大运营商和有线电视提供商都在关注视频点播和使用 Internet 渠道(包括 YouTube、Ustream 和 justin.tv 等)分发视频所取得的高速增长。
Microsoft 显然不会对所发生的这一切无动于衷。 2012 年 5 月,该软件公司在 Windows Azure 中发布了新的媒体服务功能,这有助于向广大用户分摊创建、管理和传送视频的工作。 Windows Azure 媒体服务(以下简称“媒体服务”)支持多种不同类型的设备,包括智能手机、平板电脑和高端视频工作站。 通过使用这组功能(以前的代码名称为“Nimbus”),个人开发者和公司可以构建基于云的媒体解决方案以获取、处理、管理和传送媒体内容。
解决问题
这些新的媒体服务功能为媒体管理空间提供了自动化、标准化且经济实惠的解决方案,它提供了三个主要好处以大大消除障碍和降低复杂性:
- 可通过利用云计算提供的好处自动进行扩展,包括根据用户需求增加点播容量。
- 基于 RESTful API 的丰富编程接口以及使开发人员轻松创建、管理和维护自定义工作流的 Microsoft .NET Framework 客户端库。
- 包括多个公司提供的组件的合作伙伴生态系统,这些组件可插入到上述工作流的任何步骤中。
这些全面的媒体服务为创建、管理和分发内容的公司提供了各种常见问题的解决方案。 第一个问题是成本,因为建立支持视频功能的数据中心的成本是非常高的。 必须配备服务器、编码器、网络设备和相关软件,这意味着进入门槛较高。 媒体服务解决的第二个问题是全行业普遍存在的自定义工作流问题。 媒体领域的很多公司都制订了自己的专有商业合同,因而很难协调使用多种格式和协议的不同供应商提供的相关服务。 如果多个参与者参与创建和管理内容,标准化视频的处理方式可以提高协调能力和工作效率。
开放标准
媒体服务基于开放标准,这意味着几乎任何客户端都可以利用它们,包括 Java、PHP、Objective-C 和 jQuery 等。 可以通过一个通用的 RESTful API 使用整套的功能,从而利用开放数据协议 (OData) 来帮助实现灵活的查询功能。 还有一个 .NET C# SDK(内置在 RESTful API 上),它可以方便和简化使用此语言的开发人员访问框架的过程(请参阅图 1)。
图 1 两种以编程方式使用 Windows Azure 媒体服务的方法
REST/OData API | 开发人员可以通过具象状态传输 (REST) API 层访问媒体服务组件。 由于 REST 基于 HTTP,几乎可以从任何地方通过各种不同的语言、应用程序和平台使用它。 简而言之,REST API 是用于通过 Web 访问媒体服务层的通用公共编程接口。 REST 是一种根据开放标准构建联网客户端-服务器应用程序的体系结构策略。 REST 提供了一个无状态的可缓存标准协议 (HTTP) 以在联网计算机之间发送信息。 |
.NET API | 当然啦,还有一个 .NET 客户端 SDK(它包装 REST API 调用并简化构建基于 .NET 的媒体服务客户端应用程序的过程)。 本文重点介绍了 .NET API。 将来的文章将会介绍基于 REST 的方法。 |
利用媒体服务 API
为了更好地理解 Windows Azure 媒体服务功能的优点,本文重点介绍了一个特定的使用案例。 想象一下,您需要与多个家庭成员或朋友分享家庭视频,而他们可能使用各种不同的移动设备。 图 2 描绘了将自定义处理的视频内容传送到世界各地所需的整体工作流。
图 2 分发视频内容所需的整体工作流
前提条件
- 有关 Windows Azure 媒体服务操作方法指南页面,请访问以下链接: go.microsoft.com/fwlink/?LinkID=247284。
- 有关 Windows Azure 媒体服务帐户设置步骤,请访问以下链接: go.microsoft.com/fwlink/?LinkID=247287。
- 有关 Windows Azure 媒体服务 MSDN 库内容,请访问以下链接: go.microsoft.com/fwlink/?linkid=245437。
上载和编码内容
让我们从分发视频内容的基本任务入手。 图 3 中的代码完成任何处理视频的人员的两个重要目标。 第一个目标是上载原始内容,以便可以对其进行处理。 第二个目标是以某种方式对内容进行实际编码,以使其可供多个设备使用。 视频具有多种不同的格式,如,MPEG、MPEG-2 (QuickTime)、RealMedia、H.264 (MP4) 和 Windows Media 等,甚至 YouTube 具有自己的编码格式。 编码格式具有不同的大小。 其中的很多编码格式从设计上具有较小的视频大小,从而可以快速进行 Web 下载和渲染。 其他格式(如 H.264)强调质量,而不关心视频大小。
图 3 上载和执行编码作业
static void Main(string[] args)
{
// Part 1 - Connect to Media Services
// Setup upload progress event
// Upload a video to encode
CloudMediaContext mediaContext =
new CloudMediaContext("[ ACCOUNT NAME ]","[ ACCOUNT KEY ]");
mediaContext.Assets.OnUploadProgress += Assets_OnUploadProgress;
var asset = mediaContext.Assets.Create(
@"C:\windows\Performance\WinSat\winsat.wmv");
// Part 2 - Create a task, specify encoding details
Console.Clear();
IJob job = mediaContext.Jobs.CreateJob("Sample Job");
var expressionEncoder = mediaContext.MediaProcessors.Where(
mp => mp.Name == "Expression Encoder").Single();
var task = job.Tasks.Add(
mediaProcessor: expressionEncoder,
configuration: "H.264 HD 720p VBR");
task.Inputs.Add(asset);
task.Outputs.Add("Sample Task Output Asset");
// Part 3 - Submit the encoding job to begin processing
while (job.State != JobState.Finished)
{
job = mediaContext.Jobs.Refresh(job.Id);
Console.SetCursorPosition(0, 0);
Console.WriteLine("Job Name: " + job.Name);
Console.WriteLine("Job ID: " + job.Id);
Console.WriteLine();
Console.WriteLine("Job State: {0,-20}", job.State);
Console.WriteLine("Task Progress: {0:0.00}% ",
job.Tasks.Single().Progress);
Thread.Sleep(500);
}
Console.WriteLine();
Console.WriteLine("Job Complete!");
Console.ReadLine();
}
// Part 4 - Display completion progress (See Part 1, where the callback was set up)
static void Assets_OnUploadProgress(object sender,
UploadProgressEventArgs e)
{
Console.WriteLine(e.Progress);
}
图 4 按照标有第 1 至第 4 部分的小节解释了图 3 中的代码。
图 4 说明了图 3 中的源代码(请参阅第 1-4 部分)
第 1 部分 | 此代码完成三个基本目标: 1. 创建一个 CloudMediaContext 对象,以便提供凭据以针对媒体服务进行身份验证。 将在代码的其余部分中使用此上下文以管理和处理媒体资产。 2. 设置名为 Assets_OnUploadProgress 的回调代码,用于向用户报告上载过程的完成百分比。 3. 上载原始视频文件 (winsat.wmv),以便可以对其进行处理。 注意: 此处使用的术语是“资产”,在这种情况下,它指的是原始视频。 |
第二部分 | 此代码的目标是创建一个任务,它由媒体处理器、配置以及输入和输出组成。 请注意,编码是使用“H.264 HD 720p VBR”配置设置完成的。我们将使用 Microsoft Expression Encoder。 可以使用额外的媒体处理器,因为额外的媒体行业合作伙伴将增加媒体服务的价值。 |
第三部分 | 这是开始实际处理的位置。 您可以将作业视为包含一组任务的工作流。 任务可以链在一起,并且可以并行运行它们。 |
第 4 部分 | 此代码仅仅是在视频上载过程中自动执行的回调。 它通常用于报告上载过程的完成百分比。 |
管理内容
管理基于视频的项目的难题之一是,跟踪所有资产、作业和任务。 生成内容往往涉及将几十个甚至数百个原始文件创建为编码的输出。 能够跟踪和找到特定项目以进行额外处理可能会让人望而生畏。 使用标准接口自动完成此过程是一个创新性突破。 媒体服务中的管理接口为利益相关者加强合作提供了有利条件,从而可以更有效地协调长时间运行的工作流。 CloudMediaContext 对象提供了一个直观的接口以查找与工作流关联的任何元素,并将其组织为可使用通用库(如 LINQ)查询的一系列集合。
图 5 中的代码说明了循环访问资产并显示有关视频文件以及其他文件类型(如图像)的信息的功能。 请注意,上下文对象具有一个 Asset 集合,而 Asset 对象具有一个 File 对象集合。
图 5 帐户内的各种关联资产
static void Main(string[] args)
{
// Part 1 - Connect to Media Services
// Loop through assets, displaying file information
CloudMediaContext mediaContext =
new CloudMediaContext("[ ACCOUNT NAME ]",
"[ ACCOUNT KEY ]");
Console.WriteLine("ASSET INFORMATION");
foreach (IAsset asset in mediaContext.Assets)
{
// Display the collection of assets.
Console.WriteLine("Asset ID: " + asset.Id);
Console.WriteLine("Name: " + asset.Name);
// Display the files associated with each asset.
foreach (IFileInfo fileItem in asset.Files)
{
Console.WriteLine("File Name: " + fileItem.Name);
Console.WriteLine("File Create Date: " + fileItem.Created);
Console.WriteLine("File Size: " + fileItem.ContentFileSize);
}
}
}
图 6 中的代码说明了执行 LINQ 查询以搜索特定资产的功能。 请记住,您可能会管理成千上万个文件,此类搜索功能可能会提供巨大的帮助。
图 6 在使用名称或 ID 搜索资产时,LINQ 大大简化了搜索过程
// Returns an asset, given an asset name
static IAsset GetAssetNameFromContext(
CloudMediaContext mediaContext, string assetName)
{
IAsset asset = mediaContext.Assets.Where(a => a.Name ==
assetName).FirstOrDefault();
if (asset != null)
return asset;
else
return null;
}
// Returns an asset, given an asset Id
static IAsset GetAssetIdFromContext(
CloudMediaContext mediaContext, string assetId)
{
IAsset asset = mediaContext.Assets.Where(a => a.Id ==
assetId).FirstOrDefault();
if (asset != null)
return asset;
else
return null;
}
访问策略
控制哪些用户可以查看和访问特定资产是媒体服务框架的一项内置功能。 要控制安全权限,内容所有者可以通过编程方式指定访问策略,将在其中指定读/写权限以及可以访问多长时间等详细信息。 这些是与其他视频利益相关者共享工作流的上下文中的强大功能。
本节说明了如何使用访问策略执行基本任务,例如,创建访问策略并将其分配给资产以及列出已创建的访问策略。 图 7 中的代码的目的是设置“读取”策略,以仅允许访问视频 30 分钟。 代码首先上载 winsat.wmv。 将从中创建一个名为 CanReadFor30Minutes 的新访问策略,这意味着,只能在上载过程的 30 分钟内读取该文件。 下一步是将访问策略链接到上载的视频文件。
图 7 暂时公开一些视频以进行下载
static void Main(string[] args)
{
// Part 1 - Specify an asset to upload
// Connect to Media Services
string inputFilePath =
@"C:\windows\Performance\WinSat\winsat.wmv";
CloudMediaContext mediaContext =
new CloudMediaContext("[ ACCOUNT NAME ]", "[ ACCOUNT KEY ]");
// Part 2 - Upload an asset
// Create a policy for the asset
// Link access policy to asset
IAsset asset = mediaContext.Assets.Create(inputFilePath);
// Because this is a single-file asset, get the name of first file.
string fileName = asset.Files[0].Name;
IAccessPolicy readPolicy = mediaContext.AccessPolicies.Create(
"CanReadFor30Minutes",
TimeSpan.FromMinutes(30),
AccessPermissions.Read);
// Part 3 - Define a locator based on the read policy
// and expiration date
// Print the path for the locator you created
// Get the locator path Uri
// Build the full path to the file associated
// with the locator.
ILocator locator = mediaContext.Locators.CreateSasLocator(
asset, readPolicy);
Console.WriteLine("Locator path: " + locator.Path);
var uriBuilder = new UriBuilder(locator.Path);
uriBuilder.Path += Path.AltDirectorySeparatorChar + fileName;
Uri fullUrl = uriBuilder.Uri;
// Part 4 - Print the full path to the file
Console.WriteLine("Full URL to file: " + fullUrl);
}
定位器是以 URI 形式表示其位置的策略文件的持久性副本。 定位器允许依照策略指定的条款访问资产。 在这种情况下,要在 30 分钟的时间限制内访问资产(上载的视频),我们需要使用完整 URL 以及定位器文件。 请参阅图 7 中的 fullUrl。
下载处理的资产
最后,图 8 中的代码的目的是将视频内容下载到本地存储中。 在这种情况下,winsat.mp4 文件是 H.264 编码的输出,它是通过存储为 winsat.wmv 的原始视频生成的。 您可以按以下方式调用该函数:
DownloadAsset("nb:cid:UUID:a0297fe4-7080-4393-b874-7ddf0f759c40", @"c:\temp");
图 8 从 Windows Azure 媒体服务中下载资产
static void DownloadAsset(string assetId,
string outputMediaFilesFolder)
{
// Part 1 - Connect to Media Services
// Get an existing asset based on assetId passed in.
CloudMediaContext mediaContext =
new CloudMediaContext("[ ACCOUNT NAME ]","[ ACCOUNT KEY ]");
IAsset asset = mediaContext.Assets.Where(a => a.Id ==
assetId).SingleOrDefault();
// Part 2 - If the asset exists, download the first file in the asset
// Download to outputMediaFilesFolder
if (asset != null)
{
Console.WriteLine("Asset name: " + asset.Name);
IFileInfo theFile = asset.Files.FirstOrDefault();
// You could iterate through the asset.Files collection with a
// foreach statement, and download all files for assets that
// have multiple files.
// Example: foreach(IFileInfo file in asset.Files)
// Download the file to the specified local folder.
if (theFile != null)
theFile.DownloadToFile(Path.GetFullPath(outputMediaFilesFolder +
Path.DirectorySeparatorChar + theFile.Name));
else
Console.WriteLine("No files available for this asset.");
}
else
{
Console.WriteLine("Asset not available.");
}
}
winsat.mp4 的 assetId 是 nb:cid:UUID:a0297fe4-7080-4393-b874-7ddf0f759c40。 这是一个简单的案例,按其 assetId 请求可下载的资源并指定下载目标文件夹。
云计算的好处
总而言之,Windows Azure 媒体服务功能简化了编码视频内容并将其分发到多个需要不同格式和分辨率的设备或 Web 渠道的过程。 这是利用云计算提供的好处实现的,包括根据可变的需求扩展计算和存储的功能。 此功能加上基于 REST 的丰富 API 和 .NET 客户端库可以简化创建、管理和维护工作流的过程,可以使用在广大的合作伙伴生态系统中创建的组件改进这些工作流。
媒体服务代表了在生成、管理和传送视频内容方面取得的重大突破,从而使您可以自动完成和组合使用各种不同的数字资产,并将它们放在一个集中位置或甚至是分散的位置中。 随着未来几年视频在 Web 上获得显著的增长,媒体服务的出现可谓是恰逢其时。
以后,我们将详细介绍 REST API,以及第三方为自定义编码器和高端功能提供的一些支持。
Bruno Terkaly是 Microsoft 的开发推广人员。 他的知识深度来源于多年来相关领域以及使用大量平台、语言、框架、SDK、库和 API 编写代码的经验。 他不辞辛苦,就有关构建基于云的应用程序(特别是使用 Windows Azure 平台)编写代码、发布博客并给予现场演示。
Ricardo Villalobos 是一名资深的软件设计师,具有 15 年为供应链管理行业设计和创建应用程序的经验。 他持有多个不同的技术证书,并获得了达拉斯大学供应链管理专业的 MBA 学位。他是 Microsoft 的 Windows Azure 架构推广人员。
衷心感谢以下技术专家对本文的审阅: John Deutscher、Samuel Ng 和 Tim Teebken