HTML5的音频与视频

Published on 2016 - 09 - 14

最早的时候,因特网主要用于分享学术研究的成果。情况很快就发生了改变,Web似乎一夜之间就成了万众瞩目的焦点,成了商业发展背后的动力之源。一转眼,就到了现在。今天的因特网已经成为媒体的天堂,铺天盖地的滑稽视频、世界各地的小提琴演奏录像,数目之多,令人咂舌。

这种转变之大,难以言表。2005年年初,“那一定是件美事”的梦想,如今已经幻化成YouTube这个世界第三大的视频分享网站。三四分钟长的视频已经占据互联网(以及我们的部分生活空间)。网络巨擘Cisco报告,这种趋势并未减慢,预计到2013年网络流量的90%都将用于视频。

令人难以置信的是,这种巨大的转变居然是在HTML和浏览器不内置支持视频,甚至连音频都不支持的现实下发生的。没错,功劳应该记在Flash身上,这个插件大多数时候对大多数人都是有效的。但是也有一个显而易见的盲点,苹果公司的iPad从发布之初就不支持Flash。

为了填补这个空白,HTML5添加了<audio><video>这两个HTML多年来一直缺少的元素。最终,使富媒体得到了标准、一致且不依赖插件的支持。然而,事情并非都那么一帆风顺。主流浏览器公司身陷音频与视频格式的争斗,而这种争斗一点也不比蓝光与HD-DVD的较量更光彩。结局当然不好:没有任何一种音频和视频格式得到所有浏览器支持。为了让媒体文件在HTML5中能正常播放,你必须针对不同格式分别进行编码。本文将介绍这些内容。不过,在此之前有必要回顾一下历史,用全局的眼光来审视一下HTML5问世之前视频世界的境况。

理解今天的视频

在没有HTML5的情况下,可以通过两种方式向网页中添加视频。最简单的方式,就是使用<embed>元素把视频硬塞进页面中。然后,浏览器就可以使用Windows Media Player、Apple QuickTime或其他视频播放器创建一个视频窗口,并把它放在页面中。

这种方式的问题是一切只能听天由命。你没有办法控制播放进度,也不能提前缓冲视频以避免长时间的播放停滞,甚至你都不知道自己的视频文件能否在不同浏览器或操作系统中播放。

第二种方式是使用浏览器插件,比如微软最近推出的Silverlight或最普遍的Adobe Flash。Flash完全解决了浏览器支持问题,Flash视频能够在安装了Flash插件的任何地方播放;用数字来说,就是目前能上网的计算机中有99%都安装了Flash播放器。Flash为我们提供了几乎无限制的控制功能,而且我们还可以方便地使用别人做好的Flash播放器,甚至每个发光按钮你都可以自己重新设计。

不过,Flash也不完美。为了把Flash视频放到网页中,必须使用<object><embed>元素编写一大堆乱七八糟的标记,必须适当地编码视频文件,可能还必须要花高价购买Flash开发软件并学习使用——轻易学不会。但是,最严重的问题还在于苹果发布的新移动设备iPhone和iPad。它们根本就不支持Flash,因而通过它们查看内置Flash视频的页面,只能看到一个空白的方框。

注意 插件不可靠也是业界的共识。这也是插件的工作方式决定的。比如,在访问使用Flash的页面时,浏览器会把页面中的某个矩形区域交给Flash控制。多数情况下,交接工作的过程都比较顺利。可是,一些小bug的存在,或者异常的系统配置,都可能导致意外的通信和故障,因而造成视频混乱或消耗大量计算机内存,最终让上网变得缓慢无比。

尽管如此,今天上网(不用iPhone或iPad)所看到的视频,仍然都被包装在迷你Flash应用中。你不信?右键单击视频播放器看一看。如果上下文菜单中包含“About Flash Player 10”字样的命令,那恭喜你,你点的就是无所不在的Flash插件。而且,即使是使用HTML5,恐怕我们还要准备一个Flash视频作为后备文件,以应付那些落后的浏览器(比如IE8)。

HTML5音频与视频

HTML5支持音频和视频的想法非常简单。既然能使用<img>元素在网页中添加图像,就应该能使用<audio>元素和<video>元素在网页中添加音频和视频。是这个道理,于是HTML5就增加了这两个元素。

不行就还用Flash

HTML5新增的音频和视频功能不能满足所有需求。如果你需要考虑以下事项,那么最好还是用Flash(至少目前还是要用)。

  • 有许可限制的内容。HTML5视频文件没有任何版权保护措施。事实上,任何人都可像下载图片一样下载HTML5视频,只要右键单击即可。
  • 录制视频或音频。HTML5不支持从一台电脑到另一台电脑传送音频或视频流。如果你想开发一个在线聊天程序,要使用访客机器上的麦克风和摄像头,还得用Flash。HTML5制定者为实现相同功能,正尝试新增元素。但目前在任何浏览器中,都没有办法只通过HTML实现此功能。
  • 自适应视频流。主流的、视频丰富的网站,比如YouTube,都需要精细地控制视频流和缓冲。这些网站需要以不同解析度提供视频、进行实况直播、根据访客的带宽调整视频质量。在HTML5能提供这些功能之后,视频分享网站可能会向HTML5迁移,但不会完全脱离Flash。
  • 低延迟、高性能音频。有些应用需要音频一开始就不能间断,或者需要同时播放的多个音频之间完美配合。比如虚拟合成器、音乐观察器或者多种音效同时播放的实时游戏。虽然浏览器开发商在努力提升HTML5音频的性能,但目前还无法满足要求。

