HTML5音频和视频你必须知道的事

389 阅读29分钟

为了推广我认为是目前市场上最好的HTML5书籍雷米-夏普布鲁斯-劳森同意向我们的读者捐赠《介绍HTML5》中的一个章节,其中详细介绍了使用HTML5视频和音频的内幕。这篇文章最近也进行了更新,包含了关于浏览器支持的最新信息。

很久以前,在一个感觉非常遥远的星系中,网络上的多媒体仅限于叮叮当当的MIDI曲调和GIF动画。随着带宽的提高和压缩技术的改进,MP3音乐取代了MIDI音乐,真正的视频开始得到发展。各种各样的专有播放器展开了激烈的竞争--Real Player、Windows Media等等,直到2005年有一个播放器成为胜利者。Adobe Flash,主要是因为它的插件无处不在,而且它是YouTube的首选传输机制。然而,Flash不安全,有漏洞,而且不能很好地与网络整合,所以HTML5,一个开放的标准,最终取代了大多数网站的Flash。

在这篇文章中,我们将讨论HTML5的音频和视频元素。


本地多媒体:为什么,什么,以及如何?

2007年,Anne van Kesteren写信给工作组:

"Opera有一些内部实验性的构建,有一个<video> 元素的实现。该元素暴露了一个简单的API(目前),很像Audio()对象:play(), pause(), stop()。我们的想法是,它的工作方式与<object> 相同,只是它有特殊的<视频>语义,就像<img> 有图像语义一样。"

虽然API的复杂性增加了,但van Kesteren最初宣布的内容现在已经在所有主要的浏览器中实现,包括Internet Explorer。

<video> 元素的一个明显的伙伴是<audio> 元素;它们有许多相似的特征,所以在本章中我们将它们放在一起讨论,只注意它们的区别。

<video>:为什么你需要一个<video> 元素?

以前,如果开发者想在网页中加入视频,他们必须使用<object> 元素,这是一个用于 "外来物 "的通用容器。由于浏览器的不一致性,他们还需要使用以前无效的<embed> 元素,并重复许多参数。这导致代码看起来很像这样:

<object width="425" height="344">
  <param name="movie" value="http://www.youtube.com/Âv/9sEI1AUFJKw&hl=en_GB&fs=1&" />
  <param name="allowFullScreen" value="true" />
  <param name="allowscriptaccess" value="always" />
  <embed src="http://www.youtube.com/ Âv/9sEI1AUFJKw&hl=en_GB&fs=1&" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344">
  </embed>
</object>

<embed> 是最终在HTML5中标准化的;它从来都不是任何以前的(X)HTML风味的一部分。

这段代码很难看,也很不雅观。比这更糟糕的是,浏览器必须将视频传递给第三方插件;希望用户拥有该插件的正确版本(或拥有下载和安装该插件的权利,或知道如何安装);然后希望该插件能够被键盘访问--以及将内容移交给第三方应用程序所涉及的所有其他未知因素。

插件也可能是导致浏览器不稳定的一个重要原因,当技术水平较低的用户被提示下载和安装较新的版本时,他们可能会产生担忧。

每当你在网页中加入一个插件时,你就预留了一定的绘图区域,浏览器将其委托给该插件。就浏览器而言,该插件的区域仍然是一个黑盒子--浏览器不处理或解释那里发生的任何事情。

通常情况下,这不是一个问题,但当你的布局与插件的绘图区域重叠时,就会出现问题。例如,想象一下,一个网站包含一个电影,但也有基于JavaScript或CSS的下拉菜单,需要在电影上展开。默认情况下,该插件的绘图区域位于网页的顶部,这意味着这些菜单会奇怪地出现在电影的后面。

如果你的页面有动态的布局变化,也会出现问题和怪异的现象。如果插件绘图区的尺寸被调整,有时会产生不可预见的影响--在插件中播放的电影可能不会调整大小,而只是被裁剪或显示额外的空白空间。HTML5提供了一种直接在浏览器中播放视频的标准化方式,不需要插件。

