John
Deutscher
 Azure媒体服务首席项目经理

随着媒体设备的增多,一项日益增长的需求是,视频流服务能够向用户提供超高音频质量和具有 5.1
环绕音响的优质内容。通过 Azure媒体服务使用
Dolby® Digital Plus多声道环绕音响给您的高清内容进行编码,现可交付到多个平台上,包括智能电视、Xbox、Windows
8 设备、移动设备等。

Dolby®Digital Plus或
Enhanced AC-3(E-AC-3)是一种专为高质量音频而设计的高级环绕音响音频编解码器。此编解码器基于核心
Dolby Digital 技术,是用于影院、广播和家庭影院环绕音响的一种成熟标准,超过 21亿款产品均支持该技术。在本博文中,我将介绍如何通过媒体服务使用此编解码器使您的内容提供优质的音频体验。

概述

在此示例中,编码到
Dolby® Digital Plus 涉及下列步骤:

1.    将源内容上传到您的
Azure媒体服务帐户并创建一个资源

2.    构建自定义编码预设,并将其保存到文件中

3.    提交使用自定义预设对上述资源进行编码的任务

4.    发布输出资源,并创建一个
SAS URL

5.    在应用程序中演示播放

开始之前,让我描述下每个步骤并提供我使用的示例代码。

运行示例代码后,您会获得一个标准
MP4 文件的 URL,文件包含
H.264 视频和 Dolby Digital Plus音频。接下来,您可以使用此
URL在支持 Dolby Digital Plus解码的设备上播放此视频流。Windows
8和 Xbox都有内置的
Dolby Digital Plus解码器,但 Apple设备目前不内置支持此编解码器。我的建议是遵循关于如何使用
Windows 8和 Player Framework测试环绕音响解码的指南。如果您想要在充分环绕音响下播放文件,则需要将
PC连接到能够进行 5.1播放的
AV接收器

上传源内容

开始之前,您需要首先将一些包含高清视频和多声道音频的源内容上传到您的媒体服务帐户。建议使用下列文件格式

  • MPEG-2传输流,使用
    AC-3(也称为 Dolby® Digital)编码的
    5.1音频流

  • ISO MPEG-4 (MP4)文件,包含使用
    AAC编码的 5.1音频

  • WMV文件,包含使用
    WMA Professional编码的 5.1音频

参考CreateAssetAndUploadSingleFile()中的上传源文件的示例代码。

构建自定义预设

如果这是您第一次创建自定义预设,我鼓励您阅读我之前的文章高级编码功能,了解关于如何创建自定义预设的详细信息。

接下来,我将介绍一种自定义预设,可将您的源转码为
MP4 文件,此 MP4文件包含以
4.5 Mbps传输率编码的 720p视频以及传输率为
512 kbps的 5.1声道
Dolby Digital Plus音频。此自定义预设基于“H264宽带
720p
”预设改编。此预设的<AudioProfile>部分经修改使用Dolby
Digital Plus设置

注意:有关如何调整音频编码设置(如此示例中,使用低于 512kbps的比特率)的详细信息,请参阅http://msdn.microsoft.com/zh-cn/library/dn296500.aspx

完成的 XML自定义预设如下,且应保存到本地文件中以用于编码。我使用的名称为“Dolby
Audio Preset.xml”

<?xml version="1.0"encoding="utf-16"?>

<Presets>

<Preset

Version="5.0">

<MediaFile

DeinterlaceMode="AutoPixelAdaptive"

ResizeQuality="Super"

VideoResizeMode="Stretch">

<OutputFormat>

<MP4OutputFormat

StreamCompatibility="Standard">

<VideoProfile>

<MainH264VideoProfile

BFrameCount="3"

EntropyMode="Cabac"

RDOptimizationMode="Speed"

HadamardTransform="False"

SubBlockMotionSearchMode="Speed"

MultiReferenceMotionSearchMode="Balanced"

ReferenceBFrames="False"