动态创建或编辑音频。如果你不只是想要播放录制好的音频,而是还需要分析、修改音频信息,然后实时生成音频,怎么办?确实有一些新的标准,比如Firefox资助的Audio Data API(http://wiki.mozilla.org/Audio_Data_API),可以为HTML5补充这部分功能,但目前还是指望不上啊。

使用<audio>播放点噪音

以下是使用<audio>元素的一个最简单的例子:

<p>Hear us rock out with our new song,
<cite>Death to Rubber Duckies</cite>:</p>
<audio src="rubberduckies.mp3" controls></audio>

这里的src属性是要播放的音频文件的文件名。而controls属性告诉浏览器要包含基本的播放控件。每个浏览器中的播放控件都不太一样,但用途都一样,都可以控制开始和结束,跳到新位置和调节音量(图1)。

这里是IE(上)、Chrome(中)和Firefox(下)中的播放控件。不过,要想让音频文件在这三种浏览器中都能正常播放,还必须有针对性地定制音频格式。

注意 <audio><video>元素必须同时包含开始和结束标签,不能使用<audio />这样的空元素语法形式。

<audio>元素还支持另外三个属性:preload、autoplay和loop。其中,preload属性告诉浏览器如何下载音频。如果指定的值是auto,就是让浏览器下载整个文件,以便用户单击播放按钮时就能播放。当然,下载过程是后台进行的,网页访客不必等待下载完成,而且仍然可以随意查看网页。

除了auto之外,preload属性还支持另外两个值:metadata和none。前者告诉浏览器先获取音频文件开头的数据块,从而足以确定一些基本信息(比如音频的总时长)。后者告诉浏览器不必预先下载。恰当地利用这些值,可以节省带宽。比如,当页面中有很多<audio>元素,而你又不认为访客会播放其中很多音频的时候,就可以有选择地使用前述三个值。

<audio src="rubberduckies.mp3" controls preload="metadata"></audio>

如果使用的是none或metadata,那么浏览器会在用户单击播放按钮时立即下载音频文件。通常,浏览器在下载后续数据时,会播放已经下载完的部分;除非你的网速很慢,否则应该不会卡。

如果没有设置preload属性,浏览器就自己决定是否预先下载了。对这一点,不同浏览器的处理方式也不一样。多数浏览器将auto作为默认值,但Firefox的默认值是metadata。不过,也请大家注意,这个preload属性也不是必须严格执行的规则,而只是你对浏览器的建议。根据具体情况,浏览器可以忽略你的设置。(有些旧版本浏览器根据不会在意preload属性。)

注意 如果页面中有很多<audio>元素,浏览器会分别为它们创建自己的播放控件。访客可以每次只播放一个音频文件,也可以同时播放多个。

接下来再看看autoplay属性。这个属性告诉浏览器在加载完音频文件后立即播放:

<audio src="rubberduckies.mp3" controls autoplay></audio>

如果不设置autoplay属性,必须是用户单击播放按钮才会播放音频文件。

可以利用<audio>元素不知不觉地播放背景音乐,或者为浏览器游戏播放音效。要实现背景播放,去掉controls属性,加上autoplay属性就好了。不过要注意,即使开启背景播放,也要在页面中提供相应的装置,以便用户能够关闭声音。

警告 谁也不愿意浏览一个播放难听的背景音乐,但却无法关闭其声音的网页。如果你没有给<audio>元素添加controls属性,那必须——或至少要添加一个静音按钮,利用JavaScript让用户能够设置静音。

最后,loop属性告诉浏览器在音频到达末尾时,再从头开始重新播放:

<audio src="rubberduckies.mp3" controls loop></audio>

大多数浏览器都可以流畅地循环播放音频文件,因此可以利用这一点创建没有穷尽的音乐播放体验。关键在于选择一段终点与起点恰好能够衔接起来的音频片段。类似这样的片段,访问http://www.flashkit.com/loops/可以找到很多。(这些可循环文件是为Flash设计的,但也可以下载到MP3和WAV格式的。)

了解<video>

<video><audio>实现太相像了。它们有相同的src、controls、preload、autoplay和loop属性。下面就是一个直观的例子:

<p>A butterfly from my vacation in Switzerland!</p>
<video src="butterfly.mp4" controls></video>

同样,controls属性告诉浏览器生成方便的播放控件(见图2)。在大多数浏览器中,单击页面其他任何地方,播放控件都会自动隐藏,而当鼠标悬停于影片画面上时,它们又会显示出来。

很容易把<video>元素当成Flash视频窗口。但在<video>元素上右击鼠标,会看到比Flash更简单的菜单,其中包含把视频文件保存到本地的命令(在有的浏览器里,菜单中可能还会包含改变播放速度、循环播放视频、全屏播放及静音等选项)

除了与<audio>共同的属性之外,<video>元素还有另外3个属性:height、width和poster。

其中,height和width属性用于设置视频窗口的(像素)大小。下面这行代码会创建一个400像素×300像素的视频窗口:

<video src="butterfly.mp4" controls width="400" height="300"></video>

在设置这个尺寸时,应该注意按照视频的原始比例设置。而明确设置视频窗口大小,可以在视频尚未加载完成时(或者视频加载失败时),不影响页面的布局。

最后,poster属性用于设置替换视频的图片。浏览器在三种情况下会使用这个图片:(1) 视频第一帧未加载完毕;(2) 把preload属性设置为none;(3) 没有找到指定的视频文件。

<video src="butterfly.mp4" controls poster="swiss_alps.jpg"></video>

好了,我们现在已经介绍完有关HTML5音频和视频标记的所有内容了。然而,通过巧妙地使用JavaScript,实际上还有更多可能性。不过,我们已经不能再回避了,在继续讨论利用<audio><video>元素做一些吸引人的东西之前,无论如何得直面令人头疼的音视频编解码问题。

注意 HTML5标准还为<audio><video>规定另外两个属性:muted和mediagroup。前者用于在一开始就关闭声音(访客点击播放按钮即可打开声音),后者用于把多个媒体文件链接到一起,从而实现多个文件同步播放(在视频配合独立声音文件的时候有用)。然而,这两个属性目前还没有得到任何浏览器支持。

格式之争与后备措施

我们刚刚列举的示例使用了两种流行的标准:MP3音频和H.264视频。这两种格式是IE9和Safari的最爱,但其他浏览器则有它们自己的想法(图3)。

在Firefox中播放MP3文件(上)和在IE中播放Theora视频(下),哈,这就是让人头疼的地方了

说起HTML5格式之争,作为Web开发人员,我们有几个问题想要吼一吼。嗯……难道HTML5音频和视频就这样永远地分裂下去?而谁又是罪魁祸首?呼……好吧,问题没有听起来那么好回答。不同浏览器开发商都有十足的理由倾向于不同的视频标准。小公司(像Firefox背后的Mozilla)不愿意付给流行的标准——MP3音频、H.264视频专利费。可是,真的很难责怪他们,他们自己的开发成果都是可以自由使用的。

而大一些的公司,像微软、苹果,又都言之凿凿,为自己不使用没有许可限制的标准辩护。他们报怨那些标准并不完善(目前还没有硬件加速),而且应用也不够广泛(不像H.264已经广泛应用于便携式摄像机、蓝光播放器和其他很多设备)。实际上,最大的问题还在于,谁也说不清楚那些没有许可限制的标准是否涉及其他人的知识产权。如果是,而且微软、苹果又使用了它们,那么打上一场旷日持久的官司就在所难免了。

H.264许可

我的视频格式是H.264,我需要付许可费吗?

如果你在自己的产品中使用了H.264解码器(比如,你开发了一款浏览器,能播放H.264编码的视频),那当然得付费。而如果你是提供视频的人,那就要看情况了。

首先,听听不用掏钱的情况。如果你使用H.264制作免费视频,你不用交一分钱。如果你制作的是商业视频,但实际上并没有销售(比如拍摄商业广告或通过视频访谈推销自己),那也不用花钱。

如果你在自己的网站上销售H.264编码的视频,那可能就需要向MPEG-LA支付许可费了,要么现在,要么将来。关键的问题是有多少用户。如果用户数少于10万,不用交钱。而如果用户数达到10万,少于25万,那么应该交25 000美元/年。对于一家如此规模的视频销售公司来说,这笔钱似乎还不算多,更何况还有很多其他花销比这要多得多,比如购买专业的编码工具。可是,这个数字在2016年修订许可条款后,还会有变化。打算靠Web视频挣钱的大公司更愿意使用开放的、没有许可限制的视频标准,比如Theora或WebM。

谈谈格式

官方HTML5标准没有要求浏览器支持任何一种视频或音频格式。(之前的版本要求过,但最后经过激烈的讨论后还是删除了。)因此,浏览器开发商可以自由选择想要支持的格式,而事实上他们骨子里就不可能达成一致。表1展示了目前不同浏览器使用的标准。

格  式 说  明 常用扩展名 MIME类型
MP3 世界上最流行的音频格式。然而,许可费让Firefox和Opera等小公司敬而远之 .mp3 audio/mp3
Ogg Vorbis 免费、开放的标准,能够提供高质量的压缩音频,可以与MP3媲美 .ogg audio/ogg
WAV 未加工数字音频的初始格式。由于未经压缩,所以体积奇大,大多数情况下不适合Web .wav audio/wav
H.264 视频压缩的行业标准,特别适合高清晰度视频。广泛应用于消费设备(如蓝光播放器和便携式摄像机)、Web分享站点(如YouTube和Vimeo)和Web插件(如Flash和Siverlight) .mp4 video/mp4
Ogg Theora 免费、开放的视频标准,出自Vorbis音频标准的制定者之手。品质和性能不及H.264,但可以满足大多数人的需要 .ogv video/ogg
WebM 最新的视频格式,Google在买下VP8之后,将其改为免费标准。有评论指出,其品质尚不如H.264,而且可能牵涉其他人的专利,因此将来或许会引发诉讼。无论如何,WebM最有可能成为将来的开放视频格式 .webm video/webm

表1中也列出了媒体文件应有的扩展名。为什么扩展名很重要?回答这个问题,必须认识到一个视频文件实际上有三个标准参与其中。首先,也是最明显的,就是视频编解码器,用于把视频压缩为数据流(包括H.264、Theora和WebM)。其次是音频编解码器,利用相关的标准压缩一或多个音频文件。(例如,H.264一般使用MP3,而Theora则使用Vorbis。)第三是容器的格式,规定了如何把视频、音频、描述性信息以及静态图片和字幕等填充物组合到一起。一般来说,文件的扩展名表示容器的格式。因此,.mp4意味着MPEG-4容器,.ogv表示Ogg容器。

比较微妙的地方在这里:多数容器格式都支持一些不同的视频和音频标准。例如,流行的Matroska容器(.mkv)可以包含H.264或Theora编码的视频。考虑到不让你的脑袋疼得裂开,表1针对每种视频格式给出了一种最常用,同时也是在Web上获得了最可靠支持的容器格式。

表1中也列出适当的MIME类型,这些在配置Web服务器的时候有用。如果不小心用错了MIME类型,那么浏览器可能就会顽固地拒绝播放本身好好的媒体文件。(要是你还不太明白什么是MIME类型,如何配置,可以参考下一节的内容。)

浏览器对媒体格式的支持情况

除非我们知道浏览器支持哪些格式,否则世界上的格式再多对我们也没有意义。表2列出了不同浏览器对不同音频格式的支持情况,表3展示了这些浏览器对不同视频格式的支持情况。

格式 IE Firefox Chrome Safari Opera Safari iOS Android
MP3 9 - 5 3.1 - 3 -
Ogg Vorbis - 3.6 5 - 10.5 - -
WAV - 3.6 8 3.1 10.5 - -
格式 IE Firefox Chrome Safari Opera Safari iOS Android
H.264 Video 9 - * 3.1 - 4**
Ogg Theora - 3.5 5 - 10.5 - -
WebM *** 4 6 - 10.6 - 2.3
  • Chrome目前是支持这个标准的,但为了更好地推广WebM,已经宣布将来会取消这项支持。 ** iOS 3.x支持视频,但Safari浏览器中存在一些微小的视频方面的bug。例如,设置poster属性(参见5.2.2节)会导致视频无法播放。 *** IE将来会支持WebM,但要求计算机用户自己安装编解码器。

移动设备上的浏览器也有不同的支持问题。首先是存在一些怪异的问题。比如,像自动播放和循环这样的功能,可能会不被支持,而有些设备可能会用专门的播放器(而不是在网页容器中)播放媒体文件。更重要的是,针对移动设备进行视频编码时,尺寸可以小一些,而且质量也可以不必太高。

提示 这里有一个经验法则,如果你想让视频能在移动设备上播放,那就应该使用H.264 Baseline Profile(而非Hight Profile)编码。对于iPhone和Android手机,视频尺寸不必超过640×480(如果还要支持黑莓手机,那么不必超过480×360)。很多编码软件(参见后面的附注栏)都有针对移动视频进行优化的预设选项。
 
理解MIME类型

MIME类型(有时候也叫做内容类型)就是一小段信息,表示某种Web资源的内容类型。例如,网页的MIME类型就是text/html。

Web服务器在把某个资源发送给浏览器的时候,会在前面发送MIME类型。比如,假设浏览器请求了一个网页SuperVideoPlayerPage.html,服务器会发送text/html这个MIME类型、其他一些相关信息和实际的文件内容。浏览器接收到该MIME类型后,就知道该如何处理后面的内容。这样,就不必根据文件的扩展名或其他信息去判断了。

对于常见的文件类型(如HTML页面和图片),不必担心其MIME类型,因为Web服务器都能够适当地处理。但某些Web服务器或许没有配置音频和视频的MIME类型。这就是问题了,如果Web服务器在发送媒体文件时发错了MIME类型,会导致浏览器不知所措。而结果一般就是不能播放。

为避免这个问题,务必要按照表1列出的MIME类型正确地配置Web服务器,同时也不要忘了给自己的音频和视频文件使用正确的扩展名。(光正确配置MIME类型还不够,还得使用正确的扩展名。因为Web服务器要成对儿使用这两方面信息。比如,把.mp4文件配置为video/mp4这个MIME类型后,却在视频文件上使用了.mpFour作为扩展名,那Web服务器就不知道你想让它做什么了。)

多种格式:如何讨好每一款浏览器

面对这些格式上的差异,老实巴交的Web开发人员何去何从?可惜的是,没有哪个音频或视频格式可以在所有浏览器中播放。假如你想支持所有浏览器(当然应该),就需要准备多种格式的媒体文件。甚至,你还得准备Flash格式的文件,以便那些不支持HTML5的浏览器(如IE8)用户能正常听到或看到。

好在,<audio><video>元素都支持后备机制,而Web社区的老大哥们也为我们弥补了很多缺失。当然,有点令人不爽的是,对于每个媒体文件,至少都要编码两次——既浪费时间,又浪费CPU和磁盘空间。

开始制作多版本的媒体文件之前,首先要确定如何支持非HTML5浏览器。一般来说,我们有两个基本的选择。

  • 主选Flash,HTML5作后备。也就是给所有人都提供Flash格式的文件,只有未安装Flash的人看不到。这种办法适合那些已经利用成熟的Flash视频播放器在自己的网站上展示视频,但又不想失去iPad和iPhone用户的人。
  • 主选HTML5,Flash作后备。也就是给所有人都提供HTML5视频(或音频),而那些旧版本浏览器的用户可以看到Flash内容。选择这种方式的话,还需要确定支持哪些格式。如果用户的浏览器支持HTML5,但不支持你提供的格式,他们也能看到Flash内容。这是面向未来的一种方式,但要求必须容忍HTML5音频和视频目前的限制。

接下来几节,我们按照第二种方式尝试一下。换句话说,我们要尽可能使用HTML5格式。

使用<source>元素

要想支持多种格式,第一步就要从<video><audio>元素中删除src属性,然后嵌套一组<source>元素。以下是一个<audio>元素嵌套<source>元素的例子:

<audio controls>
  <source src="rubberduckies.mp3" type="audio/mp3">
  <source src="rubberduckies.ogg" type="audio/ogg">
</audio>

在此,一个<audio>元素嵌套了两个<source>元素,每个<source>元素都指向一个不同的音频文件。浏览器会选择播放第一个它所支持的文件。Firefox和Opera会播放rubberduckies.ogg,而IE、Safari和Chrome会播放rubberduckies.mp3。

理论上讲,浏览器可以通过下载部分文件内容来判断它是否支持相应的格式。但更好的做法则是像这里一样使用type属性提供正确的MIME类型信息。如此一来,浏览器就只会下载它认为自己能够播放的文件了。

同样的做法也适用于<video>元素。下面这个例子使用了两个相同的视频文件,但一次用H.264编码,一次用Theora编码:

<video controls width="700" height="400">
  <source src="beach.mp4" type="video/mp4">
  <source src="beach.ogv" type="video/ogg">
</video>

这个例子有一些新的东西。在使用多个视频格式时,应该把H.264编码的文件放在前头。否则,运行iOS 3.x的iPad无法正确播放该文件。(iOS 4已经修复了这个问题,但将H.264格式的文件放在前头总没有坏处。)

注意 浏览器认为它支持某种类型的音频或视频文件,并不意味着它一定能播放该文件。例如,你可能会对自己的文件使用不常见的高比特率,或者在某种常用的容器格式中使用一种生僻的编解码器。要解决这个问题,可以通过type属性提供类型和编解码器信息,但这样可能会导致标记混乱。HTML5对此给出了详细的描述,请参见http://tinyurl.com/3aq5nk3。

那应该准备几种视频格式呢?为了覆盖所有用户,要有H.264、Theora和Flash后备。为了保证品质,可以用WebM替代Theora。这样会导致版本稍微老一些的Firefox和Opera无法播放,好在这些老版本并不多。实在不行就多编一次码呗,把H.264、WebM和Theora格式都准备好(顺序也是这样)。把WebM放在Theora前头,可以让支持这两种格式的浏览器播放质量更好的视频。

如果你的想法更大胆,那可以创建一个同时支持桌面和移动设备的视频页面。这样的话,不仅要考虑H.264和Theora视频格式,还要考虑为硬件配置不高、上网速度慢的设备创建一个窄带宽版本。为确保移动设备播放轻量级视频,桌面浏览器播放高品质视频,还要用到8.4节将介绍的媒体查询。

以Flash作后备

有史以来的所有浏览器在对待不认识的标签时行为都一样:视而不见。比如,假设IE8遇到了陌生的<video>开始标签,它只会“一笑而过”,根本不去检查其src属性。然而,浏览器不会忽略不认识的元素中包含的内容,这可是一个非常重要的差异。换句话说,对于下面的标记:

<video controls width="400" height="300">
  <source src="discoParty.mp4" type="video/mp4">
  <source src="discoParty.ogv" type="video/ogg">
  <p>We like disco dancing.</p>
</video>

不支持HTML5的浏览器看到的只有:

<p>We like disco dancing.</p>

这也就是我们所说的后备内容。利用这种后备方式,可以向旧版本浏览器用户提供相应的说明,而不会让人感到迷惑不解。

编码媒体文件

现在,你应该知道自己想使用哪些格式了。但你不一定知道怎么把媒体文件转换成这些格式。别担心,有很多工具可以帮你。有的工具可以一次转换很多文件,有的工具则以产出高品质内容著称(一分钱一分货),而有的工具是在强大的Web服务器上执行转换,不用等待。关键是根据自己的具体需求,找到适合你的编码工具。

以下向大家推荐几种编码工具。

  • 音频编辑器。如果你想编辑WAV文件,并将它们保存为MP3或Vorbis格式,只要找一个简单的音频编辑器即可。我推荐Audacity(http://audacity.sourceforge.net/),这是一个免费的编辑器,有Mac和Windows版本。不过,要转换成MP3,还要另安装LAME MP3编码器(http://lame.buanzo.com.ar/)。另外,Goldwave(http://www.goldwave.com/)也是一个类似的编辑器,虽然不免费,但价格也只是象征性的。
  • Miro Video Converter。这个自由、开源的程序有Windows和Mac OS X版,可以将任何视频文件转换成WebM、Theora或H.264,而且还针对iPad、iPhone和Android设备预设了不同大小和格式。唯一不足的地方就是,它没有提供高级调校选项,无法控制编码过程。要试试看?访问http://www.mirovideoconverter.com。
  • Firefogg。这是一个Firefox插件(http://firefogg.org/),可以创建Theora或WebM视频文件。与Miro相比,它提供了更多选项,而且是在你的浏览器中运行(所有工作都在本地完成,不会涉及Web服务器)。
  • HandBrake。这是一个开源、多平台的软件(http://handbrake.fr/),能把多种格式转换为H.264(及其他几种最新的格式)。
  • Zencoder。这是一种专业的、能与你的网站集成工作的媒体编码服务。Zencoder(http://zencoder.com/)能从Web服务器上下载视频文件、将它们转换成你需要的所有格式和比特率,为转换后的文件命名并分门别类地放在相应的位置下。比较大的视频网站可以与Zencoder合作,谈一个合适的按月付费价格。   > 注意 支持HTML5音频的浏览器即使不能播放媒体文件,也会忽略后备内容。例如,如果Firefox遇到了一个指向H.264格式的文件但未提供Theora格式的<video>元素,它就会显示一个带X的视频容器(如图3所示),但不会显示后备内容。

知道了怎么添加后备内容后,接下来就要考虑添加什么内容了。后备内容可以是一句话,比如“你的浏览器不支持HTML5视频,请升级浏览器”。但网站访客认为这种方式极其不礼貌,要是让他们看到这句话,你就永远跟他们无缘了。

比较合适的后备内容是另一段可以播放的视频,也就是要使用一个普通的非HTML5页面。比如,可以使用YouTube视频窗口,但必须遵守YouTube的规定(视频长度不能超过15分钟,而且不能包含令人反感和侵犯版权的内容)。准备好内容后,可以先上传到YouTube,上传时选择一种最佳格式,而YouTube会将其重新编码成它支持的格式。

另一种可能是使用Flash视频播放器。(如果你想展示音频,就是Flash音频播放器。)各式各样的Flash视频播放器太多了,其中很多都是免费的,至少非商业用途不收费。而且,大多数Flash视频播放器还都支持HTML5视频中常用的H.264格式。

下面这个例子展示了把流行的Flowplayer(http://flowplayer.org/)插入到HTML5 <video>元素中的标记:

<video controls width="700" height="400">
  <source src="beach.mp4" type="video/mp4">
   <source src="beach.ogv" type="video/ogg">

  <object id="flowplayer" width="700" height="400"
   data="flowplayer-3.2.7.swf"
   type="application/x-shockwave-flash">
    <param name="movie" value="flowplayer-3.2.7.swf">
    <param name="flashvars" value='config={"clip":"beach.mp4"}'>
  </object>
</video>

请注意,虽然这个例子考虑了三种可能的情况(H.264格式的HTML5视频、Theora格式的HTML5视频和H.264格式的Flash视频),但只需要两个视频文件,减少了编码工作量。图5展示了这个例子的结果。

同一个视频,以三种方式提供:对IE9(上)、Firefox(中)使用HTML视频,对IE7(下)使用Flash视频
提示 虽然在Flash播放器中重用H.264视频很方便,但这种方式也不是没有缺点。Flash 9.0.115.0之前的版本是不支持H.264格式的。因此,如果浏览器中安装的Flash版本比较老,就有可能播放不了H.264格式的视频,除非升级Flash插件。为了避免这种情况,可以选择Flash Video Format(.flv),这个格式保证在所有Flash版本中都能正常播放,只不过就得再多编码一次了。

当然,还是有些人连Flash都没装,而且浏览器也不支持HTML5。对这些用户,可以提供另一种形式的后备内容,比如一个指向视频文件的下载链接,点击可以在外部程序中打开。这样的内容要放在Flash内容后面,但仍然在<object>元素内:

<video controls width="700" height="400">
  <source src="beach.mp4" type="video/mp4">
  <source src="beach.ogv" type="video/ogg">

  <object id="flowplayer" width="700" height="400"
   data="http://releases.flowplayer.org/swf/flowplayer-3.2.7.swf"
   type="application/x-shockwave-flash">
    <param name="movie" value="beach.mp4">

    <img src="beach_thumbnail.jpg" alt="A lazy day at the beach">
    <p>Your browser does not support HTML5 video or Flash.</p>
    <p>You can download the video in <a href="beach.mp4">MP4 H.264</a>
    or <a href="beach.ogv">Ogg Theora</a> format.</p>
  </object>
</video>

假如你想主要提供Flash视频,以HTML5作为后备(而不是主选HTML5,以Flash作为后备),那在这个例子上简单调整一下就好。首先是<object>元素,然后在其中嵌套<video>元素,最后是</object>标签结束。这种情况下,需要把后备内容放在最后一个<source>元素之后:

<object id="flowplayer" width="700" height="400"
 data="http://releases.flowplayer.org/swf/flowplayer-3.2.7.swf"
 type="application/x-shockwave-flash">
  <param name="movie" value="butterfly.mp4">

  <video controls width="700" height="400">
    <source src="beach.mp4" type="video/mp4">
    <source src="beach.ogv" type="video/ogg">

    <img src="beach_thumbnail.jpg" alt="A lazy day at the beach">
    <p>Your browser does not support HTML5 video or Flash.</p>
    <p>You can download the video in <a href="beach.mp4">MP4 H.264</a>
    or <a href="beach.ogv">Ogg Theora</a> format.</p>
  </video>
</object>

一般来说,只有在你已经有了一个基于Flash的网站,而你想对其加以扩展,使其支持iPad等苹果设备时,才需要采用这个方案。通常,至少应该有一个JavaScript播放器,用作HTML5后备。

使用JavaScript控制播放器

到现在为止,我们介绍了一些基础知识,也知道了怎么围绕新的<audio><video>元素拿出合理的支持方案,使媒体文件不仅能在Flash播放器里播放,而且能在更多的网页中直接播放。这些新技术还是能派上用场的。

如果只谈标记,那么利用<audio><video>也就只能做那么多了。然而,这两个元素都有一个扩展的JavaScript对象模型,让我们能通过代码控制播放过程。事实上,甚至还可以调整一些细节,比如播放速度。这些功能是浏览器标准的音频和视频播放器力所不能及的。

好了,接下来的几节,我们通过两个实际的例子,介绍JavaScript对音频和视频的支持。第一个例子是为游戏添加音效,第二个例子将创建一个自定义的视频播放器。最后,我们还将讨论几个其他人利用HTML5和JavaScript开发出来的解决方案,包括可换肤的播放器和无障碍字幕。

添加音效

通过<audio>元素并不是只能播歌曲和录音,还可以利用它播放音效。这一点使其特别适合为游戏配乐和添加音效。

图6展示了一个非常简单的例子,网页中显示着可交互的弹跳球动画。现在,我们需要考虑的是怎么为它配上合适的背景音乐。

这个页面在画布元素上运行一个简单的动画,单击按钮可以添加新的弹跳球(新球会下落,并不断在画布区域内弹跳)。另外,用鼠标单击可以改变球的弹跳方向

实际上,这个例子组合了背景音乐和音效。添加背景音乐很简单,只要在页面中加上一个不可见的<audio>元素即可:

<audio id="backgroundMusic" loop>
  <source src="TheOwlNamedOrion.mp3" type="audio/mp3">
  <source src="TheOwlNamedOrion.ogg" type="audio/ogg">
</audio>

我们没有给音频播放器添加autoplay或controls属性,因此开始的时候没有声音,也看不到播放器界面。不过,倒是添加了一个loop属性,这样只要一开始播放,就会不断反复播放。为了控制声音的播放,需要使用两个音频(或视频)对象的方法:play()和pause()。怎么没有停止播放的方法呢?的确没有,要停止播放,可以先暂停视频,然后将其currentTime属性重置为0,即下次播放会从头开始。

了解了这些以后,就可以在添加第一个球时开始播放背景音乐了,很简单:

var audioElement = document.getElementById("backgroundMusic");
audioElement.play();

在清除画布的时候停止播放背景音乐同样很简单:

var audioElement = document.getElementById("backgroundMusic");
audioElement.pause();
audioElement.currentTime = 0;

前面介绍过,同时播放多少个音频文件是没有限制的。因此,在背景音乐开始播放的同时,我们可以再琢磨一下怎么添加更好玩的音效。

对这个例子来说,小球每次从地面或墙上弹开的时候,都要播放弹簧突然释放的“啵嘤”声。为了增强趣味性,我们使用了几种不同的音效。当然,我们这里只是模仿真实的游戏,如果是真实的游戏,恐怕要集成十几个甚至更多声音文件。

实现上述设计的方案有很多,但并不都可行。比如,可以再添加一个<audio>元素,用于播放音效。然后,每次小球撞击反弹时,都通过修改其src属性加载一个新音频文件。这个方案有两个问题。首先,每个<audio>元素每次只能播放一个声音文件,因此如果有多个球连续反弹,那要么不播放紧接着的、重叠的声音,要么立即停止前一个音效,加载并播放后一个。其次,重新设置src属性会强迫浏览器请求音频文件。虽然有些浏览器能很快加载完新音频(如果音频已经在缓存中了),但IE不行。结果,就是音效会延迟——球都弹开半秒钟了,音效才播放。

更好的方案是使用一组<audio>元素,每个播放一种音效。以下就是示例代码:

<audio id="audio1">
  <source src="boing1.mp3" type="audio/mp3">
  <source src="boing1.wav" type="audio/wav">
</audio>
<audio id="audio2">
  <source src="boing2.mp3" type="audio/mp3">
  <source src="boing2.wav" type="audio/wav">
</audio>
<audio id="audio3">
  <source src="boing3.mp3" type="audio/mp3">
  <source src="boing3.wav" type="audio/wav">
</audio>

注意 这里的3个<audio>元素使用了不同的音频文件,但这并不是必须的。比如,你可以使用同一个音频文件,而为了支持重叠音效,可能还得使用三个音频播放器。

发生碰撞反弹时,JavaScript代码会调用一个名为boing()的自定义函数。这个函数会按照顺序取得下一个<audio>元素,然后播放声音。

以下就是实现音效播放的代码:

//记录<audio>元素的个数
var audioElementCount = 3;

//记录当前播放的<audio>元素
var audioElementIndex = 1;

function boing() {
  //取得循环列表中的下一个<audio>元素
  var audioElementName = "audio" + audioElementIndex;
  var audio = document.getElementById(audioElementName);

  //播放音效
  audio.currentTime = 0;
  audio.play();

  //把计数器更新为下一个<audio>元素
  if (audioElementIndex == audioElementCount) {
    audioElementIndex = 1;
  }
  else {
    audioElementIndex += 1;
  }
}

这个例子能够正常运行,可如果你想实现更大范围的音效怎么办?最简单的方案就是为每个音效单独创建一个隐藏的<audio>元素。如果不行,还可以动态设置已有<audio>元素的src属性。甚至,可以像下面这样动态地创建新<audio>元素:

var audio = document.createElement("audio");
audio.src = "newsound.mp3";

或者更简单:

var audio = new Audio("newsound.mp3");

不过,这两种方式都存在问题。首先,必须在播放音频之前设置src属性。否则就会造成音效延迟,在IE中特别明显。其次,必须知道浏览器支持的音频格式,这样才能设置正确的文件类型。为此,就得使用笨拙的canPlayType()方法。给这个方法传入音频或视频的MIME类型,它会告诉你浏览器是否能播放该格式——基本上准确。如果浏览器不支持传入的类型,canPlayType()方法会返回空字符串,如果该方法认为浏览器可以,则返回“probably”,如果它希望浏览器可以,则返回“maybe”,但这些都不能保证真的可以播放。之所以会有判断失误的时候,主要是因为有时候浏览器虽然支持相应的容器,但该容器中却使用了浏览器不支持的编解码器,而即使浏览器支持编解码器,但也可能不支持其编码设置。

大多数开发人员喜欢下面这种编码方式,即只要canPlayType()不返回空字符串,就说明浏览器支持相应的格式:

if (audio.canPlayType("audio/ogg")) {
  audio.src = "newsound.ogg";
}
else if (audio.canPlayType("audio/mp3")) {
  audio.src = "newsound.mp3";
}

创建自定义视频播放器

使用JavaScript操作<audio><video>元素的最常见理由,就是构建自己的播放器。基本思想很简单,不添加controls属性,但有播放窗口,因此可以在下方添加自己的播放控件。最后,添加JavaScript代码,让新控件发挥作用。图7展示了一个例子。

制作自己的HTML5视频播放器很简单(要做好可不简单)。这个例子中包含标准的播放控件、播放进度条和其他一些按钮,展示了JavaScript对<video>元素的全方位控制能力

每个视频播放器都需要一套基本的播放按钮。图7就使用了普通的按钮。

<button onclick="play()">Play</button>
<button onclick="pause()">Pause</button>
<button onclick="stop()">Stop</button>

这几个按钮会触发以下简单的函数:

function play() {
  video.play();
}

function pause() {
  video.pause();
}

function stop() {
  video.pause();
  video.currentTime = 0;
}

另外3个播放控制按钮可不太常见,它们可以修改playbackRate以改变播放速度。例如,把playbackRate设置为2,视频会以正常速度的两倍播放,不过由于有音高校正,所以音频听起来正常,只是速度加快了。这个功能对于快速看完一段拖沓的培训视频是很有用的。类似地,把playbackRate设置为0.5,会导致视频比正常速度放慢一半播放,而把playbackRate设置为?1,速度不变,只是会倒退播放——在有些浏览器中,可能无法顺畅地实现此功能:

function speedUp() {
  video.play();
  video.playbackRate = 2;
}

function slowDown() {
  video.play();
  video.playbackRate = 0.5;
}

function normalSpeed() {
  video.play();
  video.playbackRate = 1;
}

创建播放进度条更有意思一些。进度条的标记实际上就是两个嵌套的<div>元素:

<div id="durationBar">
  <div id="positionBar"><span id="displayStatus">Idle.</span></div>
</div>

提示 播放进度条是非常适合使用<progress>元素实现的功能。但是,由于支持<progress>元素的浏览器有限——比支持HTML5视频的浏览器少得多,因此这个例子就使用两个<div>来实现类似的功能。

外面的<div>元素(durationBar)显示实心边框,勾勒出进度条的整个轮廓,表示视频的完整播放时间。内部的<div>元素(positionBar)表示当前播放的时间点,视觉上就是在黑色方框中填入蓝色。最后,内部<div>中的<span>元素保存着状态文本,用于在播放期间显示当前时间点(秒)。

用于为这两个长条添加样式的CSS规则如下:

#durationBar {
  border: solid 1px black;
  width: 100%;
  margin-bottom: 5px;
}

#positionBar {
  height: 30px;
  color: white;
  font-weight: bold;
  background: steelblue;
  text-align: center;
}

在视频播放过程中,<video>元素会连续触发onTimeUpdate事件,通过响应这个事件可以更新播放进度条:

<video id="videoPlayer" ontimeupdate="progressUpdate()">
  <source src="butterfly.mp4" type="video/mp4">
  <source src="butterfly.ogv" type="video/ogg">
</video>

在此,代码会取得视频的当前时间点(保存在currentTime属性中),除以视频总时间(保存在duration属性中),然后将得到的百分比转换为positionBar <div>元素的百分比长度:

function progressUpdate() {
  //动态设置蓝色的positionBar,从0到100%
  var positionBar = document.getElementById("positionBar");
  positionBar.style.width = (video.currentTime / video.duration * 100) + "%";

  //显示已经播放的秒数,保留两位小数
  displayStatus.innerHTML = (Math.round(video.currentTime*100)/100) + " sec";
}

提示 如果你还想做得更精致一点,可以再添加一个下载进度条,显示当前已经下载和缓冲的多少内容。浏览器已经把这个功能内置在它们自己的播放器中了。如果你要自己做,需要处理onprogress事件,并利用seekable属性。要了解<video>元素提供的更多属性、方法和事件。

JavaScript媒体播放器

如果你真的想标新立异,你可以自己开发自己的音频和视频播放器。但这可不是一项小工程,特别是像交互式播放列表这样的时髦功能,不容易实现。而且,如果不是有一个艺术设计部分作后盾,最终出来的产品界面很可能会丑陋不堪。

别苦恼了,除了自己开发,还有很多现成的HTML5播放器可供选择。网上有很多人已经开发了免费的基于JavaScript的媒体播放器。在此,我推荐两个靠谱的,一个是VideoJS(http://videojs.com/),另一个是jQuery粉丝们喜欢的jPlayer(http://www.jplayer.org/)。这两款播放器都很小,使用方便,而且可以换肤。换肤的意思就是通过更换样式表,可以为播放器界面应用不同的样式(参见图8)。

VideoJS播放器自带了模仿流行视频网站的皮肤,比如YouTube、Vimeo和Hulu。这里显示了播放控件的样式变化

大多数JavaScript媒体播放器(包括VideoJS和jPlayer)都内置了Flash后备,这样就省得我们自己去下载Flash播放器了。而且,jPlayer还提供了自己的播放列表功能,让用户可以把音频和视频文件组织到一个列表中(图9)。

使用jPlayer的播放列表功能,可以提供多个音频或视频文件。用户既可按顺序播放,也可以单击播放任意一个。图中的播放列表包含三个视频文件

要使用VideoJS,首先需要从VideoJS网站下载JavaScript文件。然后,像下面这样在页面中添加对相应JavaScript和样式表文件的引用:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>...</title>

  <script src="video.js"></script>
  <link rel="stylesheet" href="video-js.css">
</head>
...

之后,像平常使用<video>元素一样,准备多个<source>元素和Flash后备即可。(VideoJS播放器的示例代码中已经内置了Flowplayer作为Flash后备,如果你不喜欢,可以换成其他Flash播放器。)事实上,要说普通HTML5视频页面与使用VideoJS的页面有什么不一样,那就是对于后者,你必须得用一个特殊的<div>元素包装<video>元素,如下所示:

<div class="video-js-box">
  <video class="video-js" width="640" height="264" controls ...>
    ...
  </video>
</div>

仅此而已。虽然是扩展HTML5,但这么简单还真是让人惬意。

字幕与无障碍性

HTML5的制定者经常会考虑Web的无障碍性。所谓无障碍,就是让残疾人也能方便快捷地使用功能丰富的网页。

为图片添加无障碍信息很容易,只要在alt属性中放上一段合适的描述性文本即可。那么,视频流中与alt文本对应那个东西应该是什么呢?人们一致认为是字幕,也就是在视频播放期间,适时出现的一段段的内容对白或话外音。说起字幕,有人可能会想到电视上的闭源字幕(closed caption),通常都是人物对话或者画面内容的补充说明。关键是,字幕可以让即使听不见的人(或者不想在办公室里打开电脑音箱,但又忍不住观看《钢铁侠3》预告片的人)也能把视频看明白。

唉,虽然大家都认可字幕是实现无障碍的好办法,但却没人给出一个实现方案。HTML5建议了一个<track>元素,指向一个外部字幕文件,可以是WebSRT格式,也可以是新出来还有待完善的WebVTT格式。将来会有一天,浏览器能够读取这个元素,并为用户提供相应控件,以便打开和关闭字幕。而搜索引擎也可以取得字幕文件,索引其中的内容。但现在,到底怎么办还没有定论,HTML5标准里也没有给出明确的说法。

开发人员能做的,就是自己动手用JavaScript实现自己的字幕机制。通常,这需要使用一个浮动在视频窗口上的<span>元素,随着播放进度适时地显示字幕内容。例如,VideoSub这个JavaScript库(http://www.storiesinflight.com/js_videosub/),就可以从WebSRT字幕文件中提取文本,并将其显示到视频窗口中(如图10所示)。VideoSub会检测浏览器对字幕的支持情况,只有浏览器不支持字幕才会自己上手。(目前来看,还没有浏览器支持字幕,所以VideoSub总会自已动手。)甚至还有一个JavaScript播放器内置了字幕播放功能,这就是LeanBack Player(http://dev.mennerich.name/showroom/html5_video)。可惜的是,现在还没有办法告诉大家实现字幕功能的最佳方案,因为说什么都为时尚早,或许应该是下一代浏览器内置这一功能,让我们能够用最少的工作达到目的。如果你现在的确需要字幕,那么只能先选择JavaScript方案,然后随着HTML的发展再作打算。

使用VideoSub为视频添加字幕,只需引用两个JavaScript文件和一个WebSRT文件。

参考文档