HTML5视频元素的主要优势之一是,视频终于成为网络上的正式公民了。它不再被分流到<object> 或非验证性的<embed> 元素的腹地。

所以现在,元素可以用CSS进行造型;例如,它们可以在悬停时使用CSS过渡来调整大小。它们可以用JavaScript调整并重新显示在<canvas> 。最重要的是,开放网络标准所提供的与生俱来的黑客能力被打开了。以前,你所有的视频数据都被锁起来了;你的比特被困在一个盒子里。有了HTML5多媒体,你的比特可以自由地被操纵,无论你想怎么做。

只要http 端点是网络上的流媒体资源,你就可以将<video><audio> 元素指向它来流传内容。

视频元素的剖析

在最简单的情况下,在HTML5中包括视频的页面只需要这些代码:

<video src=turkish.ogv></video>

这里使用**.ogv**文件扩展名来指向Ogg Theora视频。

类似于<object> ,你可以在标签之间添加回退标记,用于不支持本地视频的旧网络浏览器。你至少应该提供一个视频的链接,这样用户就可以把它下载到他们的硬盘上,以后在操作系统的媒体播放器上观看:

<h1>Video and legacy browser fallback</h1>
<video src=leverage-a-synergy.ogv>
   Download the <a href=leverage-a-synergy.ogv>How to leverage a synergy video</a> 
</video>

HTML5 video in a modern browser and fallback content in a legacy browser.

现代浏览器中的HTML5视频和传统浏览器中的后备内容。

然而,这个例子实际上还不会做任何事情。你在这里能看到的只是电影的第一帧。这是因为你还没有告诉视频的播放,也没有告诉浏览器提供任何播放或暂停视频的控制。

自动播放

你可以告诉浏览器自动播放视频或音频,但你几乎肯定不应该这样做,因为许多用户(特别是那些使用辅助技术的用户,如读屏器)会发现这很有干扰性。移动设备上的用户可能不希望你在他们没有明确要求播放视频的情况下使用他们的带宽。尽管如此,你可以这样做。

<video src=leverage-a-synergy.ogv autoplay> </video>

由于自动播放视频的烦扰,一些浏览器如iOS上的Safari需要用户互动才能开始播放视频,所以自动播放并不总是可靠的。

控件

提供控件比自动播放视频大约好764%。你可以使用一些简单的JavaScript来编写你自己的控件(后面会详细介绍),或者你可以告诉浏览器自动提供它们。

<video src=leverage-a-synergy.ogv controls> </video>

当然,这些控件在不同的浏览器之间是不同的,就像表单控件一样,但你会发现没有什么太令人惊讶的。这里有一个播放/暂停的切换键,一个搜索栏,以及音量控制。

这些控件可以通过标签进入,因此比Flash等插件更容易访问,因为它们与HTML的其他部分整合得更好。

如果<audio> 元素有控制属性,你就会在页面上看到它们。如果没有这个属性,页面上根本就没有任何视觉效果,但当然是在DOM中,并可通过JavaScript和新的API完全控制。

海报

poster属性指向一个图像,浏览器将在视频下载过程中使用该图像,或者直到用户告诉视频播放为止。(这个属性不适用于<audio> 。)它消除了对额外技巧的需要,如显示一个图像,然后在视频开始时通过JavaScript删除它。

如果你不使用poster属性,浏览器会显示电影的第一帧,这可能不是你想显示的代表性图像。

高度、宽度

这些属性告诉浏览器视频的尺寸,单位是像素。(它们不适用于。)如果你不使用它们,浏览器就会使用视频资源的固有宽度,如果那是可用的。否则就是海报框架的内在宽度,如果有的话。否则就是300像素。建议使用这个值,以防止视频加载时内容发生偏移。

如果你指定了一个值,但没有指定另一个值,浏览器会调整未指定的尺寸以保持视频的长宽比:

<video src=leverage-a-synergy.ogv autoplay> </video>

如果您将宽度和高度都设置为与视频不匹配的长宽比,那么视频不会被拉伸到这些尺寸,而是在您指定的尺寸的视频元素内呈现 "字母盒",同时保留长宽比。

