分享

展现自我:使用Microsoft Expression Encoder 3 SDK进行视频编码

 幻灵姬风 2012-07-23

在我最喜欢的一个电影场景中,Clark W. Griswold(《疯狂圣诞假期》中由 Chevy Chase 饰演)在藏圣诞礼物时将自己困在了阁楼上。为了保暖,他戴上了从落满灰尘的衣柜中找到的 粉红色手套、绿色帽子和棕色毛皮披肩。在衣柜底部,他发现了从少年时期开始录制的家庭电 影。他含着眼泪,用一台老旧的电影放映机看完了这些电影。

从那时起,家庭电影已经经历了一段漫长的历程,但是人们仍然被同一个问题所困扰:如何 向亲朋好友展示我的电影?我们可以通过 YouTube、Vimeo 和 Facebook 这样的网站轻松共享 视频,但是对于每分钟上百兆字节的高清视频来说,将数据上传到这些网站是一项非常费时的 任务。您的便携式设备、游戏系统或家庭影院媒体中心甚至有可能播放不了这些文件。为了解 决这些问题,您需要将视频转换为其他格式。这个过程称为“编码”。

关于 Expression Encoder

Microsoft 视频编码工具 Expression Encoder 3 是 Expression 系列产品的一部分,该系 列产品可用来为 Web 和桌面应用程序创建引人注目的用户界面。Expression Encoder 同时提 供免费版和付费版。付费版包含在 Expression Studio 3 Suite(599 美元)和 Expression Web 3 Suite(149 美元)中。免费下载版不支持编码成 Silverlight Smooth Streaming 或 H.264 视频,也不支持 H.264 视频源,但是支持编码成 Windows Media Video 文件,并带有 一个不错的 SDK。本文中的许多代码示例要求使用付费版的程序,但是所有的代码示例都可以 在免费版的 SDK 中编译生成,只是会在运行时收到 InvalidMediaException 或 FeatureNotAvailableException 提示。

如果您不打算购买 Expression Suite,可以通过以下链接下载免费版的 Expression Encoder:microsoft.com/expression。Expression Professional MSDN 订阅或 Visual Studio Professional with MSDN Premium 订阅中也包含 Expression Encoder。请注意,您只 需花费 149 美元就可以购买到带有此功能包且支持各种输入和输出格式的专业视频编码软件应 用程序,这真是一个相当优惠的价格。而购买类似的视频编码解决方案则要付出多达 3,000 美 元。

无论您选择哪种版本,都要安装 Encoder 3 QFE。它增加了对更多文件类型和输入设备的支 持,改善了某些情况下的程序性能,并修复了一些小的错误。QFE 安装程序可在 Microsoft Expression 网站的 Expression Encoder 页面获得。

支持的格式

支持以下输入视频格式:

Windows Media Video (.wmv)

DVD 视频 (.vob)

MPEG(.mpg、.mpeg)

Audio Video Interleave (.avi)

Microsoft Digital Video Recording (.dvr-ms)

付费版软件增加了对以下格式的支持(另外还支持一些其他格式):

MPEG-4(.mp4、.m4v)

Quicktime (.mov)

AVC HD (.mts)

移动设备视频(.3gp、.3g2)

在大多数情况下,Expression Encoder 支持 Windows Media Player 能够播放的任何媒体 文件。如果您要支持更多文件格式(并且能够在 Windows Media Player 中播放),您需要安 装一个编解码器,例如 K-Lite Codec Pack (codecguide.com) 或 Community Combined Codec Pack (cccp-project.net)。这两种编解码器都基于开源 ffdshow 项目,并且会添加对 VP6 编 码的 Flash (.flv) 文件、Matroska 容器中的 H.264 视频 (.mkv) 以及 Ogg 视频 (.ogg) 文 件的支持。

免费版的 Expression Encoder 仅支持 Microsoft VC-1 作为输出编解码器。然而,您仍然 能够为 Silverlight(仅单比特率)、Xbox 360、Zune 和 Zune HD 编码视频。而且,VC-1 编 解码器也不错,其压缩能力与 H.264 不相上下(某些情况下可能更好)。升级到付费版软件, 您就可以输出 Silverlight Smooth Streaming 视频(多比特率)和 H.264 视频,这意味着您 编码的视频能够在 iPhone、PS3、Flash 播放器(版本 10 支持 H.264/.mp4)和其他无数设备 上播放。

编码基础知识