AdaptiveBFrames="True"

SceneChangeDetector="True"

FastIntraDecisions="False"

FastInterDecisions="False"

SubPixelMode="Quarter"

SliceCount="0"

KeyFrameDistance="00:00:02"

InLoopFilter="True"

MEPartitionLevel="EightByEight"

ReferenceFrames="4"

SearchRange="64"

AutoFit="True"

Force16Pixels="False"

FrameRate="0"

SeparateFilesPerStream="True"

SmoothStreaming="False"

NumberOfEncoderThreads="0">

<Streams

AutoSize="False"

FreezeSort="False">

<StreamInfo

Size="1280, 720">

<Bitrate>

<ConstantBitrate

Bitrate="4500"

IsTwoPass="False"

BufferWindow="00:00:05" />

</Bitrate>

</StreamInfo>

</Streams>

</MainH264VideoProfile>

</VideoProfile>

<AudioProfile>

<DolbyDigitalPlusAudioProfile

Codec="DolbyDigitalPlus"

EncoderMode="DolbyDigitalPlus"

AudioCodingMode="Mode32"

LFEOn="True"

SamplesPerSecond="48000"

BandwidthLimitingLowpassFilter="True"

DialogNormalization="-31">

<Bitrate>

<ConstantBitrate

Bitrate="512"

IsTwoPass="False"

BufferWindow="00:00:00" />

</Bitrate>

</DolbyDigitalPlusAudioProfile>

</AudioProfile>

</MP4OutputFormat>

</OutputFormat>

</MediaFile>

</Preset>

</Presets>

转码您的源内容

您可以使用
Windows Azure MediaEncoder 转码您的源内容,将自定义预设内容作为配置字符串传输到任务。查看下文示例代码中的
Transcode() 方法,了解涉及的步骤。任务产生的输出资产包含一个 MP4文件,文件中包含与
H.264编码的视频交错的 Dolby Digital Plus音频。

发布输出资源

内容转码之后,您就能为输出资源创建
SAS 定位。查看下文示例代码中的 CreateSASLocator(),了解涉及的步骤。SAS
URI 可传递到您的播放器应用程序中。

示例代码

请注意,本主题中的代码使用Azure媒体服务
.NET SDK扩展
。媒体服务
.NET SDK 扩展是一组扩展方法和帮助功能,可简化您的代码,以简化利用媒体服务进行的开发。

示例代码的
App.Config 文件如下所示

<?xmlversion="1.0" encoding="utf-8"?>

<configuration>

<startup>

<supportedRuntimeversion="v4.0" sku=".NETFramework,Version=v4.5" />

</startup>

<appSettings>

<addkey="MediaServicesAccountName"value="<MediaAccountName>" />

<add key="MediaServicesAccountKey"value="<MediaAccountKey>" />

</appSettings>

<runtime>

<assemblyBindingxmlns="urn:schemas-microsoft-com:asm.v1">

<dependentAssembly>

<assemblyIdentityname="Microsoft.WindowsAzure.Storage"publicKeyToken="31bf3856ad364e35" culture="neutral" />

<bindingRedirectoldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />

</dependentAssembly>

</assemblyBinding>

</runtime>

在上述
App.Config 中,将<MediaAccountName><MediaAccountKey>替换为您的媒体服务帐户名称和密钥

此外,我采用了
Dolby 提供的动画短片“Silent”的以下示例
5.1 环绕音响文件。

您可以在此处下载源
MP4 文件
以供您的测试使用。

(©Dolby – Silent由
Dolby提供)

采用的示例代码如下所示。

usingSystem;

usingSystem.Linq;

using System.Configuration;

usingSystem.IO;

usingSystem.Text;

usingSystem.Threading;

usingSystem.Threading.Tasks;

usingSystem.Collections.Generic;

usingSystem.Diagnostics;

usingSystem.Globalization;

usingMicrosoft.WindowsAzure;

using Microsoft.WindowsAzure.MediaServices.Client;