循环

loop属性是另一个布尔属性。正如你所想象的那样,它会循环播放媒体。

预加载

也许你很确定用户想激活媒体(例如,他从一些导航中钻到了媒体,或者这是进入页面的唯一原因),但你不想使用自动播放。如果是这样,你可以建议浏览器预装视频,以便在页面加载时开始缓冲,期望用户能激活控制:

<video src=leverage-a-synergy.ogv controls preload> </video>

预加载属性有三种规范定义的状态。如果你只是说预载,用户代理可以决定做什么。例如,移动浏览器可以默认为不预加载,直到用户明确告诉它这样做:

1. preload=auto (or just preload)

对浏览器的建议是,它应该开始下载整个文件。请注意,我们说的是 "建议"。浏览器可能会忽略这一点--也许是因为它检测到了非常慢的连接,或者是移动浏览器中的一个设置 "从不预加载媒体 "以节省用户的带宽:

2. preload=none

这种状态向浏览器建议,在用户激活控件之前,它不应该预加载资源:

3. preload=meta

这种状态向浏览器建议,它应该只是预取元数据(尺寸、第一帧、轨道列表、持续时间等),但在用户激活控件之前,它不应该进一步下载任何东西。大多数现代浏览器默认为preload=meta

src

如同在<img> ,这个属性指向要显示的文件。然而,由于不是所有的浏览器都能播放相同的格式,在生产环境中,你需要有一个以上的源文件。我们将在下一节介绍这个问题。使用带有src属性的单个源文件只对快速原型设计或内部网站有用,因为你知道用户的浏览器和它支持的编解码器。


编解码器--可怕的,可怕的

目前,支持度最高的格式是h.264格式,在MP4文件中使用。它几乎拥有普遍的浏览器支持,根据CanIUse的数据,96%的用户支持它。然而,h.264是专有的,通常不如现在更现代的编解码器优化。

幸运的是,现在有更多的优化和免版税的编解码器。使用几乎被普遍支持的webM容器格式,你可以使用VP9和AV1等编解码器。VP9被广泛支持,压缩效果比h.264好。AV1的压缩效果甚至比VP9更好,但由于它是新的,还没有得到普遍支持。AV1目前在Safari中不被支持。

为了让最多的人获得最佳体验,请使用VP9和webM,并保留MP4作为备用。如果你愿意,你甚至可以为支持的浏览器添加AV1视频。

多个<source> 元素

要做到这一点,你需要对你的多媒体进行两次编码:如果是视频,一次是Theora,一次是H.264 ,如果是音频,则同时使用Vorbis和MP3。你也可以通过改编下面的代码来选择更现代的编解码器进行测试。

然后,你将这些独立的文件版本与媒体元素绑定。你不使用单一的src属性,而是在<audio><video> 元素内为每个编码嵌套单独的<source> 元素,并带有适当的类型属性,让浏览器下载它能显示的格式。

注意,在这种情况下,我们没有在媒体元素本身提供src属性:

<video controls>
    <source src=leverage-a-synergy.ogv type=’video/ogg; codecs="theora, vorbis"'>
    <source src=leverage-a-synergy.mp4 type=’video/mp4; codecs="avc1.42E01E, mp4a.40">
 <p>Your browser doesn’t support video.
 Please download the video in <a href=leverage-a-synergy.ogv>Ogg</a> or <a href=leverage-a-synergy.mp4>mp4</a> format.</p>
</video>

第1行告诉浏览器要插入一个视频,并给它默认的控制。

2行提供了一个Ogg Theora视频,并使用type属性告诉浏览器使用的是哪种容器格式(通过给出文件的MIME类型),以及视频和音频流的编码使用的是什么编解码。我们还可以在这里提供一个WebM视频,作为高质量的免版税选择。请注意,我们在这些参数周围使用了引号。如果你漏掉了类型属性,浏览器在弄清它不被支持之前会下载每个文件的一小部分,这就浪费了带宽,并可能延迟媒体的播放。