如果要支持特定的输出设备,则需要更改视频配置文件的一些设置,所以您需要了解视频编 码的一些基本知识。对视频进行重新编码实际上是对视频进行解压缩,然后使用其他编解码器 或是手动更改视频属性(例如大小、长宽比或帧速率),对其重新压缩。尽管存在无损压缩方 法,但并不常用,因为用这些方法压缩出来的视频文件仍旧太大。因此,为了减少存储(以及 传输)视频所需的空间,就需要一种算法(我们称之为编解码器)来压缩和解压缩视频。压缩 后的视频流随即按照某种规范(我们称之为容器,如 WMV 或 MP4)存储起来。容器和编解码器 通常不是绑定使用的,因此尽管 H.264 是 MP4 容器中最常见的编解码器,但也可以使用其他 编解码器。 

比特率,以每秒千比特来表示,用于定义应该使用多少数据来存储压缩的视频。降低比特率 即是让编码器用较高的比率来压缩视频,因此会降低视频的质量。有不同的方法可用于指示编 码器如何确定视频的比特率。最简单的方法就是使用恒定比特率 (CBR),强迫编码器对每一秒 视频使用相同数量的数据。可变比特率 (VBR) 用来告诉编码器,文件的整体比特率应该是多少 ,但是允许编码器根据视频的特定区段所需的数据量,来提高或降低比特率。限制可变比特率 类似于不受限的 VBR,唯一的差别是您不仅要指定一个平均比特率,还要指定一个最高比特率 作为上限。

在对 Silverlight Smooth Streaming 视频进行编码时,限制可变比特率非常有用。它有助 于确保比特率不会超出客户端带宽,避免迫使客户端请求质量较差的视频流。CBR 和 VBR 通过 指定整体视频文件的大小来指明要使用的压缩量。

或者,您也可以让编码器使用基于质量的 VBR。您不用指定视频的整体大小,而是指定一个 质量百分比,也就是在解压后要保留的源视频中数据量。例如,相对于自然风光或动作视频, 卡通视频只需保留较少的数据量就可以保持高质量的视频。因此,如果您拥有高质量的源视频 ,并且希望将其转换成其他格式并保留最佳质量,可以考虑使用基于质量的 VBR。这些定义只 是冰山一角,但它们是选择输出设置的核心概念。在本文中,您还能够看到其他的编码定义应 用在不同的代码示例中。

我会 使用 Adrenaline Rush 视频作为这些示例的源。

安装完 Expression Encoder 3 后,创建一个新的 Visual Studio C# 控制台应用程序项目 。添加对 Microsoft.Expression.Encoder.dll 和 Microsoft.Expression.Encoder.Utilities.dll 的引用,这两个文件位于 \Program Files (x86)\Microsoft Expression\Encoder 3\SDK。您还需要添加对 WindowsBase 的引用(您可以 在“添加引用”对话框的“.NET”选项卡中找到 WindowsBase)。用到的许多类位于 Microsoft.Expression.Encoder 命名空间中,所以要为其添加一条 using 语句。

要实例化的第一项是 MediaItem 对象。MediaItem 构造函数使用一个字符串作为构造函数 的唯一参数。该参数用于传递将在编码项目中用作源的文件的路径:

MediaItem src = new MediaItem (@"C:\WMdownloads\AdrenalineRush.wmv");

创建 MediaItem 对象仅需一两秒钟的时间,但 SDK 会在后台进行大量的工作:收集关于源 视频的信息,例如高、宽、帧速率(在屏幕上显示各幅图像的频率)和持续时间。同时还会收 集有关音频流的信息。

接下来创建 Job 类的实例(仅包含一个无参数的构造函数),然后将您的 MediaItem 添加 到该实例的 MediaItems 列表中。Job 类充当了所需输出格式(称为配置文件)的管理器:

Job job = new Job();
job.MediaItems.Add(src);

现在您需要指示 Job 类在编码过程中要使用哪些音频和视频配置文件,最简单的方法是使 用在用户界面中定义的某个配置文件。例如,若要为 Zune HD 创建视频,可以使用 VC1ZuneHD 预设配置:

job.ApplyPreset(Presets.VC1ZuneHD);

最后,指定输出目录并开始编码过程:

job.OutputDirectory = @"C:\EncodedFiles";
job.Encode();

您的 Program.cs 文件应当与图 1 类似。

图 1 为 Zune HD 创建视频

using Microsoft.Expression.Encoder;

namespace TestApp
{
  class Program
  {
    static void Main(string[] args)
    {
      MediaItem src = new MediaItem 
        (@"C:\WMdownloads\AdrenalineRush.wmv");
      Job job = new Job();
      job.MediaItems.Add(src);
      job.ApplyPreset(Presets.VC1ZuneHD);
      job.OutputDirectory = @"C:\EncodedFiles";
      job.Encode();
    } 
  } 
}

