【51CTO精选译文】<audio>和<video>是首批被添加到HTML 5规范中的特征标记。它们的加入使得浏览器能够以一种更易用的方式来处理音频及视频文件。
51CTO编辑推荐:HTML 5 下一代Web开发标准详解
本文作者Kurt Cagle是一位资深的多媒体应用开发者,对HTML 5规范十分关注。本文对HTML 5规范中最吸引人的<audio>和<video>功能进行了最详细的介绍。以下是Kurt文章的全文翻译。对HTML 5其他规范感兴趣的读者们,可以参考51CTO之前对HTML 5标准的全面介绍,或者也可以在HTML 5专题中寻找自己感兴趣的内容。
多年以前,当我还是程序员时,我所做的大量工作主要集中在为图形显示及电脑游戏开发多媒体应用程序(这些应用程序结合了视频、音频、动画和文字)方面。在90年代初,我主要使用的工具是Macromedia Director。在业内,一直存在基于web的音频(更不用说视频)应用程序开发的想法,直到Realnetworks的出现。RealNetworks是首次提供了较大规模的流媒体技术,从而使得开发人员可以通过Internet发送缓冲的媒体内容。后来,RealNetworks又允许将播放文件嵌入到网页之中。
从技术角度来讲,对HTML中指定的视频和音频进行标记的想法在HTML 3(甚至HTML 4)上实现起来的难度很大。因为HTML 4本质上是个“静止”版本,用于显示内容的特定机制十分依赖相应的格式(例如,苹果公司的QuickTime电影和Flash视频),并且通常需要将标记与各个参数进行捆绑后再向服务器传递相关信息。因此,将视频及音频嵌入到网页的工作变成了一种特殊的技能。
因此,将<audio>及<video>作为首批被添加到HTML 5规范中的特征标记也就变得理所当然了,而这似乎已经成为浏览器厂商实现HTML 5的首要考虑的事情。这些新加入的元素使得浏览器能够以一种易于使用的方式处理音频及视频文件,而HTML 5所提供的API还能带给用户许多帮助,从而更精确的对视频和音频进行控制。
HTML 5 的<audio>和<video>元素
在<audio>和<video>中,<audio>较为简单,表1中列出了<audio>的所有属性
表1 <audio>元素属性
属性名称 |
值的格式 |
描述 |
src |
xs:anyURI |
该属性提供媒体源的URL地址 |
autobuffer |
Autobuffer
(自动缓冲) |
在网页显示时,该二进制属性表示是由用户代理(浏览器)自动缓冲的内容,还是由用户使用相关API进行内容缓冲 |
autoplay |
Autoplay
(自动播放) |
在网页显示时,该二进制属性表示当网页完成载入后浏览器是否应该自动播放视频 |
loop |
Loop(循环) |
在网页显示时,该二进制属性表示当多媒体运行结束后浏览器是否应该自动循环播放 |
controls |
Controls
(控制) |
在网页显示时,该二进制属性表示用户代理(浏览器)是否允许用户对视频进行控制 |
注意,<audio>元素(及<video>元素)同样支持所有基于<div>的其他常规属性(如style、class等),甚至在该接口不可见时也是如此。
<video>元素除包含<audio>中所有属性外,还有额外三种属性。
表2 < Video >元素属性
属性名称 |
值的格式 |
描述 |
src |
xs:anyURI |
该属性提供媒体源的URL地址 |
autobuffer |
Autobuffer(自动缓冲) |
在网页显示时,该二进制属性表示是由用户代理(浏览器)自动缓冲的内容,还是由用户使用相关API进行内容缓冲 |
autoplay |
Autoplay(自动播放) |
在网页显示时,该二进制属性表示当网页完成载入后浏览器是否应该自动播放视频 |
loop |
Loop(循环) |
在网页显示时,该二进制属性表示当多媒体运行结束后浏览器是否应该自动循环播放 |
controls |
Controls(控制) |
在网页显示时,该二进制属性表示用户代理(浏览器)是否允许用户对视频进行控制 |
width |
dimension ###(cm|em|en|in|px|pt|%) |
该属性表示在合适的地方提供视频图像的显示宽度。当高度未指明时,其值将与给定的初始视频宽度成一定比例 |
height |
dimension ###(cm|em|en|in|px|pt|%) |
该属性表示在合适的地方提供视频图像的显示高度。当宽度未指明时,其值将与给定的初始视频高度成一定比例 |
poster |
xs:anyURI |
当视频未响应或缓冲不足时,该属性值链接到一个图像。该图像将以一定比例被显示出来 |
当视频处于缓冲状态时,Poster实际上是一个图像占位符,它并不总是必需的。当预载入视频时,许多视频编解码器会自动从视频中解压一个特殊的图片来作为poster。当然,并不是所有的编解码器(codec)都有这一功能。
当视频载入时,在特定环境下使用指定poster(放弃视频所提供的默认poster)来做为某个视频的“商标”是非常有帮助的。当视频开始播放或是暂停时,poster所显示的图片与内容是不相干的。在另一种情况中,解码器可以显示视频暂停前的最后一张图片,或者当视频持续播放时,视频的最后一帧图片将会显示出来。
通常情况下,视频和音频的播放会采用指定媒体源所压缩到媒体中的编解码器,但有时浏览器并不支持某种特殊的的编解码器。在这种情况下,可以使用@src属性作为解决方案,HTML5同时定义了第二个<source>元素,它主要的作用是定义媒体源所在的位置及媒体源播放所使用的编解码器类型。表3 列出了<source>元素的定义
表3 <Source>元素属性
属性名称 |
值的格式 |
描述 |
src |
xs:anyURI |
该属性提供媒体源的URL地址 |
type |
媒体源的隐藏类型,字符串形式 |
该属性包含了媒体源的播放隐藏类型,通常出现在视频格式中 |
media |
一个媒体编解码器的字符串 |
该字符串包含了与指定媒体源所匹配的编解码器信息 |
在多<source>元素存在的情况下,如果web浏览器不能使用第一个指定编解码器(浏览器不支持),它将会搜寻列表直到发现第一个可以使用的编解码器为止。
HTML 5代码后面所紧跟的比特描述了视频元素所支持的三种不同编解码器:
第一种情况是:如果<source>元素描述的是mp4资源(最典型的视频类型为MPEG格式,尽管它们经常是“mpg”格式的直接扩展),那么它将使用baseline profile 编解码器。第二种情况是将视频与simple profile视频编解码器一起编码,第三种情况是将视频与Ogg-vorbis编解码器一同编码。最典型的做法是,让@type属性包含关联的隐藏属性。如果它没有包含,那么@media属性可以通过@type信息来确定。注意,你在判断@src属性时可以有多种选择:即使<source>元素存在,它也会被提前使用,但你必须在你的媒体元素中选择一个。(51CTO编辑注:HTML 5标准确立的最大的争议点就是有关视频元素所支持的编解码器的问题。比如Mozilla坚持将开放的Ogg标准加入进来,而苹果则争抢着把MP4标准加入,其他公司也抱着相同的想法。这就造成了上述描写的情况。)
理论上,<video>和<audio>元素必须可以包含当前可以使用的绝大多数编解码器。但在实际过程中,当前支持<video>和<audio>元素的浏览器其实只支持开源的Ogg Vorbis 和Theora标准。你可能并不熟悉这些标准——尽管Terry Pratchett的《磁盘世界》(Diskworld)系列丛书的粉丝们也许可以从Exquisitor Vorbis(“small gods”)的特性中找到Ogg Vorbis的名字,并且(也很有可能)在他的书中多次提到 Nanny Ogg的特性。另一方面,Theora (Jones)是Max Headroom 属性调节器(controller)的名称。
与更为人熟知的MPEG格式相比,Ogg Vorbis标准是开源并且资料非常详实。因此,在为游戏及在线应用程序存储音频文件时,Ogg Vorbis格式非常受欢迎。与其他格式相比,Ogg Vorbis/Theora 并没有得到HTML 5规范所给予的更多优惠,但它是Firefox唯一支持的格式。
Chrome 和 Safari 团队均宣布有可能将两种标准都添加进来的打算。
音频,视频以及DOM
<video>及<audio>元素均使用基于抽象HTMLMediaElement (注:不包含正规<media>元素)的相同DOM接口。你可以在页面中使用这些接口来控制各种视频及音频流。例1显示了这些接口的交互式数据语言(IDL)。
从IDL中可以看出,媒体元素的API主要完成以下工作:
Src属性负责设置媒体的@src属性,但src属性的改变并不能自动改变当前视频的属性。当你改变src后,你需要调用load()函数来对新视频及其属性进行重新载入,并在视频完成载入和缓冲后调用play()。在一个纯粹的并行网络世界中,完成这个工作相对容易。当你从一个正在运行的web页面上下载媒体到本地文件时,这些代码已经开始运行了。
然而,媒体文件在本质上是一个需要较长时间的过程。当你需要同时完成载入、缓冲音频及视频文件及网络连接时,这将是一个巨大的挑战,因为这会受到很多因素的影响。由于这个原因,当我们在处理web上的音频及视频时,如果你想对该过程进行控制的话,那你就不得不采取异步工作的方式,将客户端在媒体服务器中获得的各种信息进行重新处理。表4(直接提取于HTML5文档)提供了一个各种事件以及在它们被调度时的完整信息。
表4:媒体用户接口事件
事件名称 |
接口 |
在什么时将被调度 |
前提条件 |
Loadstart
加载开始 |
Event
事件 |
浏览器开始寻找媒体数据,作为资源选择算法的一部分 |
NETWORK_LOADING
网络状态为装载状态 |
Progress
进度 |
Event
事件 |
浏览器获取媒体数据。 |
NETWORK_LOADING
网络状态为装载状态 |
Suspend
挂起 |
Event
事件 |
浏览器有意不在当前获取媒体数据,但是也不全部下载媒体资源 |
NETWORK_IDLE
网络状态为空闲状态 |
Abort
终止 |
Event
事件 |
在媒体数据完全下载完之前,浏览器停止获得媒体数据。这不能归因于一个错误的发生 |
错误是一个对象,表示媒体错误终止的MEDIA_ERR_ABORTED代码。此时,网络是处于空载状态,还是处于空闲状态,取决于什么时候下载终止 |
Error
错误 |
Event
事件 |
当取得数据时,错误发生。 |
错误是一个对象,表示媒体错误终止的MEDIA_ERR_NETWORK代码或更高层次的代码。此时,网络是处于空载状态,还是处于空闲状态,取决于什么时候下载终止 |
Emptied
空闲 |
Event
事件 |
先前网络状态不是处于空载状态的媒体要素刚刚转向了这种状态(或者是因为当下载时被报告了一个致命的错误,或者是因为当资源选择算法已经运行时,load()方法被调用,这种情况下它是与load()方法的调用同时发生的) |
网络状态为空载状态,所有的IDL属性都是初始化状态 |
Stalled
迟延 |
Event
事件 |
浏览器正在获取数据,但是数据出乎意料的没有到来 |
NETWORK_LOADING.
网络状态为装载状态 |
Play
播放 |
Event
事件 |
重新播放已经开始。当play()方法返回后,接着播放 |
暂停是最近的为假 |
Pause
暂停 |
Event
事件 |
重新播放已经被停止。当pause方法返回后,接着播放 |
暂停是最近的为真 |
Loadedmetadata
装载媒体数据 |
Event
事件 |
浏览器决定媒体资源的持续时间和尺度。 |
准备状态最近处于拥有当前的数据或第一次大于所需的数据的状态 |
Loadeddata
装载数据 |
Event
事件 |
浏览器能够归还数据当第一次处于当前重播的位置 |
准备状态最近提升到拥有的数据或第一次大于所需的数据的状态 |
Waiting
等待 |
Event
事件 |
因为下一个帧不能得到,所以重新播放被停止,但是浏览器希望这个架构在这个过程中能被得到 |
准备状态最近等于或少于当前的数据,暂停则为假。要么搜索为真,要么当前回放位置不包含在缓冲的数据中。 |
Playing
正在播放 |
Event
事件 |
回放被启动 |
准备状态最近等于或多于未来的数据,暂停则为假,搜索则为假;要么当前回放位置包含在缓冲的数据中。 |
Canplay
能够播放 |
Event
事件 |
浏览器能够继续回放媒体数据,但如果回放操作现在就开始的话,不用停下来等待进一步的缓冲,媒体资源则不能以当前的回放速率一直工作到结束 |
准备状态最近增加到未来的数据或更多 |
Canplaythrough
能够从头到尾的播放 |
Event
事件 |
浏览器如果现在就开始回放操作的话,媒体资源能以当前的回放速率一直工作,而不用停下来等待进一步的缓冲 |
准备状态最近等于足够的数据 |
Seeking
正在寻找 |
Event
事件 |
寻找IDL的属性被修改为真,搜索操作用去的时间很长。 |
|
Seeked
寻找 |
Event
事件 |
寻找IDL的属性被修改为假 |
|
Timeupdate
时间更新 |
Event
事件 |
作为正常回放的一部分,当前回放位置被改变;或是以一种有趣的方式进行回放,如间断进行 |
|
Ended
结束 |
Event
事件 |
因为到达了媒体资源的终点,所以回放被停止 |
当前的时间等同于媒体资源结束的时间;结束为真。 |
Ratechange
交换率 |
Event
事件 |
defaultPlaybackRate或是playbackRate属性已被更新。 |
|
Durationchange
持续期的交换 |
Event
事件 |
duration属性已被更新 |
|
Volumechange
卷交换 |
Event
事件 |
volume属性或是muted属性被修改。在相关属性的安装已经返回后,开始工作 |
|
在表4的所有事件中,事件canplay 和 canplaythrough是最有用的。首先,当足够的数据被视频播放器载入并开始播放时,canplay将会被使用(即便所有数据并未完全载入)。对于事件canplaythrough来说,它会在数据完全载入到浏览器缓冲区之后才会运行,这样使得视频可以流畅播放,无需因等待缺失数据而暂停。
当视频文件已经有足够的数据可以开始播放时,它将产生oncanplay事件,该事件可以点亮Play按钮。也就是说,当用户按下Play按钮时,它实际上已经在播放刚刚下载完成的视频了。
但这些仅仅在理论上是可行的。实际上,即使在firefox中,<video>和<audio>也没有完全实现。由于这个原因,很多事件的处理并没有传递到JaveScript层。这就意味着,由于这一操作很粗略,先调用load()再调用play()仍然是载入视频源的最好方式。这一领域很有可能在执行过程中(按照XHTML的标准)得到更充分的支持。