namespaceDeliveringPremiumAudio

{

/// <summary>

///

/// </summary>

class Program

{

//
从 App.config文件中读取值。

private static readonly string_mediaServicesAccountName =

ConfigurationManager.AppSettings["MediaServicesAccountName"];

private static readonly string_mediaServicesAccountKey =

ConfigurationManager.AppSettings["MediaServicesAccountKey"];

private static readonly string_storageConnectionString =

ConfigurationManager.AppSettings["StorageConnectionString"];

private static CloudMediaContext_context = null;

private static MediaServicesCredentials_cachedCredentials = null;

//指向示例文件的指针,以及保存的自定义预设
XML

private static readonly string _sampleFile =@"C:\temp\sintel.wmv";

private static readonly string_customPreset = @"C:\temp\Dolby Audio Preset.xml";

static void Main(string[] args)

{

try

{

//在静态类变量中创建和缓存媒体服务凭据

_cachedCredentials =new MediaServicesCredentials(_mediaServicesAccountName,_mediaServicesAccountKey);

//
使用缓存的凭据创建 CloudMediaContext

_context = newCloudMediaContext(_cachedCredentials);

//
步骤 1.上传示例内容并创建资源

IAsset inputAsset =CreateAssetAndUploadSingleFile(AssetCreationOptions.None, _sampleFile);

//
步骤 2.将自定义预设加载到配置字符串中

string configuration =File.ReadAllText(_customPreset);

//
步骤 3.将输入转码

IAsset outputAsset =Transcode(inputAsset, configuration);

//
步骤 4.为输出资源创建
SAS 定位并打印到控制台

if (null != outputAsset)CreateSASLocator(outputAsset);

//
上述方法创建的定位符有效期为 30天

//
测试完成后,您应考虑删除定位

}

catch (Exception ex)

{

Console.WriteLine(ex.Message);

}

}

///<summary>

///
此功能将创建一个空资源

/// </summary>

static private IAssetCreateEmptyAsset(string assetName, AssetCreationOptions assetCreationOptions)

{

var asset =_context.Assets.Create(assetName, assetCreationOptions);

Console.WriteLine("Assetname:" + asset.Name);

Console.WriteLine("Timecreated:" + asset.Created.Date.ToString());

return asset;

}

/// <summary>

///
此功能创建了一个资源,并将输入文件上传至其中

/// </summary>

static public IAssetCreateAssetAndUploadSingleFile(AssetCreationOptions assetCreationOptions,string singleFilePath)

{

var fileName =Path.GetFileName(singleFilePath);

//
创建唯一的资源名称

var assetName = fileName +DateTime.UtcNow.ToString();

var asset =CreateEmptyAsset(assetName, assetCreationOptions);

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

Console.WriteLine("CreatedassetFile {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);

assetFile.Upload(singleFilePath);

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

Console.WriteLine("");

long size =assetFile.ContentFileSize;

locator.Delete();

accessPolicy.Delete();

return asset;

}

///<summary>

///
此功能使用提供的预设将源资源转码,并返回输出资源

/// </summary>

static public IAsset Transcode(IAssetsourceAsset, string preset)

{

//
申报新作业。

IJob job = _context.Jobs.Create("TranscodingJob for " + sourceAsset.Name);

//
获取 Windows Azure MediaEncoder参考,向其传递

//
此特定任务使用的处理器名称。

IMediaProcessor processor =GetLatestMediaProcessorByName("Windows Azure Media Encoder");

//使用字符串预设创建一个包含编码详细信息的任务。

ITask task = job.Tasks.AddNew("Transcoding Task for "+ sourceAsset.Name,

processor,

preset,

Microsoft.WindowsAzure.MediaServices.Client.TaskOptions.None);

//
指定要编码的源资源。

task.InputAssets.Add(sourceAsset);

//
添加输出资源,以包含作业结果。

//
输出指定为AssetCreationOptions.None,这表示

//
输出资源未加密。

task.OutputAssets.AddNew("Output asset", AssetCreationOptions.None);

//使用下面的事件处理程序查看作业进度。

job.StateChanged += new

EventHandler<JobStateChangedEventArgs>(StateChanged);

//启动作业。

job.Submit();

//检查作业执行情况,等待作业完成。

Task progressJobTask =job.GetExecutionProgressTask(CancellationToken.None);

progressJobTask.Wait();

//获取更新的作业参考。

job = GetJob(job.Id);

//如果作业状态为错误,作业进度的事件处理

//方法应该会记录错误。这里我们查找

//错误状态并在需要时退出。

if (job.State == JobState.Error)

{

Console.WriteLine("Transcode() failed, exiting...");

return null;

}

//
从作业中获取输出资产的参考。

IAsset outAsset = job.OutputMediaAssets[0];

return outAsset;

}

/// <summary>

///
此功能返回指定媒体处理器最新版本的参考

/// </summary>

private static IMediaProcessorGetLatestMediaProcessorByName(string mediaProcessorName)

{

var processor =_context.MediaProcessors.Where(p => p.Name == mediaProcessorName).

ToList().OrderBy(p => newVersion(p.Version)).LastOrDefault();

if (processor == null)

throw new ArgumentException(string.Format("Unknownmedia processor", mediaProcessorName));

return processor;

}

/// <summary>

///
处理事件的帮助程序方法

/// </summary>

private static void StateChanged(objectsender, JobStateChangedEventArgs e)

{

Console.WriteLine("Job statechanged 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("Jobis finished.");

Console.WriteLine("Please wait while local tasks or downloadscomplete...");

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:

//将发送者转换为作业。

IJob job = (IJob)sender;

//必要时显示或记录错误详细信息。

LogJobStop(job.Id);

break;

default:

break;

}

}

/// <summary>

///
记录失败作业信息的帮助程序方法

/// </summary>

private static void LogJobStop(stringjobId)

{

StringBuilder builder = newStringBuilder();

IJob job = GetJob(jobId);

builder.AppendLine("\nThe jobstopped due to cancellation or an error.");

builder.AppendLine("***************************");

builder.AppendLine("JobID:" + job.Id);

builder.AppendLine("JobName:" + job.Name);

builder.AppendLine("JobState:" + job.State.ToString());

builder.AppendLine("Jobstarted (server UTC time):" + job.StartTime.ToString());

//记录任何存在的作业错误。

if (job.State == JobState.Error)

{

builder.Append("ErrorDetails:\n");

foreach (ITask task injob.Tasks)

{

foreach (ErrorDetail detailin task.ErrorDetails)

{

builder.AppendLine(" TaskId:" + task.Id);

builder.AppendLine("   ErrorCode:" + detail.Code);

builder.AppendLine("   ErrorMessage:" + detail.Message + "\n");

}

}

}

builder.AppendLine("***************************\n");

Console.Write(builder.ToString());

}

/// <summary>

///
此功能为给定资源创建
SAS 定位

/// </summary>

private static voidCreateSASLocator(IAsset asset)

{

Console.WriteLine("Publishingasset " + asset.Name);

//
创建原始定位,发布输出资源。

//确定只读访问策略并

//指定资源可访问的时限为
30天。

_context.Locators.Create(

LocatorType.Sas,

asset,

AccessPermissions.Read,

TimeSpan.FromDays(30));

//
为此 MP4文件生成
SAS定位符。

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

Uri mp4Uri =mp4AssetFile.GetSasUri();

Console.WriteLine("Output isnow available for progressive download: ");

Console.WriteLine(mp4Uri.OriginalString);

return;

}

}

}

播放演示

演示播放的一个简单方法是在
Windows 8.1 上启动 Windows Media Player应用程序,转至
File\Open URL(文件\打开
URL),输入编码后的资源的 SAS路径。

如果您的 PC已连接到能够进行
5.1播放的 AV接收器,您将能够听到完整
5.1环绕音响输出。

您可以在此处下载我的编码成果示例。

注意事项

使用立体声进行编码

如果您的输入资源是立体声,则
Azure Media Encoder 会在环绕声道中插入静音 –输出资源仍然包含
5.1音频。请注意,仅当以 Smooth Streaming格式交付输出内容时才建议插入静音。

或者,您也可以修改 <DolbyDigitalPlusAudioProfile>元素,参考编码成
Dolby Digital Plus 立体声

XML 记录的设置,从而使编码为立体声输出。

通过 Smooth Streaming进行
Dolby Digital Plus音频的流式传输

可以将
Dolby Digital Plus 音频传送到 Windows 8.1上的现代化应用程序或者通过
Smooth Streaming传送到 Xbox One。为实现这一点,您需要对示例代码进行如下修改

之后,您将需要使用针对 Windows 8的
Smooth Streaming客户端 SDK构建一个
Windows 8现代化应用程序。有关使用 Smooth Streaming客户端
SDK构建应用程序以播放 Dolby内容的详细信息,请阅读文章“如何构建
Smooth Streaming Windows Store 应用程序

目前并非所有平台(如 Apple iOS)都支持
Dolby 解码器,但市场上有很多其他的客户端框架支持机顶盒和智能电视等设备上的 Dolby
解码。如果您想要使用其他设备,则需要向设备制造商确认支持的解码器。

启用 Dolby Professional Loudness Metering

过去,很多使用多声道音频的广播公司都碰到过原声带平均音量高于或低于其他节目音量的问题。您可能也遇见过此问题,比如在节目间歇听到了声音很大的商业广告。另外,当环绕音响内容以立体或单声道音频输出形式在电视机上播放时,也会出现问题。如
Dolby 的此报告中所述,使用多声道音频的一个常见问题是在不同节目之间保持音量稳定一致的问题。要解决这个问题,建议的做法是在
Dolby Digital Plus 流中指定对话音量参数(也称为对话规范化或 DialNorm)。该值将音频音量设置为预设水平,可帮助解码器在不同节目之间进行音量水平的匹配,并摆脱烦人的音量变化。

上文提供的预设假设源内容的默认对话规范化值为 -31 dB。请参阅“使用
Dolby Professional Loudness Metering (DPLM) 支持
”部分,了解如何测量源内容对话的实际音量以及如何为对话规范化设置正确的值。

要了解有关 Dolby Digital Plus技术的更多内容,请在此Dolby页面查看我们合作伙伴提供的详细信息。

如果你有任何疑问,欢迎访问MSDN社区,由专家来为您解答Windows
Azure各种技术问题,或者拨打世纪互联客户服务热线400-089-0365/010-84563652咨询各类服务信息。

本文翻译自:http://azure.microsoft.com/blog/2014/09/03/delivering-premium-audio-experiences-with-dolby-digital-plus/

利用 Dolby® Digital Plus 提供优质音频体验的更多相关文章

  1. Camel Games借助AWS在爆发式增长中提供优质游戏体验

    关于Camel Games Camel Games 成立于2009年,是中国首家得到google市场官方认证的顶尖开发公司.长期以来,Camel Games始终依靠于率先的技术背景,致力于成为国际一流 ...

  2. 提升 RTC 音频体验 - 从搞懂硬件开始

    前言 RTC(实时音视频通信)技术的快速发展,助力了直播.短视频等互动娱乐形式的普及:在全球疫情持续蔓延的态势下,云会议需求呈现爆发式增长,进一步推动了 RTC 行业的快速发展.为了给客户提供稳定可靠 ...

  3. 利用纯java捕获和播放音频

    参考: 1.http://www.cjsdn.net/doc/jdk60/javax/sound/sampled/package-summary.html 2.http://www.cjsdn.net ...

  4. 优质办公体验,掌上OA一机hold住全场

    20多年前,人们希望可以脱离文件满天飞的办公办公环境,OA办公自动化出现了:随后.人们希望能在不同部门.不同分支机构间互通有无,打破信息孤岛.应用孤岛.数据孤岛,协同OA出现了:今天,人们梦想随时随地 ...

  5. bilibili携手WeTest,保障视频类应用优质适配体验

    WeTest 导读 中国移动视频用户规模越来越大,各类移动视频APP也百家争鸣, B站作为国内知名的年轻人文化社区,bilibili在推出移动端时,除了坚持自身的独特定位以外,对其APP的质量也十分重 ...

  6. SpringCloud03 Ribbon知识点、 Feign知识点、利用RestTemplate+Ribbon调用远程服务提供的资源、利用feign调用远程服务提供的资源、熔断

    1 远程服务资源的调用 1.1 古老的套路 在微服务出现之前,所有的远程服务资源必须通过RestTemplate或者HttpClient进行:但是这两者仅仅实现了远程服务资源的调用,并未提供负载均衡实 ...

  7. 苹果XR手机的音频体验测试总结

    苹果XR手机的音频   苹果XR算是苹果手机历史上一个里程碑的型号了,是苹果憋了两年的大招,连苹果9的称号就不要了.直接是X.说明苹果对它给予的希望很大.作为一个音频算法工程师,一直想体验一下XR的音 ...

  8. 利用Effmpeg 提取视频中的音频(mp3)

    在B站看到一个up发的病名为爱的钢琴曲,感觉很好听,然后当然是要加入歌单啊.然而不知道怎么转换成mp3,找来找去找到了EFFmpeg 这篇只是达到了我简单的需求,以后可能会有EFFmpeg更详细的使用 ...

  9. 利用WINDOWS活动目录提供LDAP的方案

    Windows Server 2008 R2 活动目录服务安装 http://blog.sina.com.cn/s/blog_622de9390100kgv3.html WINDOWS 2008 域控 ...

随机推荐

  1. 在Linux系统下安装大于mysql5.5版本的数据库

    linux下mysql 5.5的安装方法: 1.安装所需要系统库相关库文件      gcc等开发包,在安装linux系统的时候安装. 2.创建mysql安装目录 # mkdir -p /usr/lo ...

  2. Linux 系统结构详解

    Linux 系统结构详解 Linux系统一般有4个主要部分: 内核.shell.文件系统和应用程序.内核.shell和文件系统一起形成了基本的操作系统结构,它们使得用户可以运行程序.管理文件并使用系统 ...

  3. Linux C 程序 字符串运算符-表达式(TWO)

    1.字符串常量 双引号"" :eg:"china"   ,字符串在存储的时候会以一个\0为结束标志.2.符号常量  ,给常量取一个名字. #include< ...

  4. apply()与call()的区别

    一直都没太明白apply()与call()的具体使用原理,今日闲来无事,决定好好研究一番. JavaScript中的每一个Function对象都有一个apply()方法和一个call()方法,它们的语 ...

  5. 简单的JQuery分页代码

    1. [代码][JavaScript]代码      001 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" ...

  6. Java知识总结--数据库

    1 薪水排序后薪水排名在第3-5的员工 1)select * from(select ename,sal,rownum rn from (select ename,sal from emp_44 wh ...

  7. ViewState压缩

    /// <summary> ///CompressViewState 的摘要说明 /// </summary> public class CompressViewState:S ...

  8. JS判断是否微信浏览器

    JS判断是否微信浏览器 function isWeixinBrowser(){ var ua = navigator.userAgent.toLowerCase(); return (/microme ...

  9. 自定义弹出div对话框

    <style type="text/css"> html,body{height:100%;overflow:hidden;} body,div,h2{margin:0 ...

  10. VB6-系统打印常识

    在一次做图片打印的时候,对位置的调整老是不得法,后来通过CBM666老师的帮助才解决问题,分享以下他给的帮助.     , , picA.Width , picA.Height Printer.End ...