在运行应用程序之前,还有最后一件事要做:如果您使用的是 64 位 Windows,您需要修改 项目,将其编译目标设为 x86 平台。在 Visual Studio 菜单栏中,选择“项目”和“(项目名 称) 属性”。在打开的对话框中,选择“生成”选项卡并将“目标平台”的值由“任何 CPU” 改为“x86”。

现在您就可以运行应用程序,并创建可在 Zune HD 上播放的视频了。编码过程需要几分钟 的时间,而且极占 CPU 资源。作为并行计算任务运行,对于视频编码过程非常有益,所以多核 计算机在这里非常有优势。

Expression Encoder 还包含一些用于针对在线服务(例如 YouTube、Vimeo 和 Facebook) 进行编码的预设配置。用我的 Panasonic Lumix DMC-ZS3 数码摄像机拍摄的 720p 视频每分钟 大约要消耗 110MB 空间。而使用 YouTube HD 预设配置(同样为 720p)转换视频,则可以把 视频减小至仅仅 16MB。这极大地提高了上传和本地存储的效率。将视频转换为 .mp4 文件,还 能让它与更多的视频编辑程序兼容。


自定义设置

若要手动实现和 VC1ZuneHD 预设配置相同的效果,您需要使用与图 2 中类似的代码来设置 视频和音频配置文件。对于图 2 中要编译的代码,您需要添加对 Microsoft.Expression.Encoder.Utilities 和 System.Drawing 的引用。还要为 Microsoft.Expression.Encoder.Profiles 和 System.Drawing 添加 using 语句。 OutputFormat 本质上用来指定输出文件的容器。我提到“本质上”是因为 Silverlight 的编 码原理只有少许不同(稍后我要谈到这一点)。

图 2 Zune HD 的视频和音频配置文件设置

MediaItem src = new MediaItem (@"C:\WMdownloads\AdrenalineRush.wmv");

src.OutputFormat = new WindowsMediaOutputFormat();

src.OutputFormat.VideoProfile = new AdvancedVC1VideoProfile();
src.OutputFormat.VideoProfile.Bitrate = new
   VariableConstrainedBitrate(1000, 1500);
src.OutputFormat.VideoProfile.Size = new Size(480, 272);
src.OutputFormat.VideoProfile.FrameRate = 30;
src.OutputFormat.VideoProfile.KeyFrameDistance = new TimeSpan(0, 0,  4);
src.OutputFormat.AudioProfile = new WmaAudioProfile();
src.OutputFormat.AudioProfile.Bitrate = new
   VariableConstrainedBitrate(128, 192);
src.OutputFormat.AudioProfile.Codec = AudioCodec.WmaProfessional;
src.OutputFormat.AudioProfile.BitsPerSample = 24;

  
Job job = new Job();
job.MediaItems.Add(src);
job.OutputDirectory = @"C:\EncodedFiles";
job.Encode();

VideoProfile 指定要使用的视频编解码器,以及编码时要使用的详细设置。同样, AudioProfile 指定要使用的音频编解码器及其设置。构造 VariableConstrainedBitrate 时, 第一个参数用于指定平均比特率,第二个参数用于指定最高比特率。大小设置用于指定容纳编 码后的视频的框。对于 Adrenaline Rush 视频,正确的大小设置实际上应为 480x272 以维持 长宽比。但如果我输入 480x480,得出的视频依然是 480x272。 

图 2 中的 KeyFrameDistance 属性指的是一种视频编码概念,这个概念我还没有谈到。大 多数视频编码方式是只保存一帧到下一帧之间的变化,而不是保存每个视频帧的整个画面。关 键帧是包含整个画面的帧。本代码每四秒创建一个关键帧。每当视频中有重大变化(例如场景 变化)时,就会自动创建关键帧,但是您还应当按照预定义的间隔创建关键帧,以方便在电影 播放时进行视频检索。

Silverlight Smooth Streaming

Silverlight Smooth Streaming 可以根据当前的网络状况动态切换正在播放的媒体文件的 比特率。Smooth Streaming 项目由存储在 .ismv 文件、.ism 和 .ismc 元数据文件中的各个 视频组成,后两者支持 Smooth Streaming 播放。

若要创建 Silverlight Smooth Streaming 项目,必须进行多处更改。首先,将 KeyFrameDistance 改为两秒。如果 KeyFrameDistance 保留为四秒,视频仍可以播放,但是当 播放器切换比特率时,您会注意到播放时会出现停顿。Silverlight 播放器将请求视频按照两 秒钟一个块来播放,因此如果在每个请求开始的时候有一个关键帧,播放会更加流畅。您还需 要添加以下行:

src.OutputFormat.VideoProfile.SmoothStreaming = true;


将 SmoothStreaming 设为 true,可让编码器将视频输出为 .ismv 文件,并创建 .ism 和 ismc 文件。只具备一个比特率不是一个真正流畅的流项目,所以为了创建多个输出比特率,您 需要向 VideoProfile 添加多个流。使用类似图 3 中的代码来实现这个目的。

图 3 添加 Silverlight Smooth Streaming

MediaItem src = new MediaItem (@"C:\WMdownloads\AdrenalineRush.wmv");
src.OutputFormat = new WindowsMediaOutputFormat();

src.OutputFormat.VideoProfile = new AdvancedVC1VideoProfile();
src.OutputFormat.VideoProfile.KeyFrameDistance = new TimeSpan(0, 0, 2);
src.OutputFormat.VideoProfile.SmoothStreaming = true;
src.OutputFormat.VideoProfile.Streams.Clear();
src.OutputFormat.VideoProfile.Streams.Add(new StreamInfo(new
   VariableConstrainedBitrate(2000, 3000), new Size(1280, 720)));
src.OutputFormat.VideoProfile.Streams.Add(new StreamInfo(new
   VariableConstrainedBitrate(1400, 1834), new Size(848, 476)));
src.OutputFormat.VideoProfile.Streams.Add(new StreamInfo(new
   VariableConstrainedBitrate(660, 733), new Size(640, 360)));

src.OutputFormat.AudioProfile = new WmaAudioProfile();
src.OutputFormat.AudioProfile.Bitrate = new
   VariableConstrainedBitrate(128, 192);
src.OutputFormat.AudioProfile.Codec = AudioCodec.WmaProfessional;
src.OutputFormat.AudioProfile.BitsPerSample = 24;

Job job = new Job();
job.MediaItems.Add(src);
job.OutputDirectory = @"C:\EncodedFiles";
job.Encode();

这些代码指定了三种不同的比特率和大小来进行编码。为了获得最佳效果,视频大小需要随 比特率的降低而缩小。指定自己的比特率时,您可以使用 Expression Encoder 3 UI 中的 IIS Smooth Streaming 设置。请注意,以高出源文件的分辨率来对视频进行编码,是不可能获得更 高质量的。唯一有可能的是,如果使用较弱的压缩方法,则可以以高出源文件的比特率来对视 频进行编码。如果 SDK 能够确定源文件的比特率,将会显示在 MediaItem 的 SourceVideo Profile 属性中:

int bitrate = ((ConstantBitrate) src.SourceVideoProfile.Bitrate).Bitrate;

如果 SDK 无法获得源文件的比特率,您可以根据文件大小估算出一个相当接近的值。这是 具体的估算公式:

以 kb/s 为单位的大概比特率 =(以千字节为单位的文件大小 * 8 / 以秒为单位的视频持 续时间)- 以 kb/s 为单位的音频比特率

您可以使用 System.IO.FileInfo 类来获得源文件大小,用 SDK 来获得持续时间 (MediaItem.FileDuration 属性)以及可能的音频比特率。如果您不知道音频比特率,可以使 用 128 或 160 来估算(大多数的音频比特率都介于 64 和 192 之间),您还可以通过 Windows Media Player 的“属性”窗口(按 Alt 键显示菜单,然后选择“文件”|“属性”) 获得音频比特率。

监视进度

因为一项编码任务要花费数小时才能完成,能够看到编码进度是非常有帮助的。SDK 提供了 一种简单的方法,即通过事件来监视编码进度,您可以为该事件添加处理程序:

job.EncodeProgress += new EventHandler<EncodeProgressEventArgs> (OnProgress);

添加一个类似如下的方法来处理事件:

static void OnProgress(object sender, EncodeProgressEventArgs e)
{
  Console.Clear();
  Console.WriteLine((100 * (e.CurrentPass - 1) + e.Progress) /  e.TotalPasses + "%");
}

多通路编码是一个与本代码示例相关的新概念。使用可变比特率进行编码时,过程分为两步 ,称为通路。在第一个通路中,分析源视频以确定哪部分最复杂,并能够通过提高比特率获益 。在第二个通路中,使用在第一个通路中获得的信息对视频进行编码。因此,如果您使用了恒 定比特率,就没有必要使用 EncodeProgressEventArgs 类的 CurrentPass 或 TotalPasses 属 性。