标签之间的内容是后备内容,只针对完全不支持元素的浏览器。一个能理解HTML5视频但不能播放你的代码所指向的任何格式的浏览器,不会显示标签之间的 "回退 "内容。这已经在我身上咬了好几次了。遗憾的是,没有这方面的视频记录。

第3行 提供了一个H.264 视频。H.264AAC 的编解码字符串比Ogg 的编解码字符串更复杂,因为H.264AAC 有几个配置文件。更高的配置文件需要更多的 CPU 来解码,但它们的压缩效果更好,占用的带宽更少。

<video> 元素内是我们的后备信息,包括这两种格式的链接,适用于本机不能处理这两种视频类型的浏览器,但可能是在能处理其中一种格式的操作系统之上,因此用户可以下载文件并在浏览器外的媒体播放器中观看。

好了,这就是现代浏览器的所有用户的原生HTML5视频。那么,使用传统浏览器的用户--包括IE8和更老的浏览器--该怎么办?


传统浏览器的视频

现在几乎每个浏览器都支持HTML视频。只有在您必须支持非常老的浏览器版本(如IE 8)的情况下才会这样做

老式浏览器不能播放原生视频或音频,祝福他们。但是,如果你准备依靠插件,你可以确保老式浏览器的用户仍然可以体验你的内容,而且不会比他们目前得到的更差。

还记得元素的内容可以包含标记,如前面例子中的文本和链接吗?因为MP4文件类型也可以由Flash播放器插件播放,所以你可以将MP4电影组合起来作为Internet Explorer 8和其他浏览器的旧版本的退路。

这方面的代码和你想象中的过渡性黑客一样可怕,但它在安装了Flash播放器的地方都能发挥作用--这几乎是所有地方。你可以在一篇名为 "人人都能看的视频!"的文章中看到这个巧妙的技术。"的文章中可以看到这个巧妙的技术,它的发明者是克罗克-卡门

另外,你也可以在一个视频托管网站上托管回退内容,并在视频元素的标签之间嵌入一个链接:

<video controls>
   <source src=leverage-a-synergy.ogv type=’video/ogg; codecs="theora, vorbis"’>
   <source src=leverage-a-synergy.mp4 type=’video/mp4; codecs="avc1.42E01E, mp4a.40.2"’> 
   <embed src="http://www.youtube.com/v/cmtcc94Tv3A&hl=en_GB&fs=1&rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344">
</video>

你可以使用html5media库来劫持<video> 元素,并通过在你的页面头部添加一行JavaScript来自动添加必要的回退。

编码免版税的视频和音频

理想情况下,你应该从源格式本身开始转换,而不是重新压缩一个已经压缩的版本。双重压缩会严重降低最终输出的质量。

在音频方面,开源音频编辑软件Audacity对大多数现代编解码器有内置支持。对于视频转换,有几个不错的选择。对于.WebM,你可以看看www.webmproject.org/tools/,以了解越来越多的列表。

要将视频文件转换为不同的格式,你可以使用VLC这样的工具。

格式之间的文件转换也可以自动进行,并在服务器端处理。例如,在CMS环境中,你可能无法控制作者上传文件的格式,所以你可能想在服务器端进行压缩。开源的ffmpeg库可以安装在服务器上,对上传的文件进行工业强度的转换(也许你正在启动你自己的YouTube-killer?)

如果你担心存储空间,而且你乐意在各种CC许可证下分享你的媒体文件(音频和视频),可以看看互联网档案馆,它将为你转换和托管它们。只要创建一个密码并上传,然后在你的页面上使用元素,但链接到他们服务器上的源文件。

向手持设备发送不同压缩格式的视频

视频文件往往很大,如果发送非常高质量的视频到手持设备上,可能会造成浪费,因为这些设备的屏幕尺寸很小,没有必要发送高质量的视频。将用于宽屏显示器的高清晰度视频发送到手持设备屏幕上是没有意义的。将视频压缩到适合小屏幕的尺寸可以节省大量带宽,使你的服务器和最重要的--你的移动用户满意。