合并视频

如果您只想对视频的一部分进行编码,或者要合并多个视频,SDK 也提供了支持。若要修改 源媒体项的开始和结束时间,您可以修改 Clips 属性。如果只想对视频的前六秒进行编码,可 以使用类似以下的代码:

src.Sources[0].Clips[0].StartTime = new TimeSpan(0);
src.Sources[0].Clips[0].EndTime = new TimeSpan(0, 0, 6);

若要添加其他视频作为源文件,您可以将其他视频附加到 MediaItem 的 Sources 属性中。 这会将源文件按顺序编码到单一输出文件中:

MediaItem src = new MediaItem (@"C:\WMdownloads\AdrenalineRush.wmv");
src.Sources.Add(new Source(@"C:\WMdownloads\Video2.wmv"));

实时编码

Expression Encoder 还支持对来自实时源(如网络摄像头)的内容进行编码。这个概念( 和代码)与对视频文件进行编码类似,但是您需要使用一组不同的类。这些类可以在 Microsoft.Expression.Encoder.Live 命名空间中找到。

首先要使用的类是 LiveJob。LiveJob 类似 Encoder.Job,也是用来处理视频编码工作的。 但在实时方案中,OutputFormat 是 LiveJob 的属性,而不是 MediaItem 对象(已经不需要该 对象)。当 LiveJob 对象被实例化时,它会寻找与计算机连接的视频输入设备,并填充 VideoDevices 和 AudioDevices 属性。您随后便可以将其用作编码器的输入源。图 4 显示了 一个示例。

Figure 4 对实时视频进行编码

using (LiveJob job = new LiveJob())
{
  LiveDevice videoDevice = job.VideoDevices[0];
  LiveDevice audioDevice = job.AudioDevices[0];
  LiveDeviceSource liveSource = job.AddDeviceSource(videoDevice,
    audioDevice);
  job.ActivateSource(liveSource);
  WindowsMediaBroadcastOutputFormat outputFormat = new
    WindowsMediaBroadcastOutputFormat();
  outputFormat.BroadcastPort = 8080;
  job.OutputFormat = outputFormat;
  Console.WriteLine("Press enter to stop encoding...");
  job.StartEncoding();
  Console.ReadLine();
  Console.WriteLine("Stopping");
  job.StopEncoding();
}

这将使用网络摄像头(假设您已经连接)启动一个实时编码会话,并在您本地计算机的端口 8080 上进行广播。若要查看实时编码,请打开 Windows Media Player 并选择“文件”|“打 开 URL”,然后输入 mms://localhost:8080。经过短时间的缓冲后,您应当可以看到来自网络 摄像头的视频,但是会存在一段 20 至 30 秒的延迟。存在这段延迟是因为编码和传输视频流 需要一段时间。您应该可以使用此视频作为 Windows Media Services 或 IIS Media Services 的源,对外进行广播。


其他工具

如果不确定您选择的编码设置是否可以带来所需的输出质量,可以使用 Expression Encoder 3 UI 提供的名为 A/B Compare 的方便功能。该功能使您可以对位于当前播放位置附 近五秒钟的视频进行编码。编码后的视频将会与原始视频分屏并列显示出来(请参见图 5), 这样您就可以轻松比较编码后的视频和原始视频的质量。

图 5 Expression Encoder 3 的 A/B Compare 功能

您随后可以将当前设置保存为用户定义的预设配置,方法是单击“编辑”|“将当前设置保 存为预设配置”。该预设配置将保存为一个 XML 文件,可供在 SDK 中使用:

job.ApplyPreset(@"C:\WMdownloads\NewPreset.xml");

如果您已经想象过,通过控制台应用程序自动执行视频转换过程是多么简单的一件事,请看 看 Expression Encoder 的 Convert-Media PowerShell 模块:convertmedia.codeplex.com。 这个 PowerShell 模块包含了 Expression Encoder SDK,提供了一个命令行编码界面,无需编 写任何代码。就像所有 CodePlex 项目一样,它是一个开源模块。

现在,希望您已经了解与视频编码相关的核心术语,并且在考虑使用哪些编解码器和比特率 时能够做出明智的决定。您还知道如何使用 Expression Encoder 3 SDK 针对特定目标(例如 Xbox 360、iPhone 和 Silverlight,以及实时流式视频)进行视频码。所以,不要等到像 Clark W. Griswold 一样将自己困在阁楼上,才意识到家庭视频和被遗忘的记忆有多么重要。 将它们转换成所有人都可以观看的格式。





    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多