HTML5允许你在源元素上使用媒体属性,它可以查询浏览器以找出屏幕尺寸(或颜色数量、长宽比等),并发送针对不同屏幕尺寸而优化的不同文件。

我们使用min-device-width ,而不是min-width ,以迎合那些有视口进入内容的设备--也就是每一个全功能的智能手机浏览器,因为这给了我们视口显示的宽度。

这种功能和语法是从CSS媒体查询规范中借用的,但也是标记的一部分,因为我们要根据设备特性来切换源文件。800px在下面的例子中,浏览器被 "询问 "它是否有min-device-width ,也就是说,它是否有一个宽屏幕?如果有,它就会收到hi-res.ogv; ,如果没有,就会发送lo-res.ogv :

<video controls> 
   <source src=hi-res.ogv ... media="(min-device-width: 800px)"> 
   <source src=lo-res.ogv>
</video>

还要注意的是,你仍然应该使用先前讨论的编解码器参数和回退内容的类型属性。我们只是为了清晰起见而省略了这些。


滚动的自定义控件

媒体元素,以及音频和视频元素的一个真正令人振奋的方面是,JavaScript的API超级简单。音频和视频的API都来自同一个媒体API,所以它们几乎完全一样。这些元素的唯一区别是,视频元素有高度和宽度属性以及一个海报属性。事件、方法和所有其他属性都是一样的。考虑到这一点,我们将坚持使用更性感的媒体元素:元素来讨论我们的JavaScript。

正如你在本章开始时看到的,Anne van Kesteren谈到了新的API,我们有新的简单方法,如play()pause() (没有停止方法:只是暂停和移动到开始)、load()canPlayType() 。事实上,这就是媒体元素上的所有方法。其他的都是事件和属性。

使用JavaScript和新的媒体API,你可以创建和管理你自己的视频播放器控件。在我们的例子中,我们引导你通过一些方法来控制视频元素,并创建一个简单的控件集。我们的例子不会让你大吃一惊--它没有视频元素本身那么性感(而且有点矫揉造作!)--但你会很好地了解到通过脚本可以实现什么。最重要的一点是,用户界面将是所有的CSS和HTML。因此,如果你想用你自己的方式来设计它,只要有一点网络标准知识就可以了--不需要编辑一个外部的Flash播放器或类似的东西。

我们的手卷式基本视频播放器控件将有一个播放/暂停的切换按钮,并允许用户沿着视频的时间线划动,以跳到特定的部分。

Custom video controls

我们的起点将是一个启用了本地控件的视频。然后我们将使用JavaScript剥离本地控件并添加我们自己的控件,这样,如果JavaScript被禁用,用户仍然有办法按照我们的意图控制视频。

<video controls> 
   <source src="leverage-a-synergy.ogv" type="video/ogg" /> 
   <source src="leverage-a-synergy.mp4" type="video/mp4" /> 
   Your browser doesn’t support video. Please download the video in 
   <a href="leverage-a-synergy.ogv">Ogg</a> or <a href="leverage-a-synergy.mp4">MP4</a> format.
</video> 

<script> 
  var video = document.getElementsByTagName('video’)[0]; 
  video.removeAttribute('controls’); 
</script>

播放、暂停和切换播放

接下来,我们希望能够通过一个自定义控件来播放和暂停视频。我们已经包含了一个按钮元素,我们要绑定一个点击处理程序并实现播放/暂停功能。在我的整个代码例子中,当我提到播放变量时,它将指的是按钮元素。

<button class="play" title="play">& #x25BA;</button>

我们使用& #25BA ,这是一个几何XML实体,看起来像一个播放按钮。一旦按钮被点击,我们将启动视频,并使用& #x2590 ,将值切换到两个管道,这看起来(有点)像一个暂停。

Using XML Entities

为了简单起见,我把按钮元素作为标记,但随着我们逐步增强我们的视频控件,所有这些额外的元素(用于播放、暂停、刷新等)都应该由JavaScript生成。

在播放/暂停的切换中,我们有很多事情要做:

  • 如果视频当前暂停,开始播放,或者如果视频已经结束,那么我们需要将当前时间重置为0,也就是说,将播放头移回视频的起点。
  • 改变切换按钮的值,显示用户下次点击时,它将从暂停切换到播放或从播放切换到暂停。
  • 最后,我们播放(或暂停)视频。
if (video.paused || video.ended) {
   if (video.ended) {
      video.currentTime = 0;
}
   this.innerHTML = ' ’; // & #x2590 & #x2590 doesn’t need escaping here
   this.title = 'pause’;
   video.play(); 
} else {
   this.innerHTML = ' ’; // & #x25BA
   this.title = 'play’;
   video.pause(); 
}

这个逻辑的问题是,我们完全依赖我们自己的脚本来决定播放/暂停按钮的状态。如果用户能够通过原生的视频元素控制来暂停或播放视频呢(有些浏览器允许用户右击并选择播放和暂停视频)?另外,当视频结束时,播放/暂停按钮仍然会显示一个暂停图标。最终,我们需要我们的控件始终与视频的状态相关。

丰富的媒体元素

媒体元素引发了一系列广泛的事件:当播放开始时,当视频加载完毕时,如果音量改变了,等等。因此,回到我们的自定义播放/暂停按钮,我们剥离脚本中涉及改变其可见标签的部分:

if (video.ended) {
   video.currentTime = 0; 
} 
if (video.paused) {
   video.play(); 
} else {
   video.pause(); 
} // which could be written as: video[video.paused ? 'play’ : 'pause’]();

在简化的代码中,如果视频已经结束,我们就重置它,然后根据其当前状态切换播放。控件本身的标签是由单独的(匿名)函数更新的,我们将其直接挂在视频元素的事件处理程序中:

video.addEventListener('play’, function () { 
   play.title = 'pause’; 
   play.innerHTML = ';
}, false);

video.addEventListener('pause’, function () { 
   play.title = 'play’; 
   play.innerHTML = ';
}, false); 

video.addEventListener('ended’, function () { 
   this.pause(); 
}, false);

现在,每当视频被播放、暂停或达到结束时,与相关事件相关的函数就会被触发,以确保我们的控件显示正确的标签。

现在我们正在处理播放和暂停,我们想向用户显示视频已经下载了多少,因此有多少是可以播放的。这将是可用的缓冲视频的数量。我们还想捕捉到显示视频播放量的事件,这样我们就可以将我们的视觉滑块移动到适当的位置,以显示我们在视频中停留了多长时间。最后,也是最重要的一点,我们需要捕捉到表示视频可以播放的事件,也就是说,有足够的视频数据可以开始观看。

seekable content

监控下载进度

媒体元素有一个 "进度 "事件,一旦媒体被获取,但有可能在媒体被处理之前就启动了。当这个事件发生时,我们可以读取视频。 seekable对象,它有一个长度、start()和end()方法。我们可以使用下面的代码更新我们的寻路条(其中缓冲区变量是显示我们可以寻路和已经下载的视频的数量的元素):

video.addEventListener('progress’, updateSeekable, false);
function updateSeekable() {
   var endVal = this.seekable && this.seekable.length ? this.seekable.end() : 0;
   buffer.style.width = (100 / (this.duration || 1) * endVal) + '%’; 
}

该代码与进度事件绑定,当它启动时,它得到了可以播放的视频与视频长度的百分比。注意,关键词this指的是视频元素,因为那是将执行updateSeekable 函数的上下文,而持续时间属性是媒体的长度,单位是秒。

然而,在Firefox的视频元素中有时会有一个微妙的问题,导致video.seekable.end() 值与持续时间不一致。或者说,一旦媒体被完全下载和处理,最终的持续时间与video.seekable.end() 的值不一致。为了解决这个问题,我们也可以使用相同的updateSeekable函数来监听持续时间变化事件。这样,如果持续时间在最后一次处理事件后确实发生了变化,持续时间变化事件就会触发,我们的缓冲区元素就会有正确的宽度:

video.addEventListener('durationchange’, updateSeekable, false); 
video.addEventListener('progress’, updateSeekable, false); 
function updateSeekable() {
   buffer.style.width = (100 / (this.duration || 1) *
   (this.seekable && this.seekable.length ? this.seekable.end() : 0)) + '%’; 
}

当媒体文件准备好播放时

当你的浏览器第一次遇到页面上的视频(或音频)元素时,媒体文件还没有准备好被播放。浏览器需要下载视频(或音频),然后对其进行解码,以便播放。一旦完成,媒体元素将触发canplay事件。通常情况下,这时你会初始化你的控件并删除任何 "加载 "指示器。因此,我们初始化控件的代码通常看起来像这样。

video.addEventListener('canplay’, initialiseControls, false);

这里没有什么非常令人兴奋的东西。控件的初始化使播放/暂停的切换按钮生效,并重置寻道栏中的播放头。

与加载有关的事件按以下顺序发生。loadstart,durationchange,loadeddata,progress,canplay,canplaythrough

然而,有时这个事件不会立即启动(或至少在你期望它启动的时候)。有时,视频暂停下载是因为浏览器试图为你节省下载太多。如果你在期待canplay事件,这可能是一个令人头痛的问题,除非你给媒体元素来点刺激,否则它不会启动。因此,我们已经开始监听loadeddata事件。这说明有一些数据已经被加载,虽然不是所有的数据。这意味着元数据是可用的(高度、宽度、持续时间等等)和一些媒体内容,但不是全部。通过允许用户在loadeddata启动时开始播放视频,它迫使Firefox等浏览器从暂停状态转为下载其余的媒体内容,使其能够播放整个视频。所以,事实上,事件周期中启用用户界面的正确时间点是loadeddata。

video.addEventListener('loadeddata’, initialiseControls, false);

预加载元数据

媒体元素最近新增的一个属性是预加载属性(非常新,以至于现在浏览器不支持)。它允许开发者告诉浏览器只下载关于媒体元素的头信息,这将包括元数据。如果浏览器真的支持这个属性,那么如果你想激活媒体的持续时间和滑块控制,我们就应该监听loadmetadata事件而不是loadeddata事件。

快进、慢动作和倒退

该规范提供了一个属性,即playbackRate。默认情况下,假定playbackRate是1 ,意味着以媒体文件的固有速度正常播放。增加这个属性可以加快播放速度;减少这个属性可以减慢播放速度。负值表示视频将反向播放。

不是所有的浏览器都支持playbackRate(现在只有基于WebKit的浏览器支持),所以如果你需要支持快进和倒退,你可以通过编程改变currentTime来解决这个问题。

function speedup(video, direction) {
   if (direction == undefined) direction = 1; // or -1 for reverse
   if (video.playbackRate != undefined) { 
      video.playbackRate = direction == 1 ? 2 : -2; 
   } else { // do it manually
      video.setAttribute('data-playbackRate’, setInterval ((function playbackRate () { 
         video.currentTime += direction; 
         return playbackRate; // allows us to run the function once and setInterval
      })(), 500)); 
   } 
}

function playnormal(video) { 
   if (video.playbackRate != undefined) { 
      video.playbackRate = 1; 
   } else { // do it manually clearInterval(video.getAttribute('data-playbackRate’)); } 
}

从前面的例子可以看出,如果支持playbackRate,你可以设置正数和负数来控制播放的方向。除了能够使用playbackRate进行倒退和快进之外,你还可以使用一个分数,以慢动作播放媒体,使用video.playbackRate = 0.5 ,其播放速度是正常速度的一半。


多媒体可及性

我们已经谈到了视频元素的键盘可及性,但是多媒体的文字记录、字幕呢?毕竟,视频或音频没有像<img> 那样的alt属性。标签之间的回退内容只适用于无法处理原生视频的浏览器;而不适用那些浏览器可以显示媒体,但由于残疾或情况(例如,在嘈杂的环境中或需要节约带宽)而无法看到或听到媒体的人。

HTML5多媒体无障碍性的理论是非常好的。原作者应该制作一个字幕文件,并将其与多媒体文件一起放在容器Ogg或MP4文件中,浏览器将提供一个用户界面,用户可以据此获得这些说明或字幕。即使视频被 "嵌入 "到1000个不同的网站上(仅仅通过使用外部URL作为视频/音频元素的来源),这些网站也能免费获得字幕信息,因此我们可以获得 "一次写入,到处阅读 "的可访问性。

为了做到这一点,你可以使用连接到WebVTT文件的<track> :

<track kind=captions src=captions.vtt />

你可以把它放在一个<video> 元素里面,如果你有多个不同语言的版本,可以添加一个srclang 属性。

data-* 属性 (自定义数据属性)

HTML5允许任何元素上的自定义属性。这些可以用来向本地脚本传递信息。

以前,为了在你的标记中存储自定义数据,作者会做一些恼人的事情,比如使用类:<input class="spaceship shields-5 lives-3 energy-75"> 。然后你的脚本就需要浪费时间去抓取这些类的名字,比如shields-5 ,在分隔符(在这个例子中是连字符)处将它们分割开来提取值。在他的书《PPK论JavaScript》(New Riders,ISBN 0321423305)中,Peter Paul Koch解释了如何做到这一点,以及为什么他选择在一些HTML4页面中使用自定义属性,使JavaScript更精简,更容易编写,但也使该页面在技术上无效。由于使用data-shields=5 向脚本传递名/值对要容易得多,HTML5使这种有用的、真实世界的做法合法化和标准化。

我们使用的是data-begindata-end ;它们也可以合法地称为data-startdata-finish ,或者(在不同类型的视频中)data-ooh-matrondata-slapandtickle 。就像选择类或ID名称一样,你应该选择一个与语义相匹配的名称。

自定义数据属性只是为了将信息传递给网站自己的脚本,对于这种情况,没有更合适的属性或元素。

规范说:"这些属性不打算让独立于使用这些属性的网站的软件使用",因此不打算向爬虫或第三方分析器传递信息。那是微格式、微数据或RDFa的工作。

当浏览器完全支持data-* 属性时,JavaScript可以使用element.dataset.foo(其中data-foo属性包含值)访问这些属性。支持可以通过扩展HTMLElement对象用JavaScript来模拟,这在IE9 alpha release及以下版本中通常是不可能的,你可以在这里看到。否则,脚本可以通过get/setAttribute 方法访问这些值。与setAttribute 相比,dataset 属性的优势在于它可以被枚举,而且,在浏览器中完全实现后,设置dataset 属性会自动设置元素上的内容属性,给你一个设置自定义数据的速记语法。

欲了解更多信息,请参见该规范


总结

您已经看到了HTML5如何为您提供了第一个可靠的第三方插件替代方案。目前,不兼容的编解码器支持使其比使用插件更难在页面中简单地嵌入视频并使其跨浏览器工作。

从好的方面看,由于视频和音频现在是浏览器原生支持的常规元素(而不是一个 "黑盒子 "插件),并提供强大的API,它们非常容易通过JavaScript来控制。只需一点网络标准知识,开发者就可以轻松地建立他们自己的自定义控件,或者只用几行代码就可以进行各种疯狂的视频操作。作为无法应对的浏览器的安全网,我们建议你也在元素之外添加下载视频文件的链接。

现在已经有一些现成的脚本,可以让您在自己的页面中轻松利用HTML5的协同作用,而不必自己编写所有代码。Kaltura播放器是一个开源的视频播放器,可以在所有的浏览器中使用。jPlayer是一个非常自由授权的jQuery音频播放器,在传统的浏览器中可以降级为Flash,可以用CSS进行样式设计,并可以扩展到允许播放列表。

用JavaScript访问视频,不仅仅是编写新的播放器。在下一章中,你将学习如何操作本地媒体元素,以获得一些真正惊人的效果。或者至少,我们的头在屏幕上跳来跳去--谁能想象有什么比这更惊人的呢?