原文地址: Everything You Need to Know About HTML5 Video and Audio

更新日志(未翻译):
  • Article updated 26 January 2011 — Simplified information about what video formats Opera supports, as now Linux versions handle video the same as Mac and PC. Also deleted links to Labs WebM builds, as all release versions now support it.
  • Article updated 1 July 2010 — replaced download links to our experiment WebM-enabled builds with links to Opera 10.60 (final).
  • Article updated 14th May 2010 — some minor changes made; information on codecs added to mention the VP8 codec Google have made available and the experimental VP8-supporting Opera Labs build.

介绍

最新版本的Opera浏览器已经支持了HTML5 video和audio元素。但是你是如何在使用他们呢?《HTML 5 video介绍》是一篇十分经典但仍不够深入的文章。《采用脚本化字幕的可访问HTML 5 video》则讲述的是如何在规范尚完善之前实现HTML 5 video字幕。而且,在《video标签的再次介绍》一文中,有一些信息是关于Opera浏览器对该标签的实现细节。我推荐大家把上面三篇文章读一读。

该文章旨在提供所有关于HTML 5媒介,以及相关的DOM API、事件等等的实际信息,因此呢,你可以为一些旧的浏览器通过降级的方式,实现你自己兼容良好的HTML 5播放器。

编者提醒:本文最初发表于Opera Core Concerns blog,但是我们对此文章十分欣赏,我们也深信Simon会允许我们将此文章发表于此处。

哪些被支持了?

除了以下几项,Opera浏览器支持所有标准的HTML 5视屏规范:

不支持preload属性(在规范中,autobuffer更替成了preload;Opera的DOM拥有autobuffer属性,但是暂时没有任何用途。)
  • buffered,seekable和played IDL属性总是会返回空的TimeRanges对象。
  • 设置playbackRate和defaultPlaybackRate的值,不会影响到视屏回退的速度或者方向。

当前Opera支持由VP8和Vorbis解码的WebM格式,Ogg,由Theora解码和Vorbis解码的Ogg格式,还有由PCM解码的WAVE格式 。

让我们来点实际演练

那么,我们怎么让一个video标签在HTML里面播放视频呢?首先你需要正确格式以及编码的视频。Opera当前支持Ogg/WebM格式,它们俩也是被火狐和谷歌支持的。

如果你想播放一个视频,但是它又不是Ogg/WebM格式,你需要自行地转换它。你可以使用类似于Miro的程序来搞定它。

那么现在,假定你服务器(或者本地磁盘)上,存有一个符合我们约定的视频文件,你需要在静态页面中去播放它。请在HTML中写入如下标签:

<video src='video.ogv' contrals>video not supported</video>

这个controls属性指示着浏览器提供的本地控件。如果你想通过JavaScript编写个性化的控件,你不应该考虑使用controls这个属性。因为就算开发者使用脚本设置属性让控件“不可用”,当Opera用户点击鼠标右键的时候,Opera浏览器的控件依然是可用的,所以说无论controls属性如何设置,Opera的控件一直都会出现的。

“video not supported”这句话会在不支持video元素的浏览器中出现;在实际应用中,为了降级兼容,你可以替换成指向视频的超链,或者一个用于替代的插件(例如:Flash)的object标签。

视频文件是否会播放还要依赖于你服务器的配置。当前版本的Opera要求你可播放的视频文件的形式是video/ogg(或者audio/ogg, or application/ogg, or audio/wav......)。因此,假如你发现你的视频播放不了,有可能是你的服务器根本不知道以ogv后缀名命名的文件到底是什么文件,你的服务器会默认处理成text/plain,此刻,Opera浏览器是拒绝播放该类型的文件的。这里有Apache的解决方案;在你的.htaccess文件里面加上如下一行代码:

AddType video/ogg .ogv AddType audio/ogg .oga

以上是对Ogg视频格式的配置。你也可以为.mp4格式的文件配置video/mp4。

audio元素和video元素十分相像,但是它不会播放视频,而且一些关于video仅有的特性,它是木有的。

<audio src="audio.oga" controls> audio not supported </audio>

其实你也可以通过脚本来创建audio元素和video元素。由于video是需要对视频进行渲染的,所以你需要将其放入文档节点中去显示。一个audio元素播放音乐,则是不需要加入文档节点中的,除了你需要在浏览器中显示它一些原生的控件。

这里有一个关于如何把一个video标签作为最后一个元素插入到body中的代码:

var video = document.createElement('video'); 
video.src = 'video.ogv';
video.controls = true; document.body.appendChild(video);

同样对于audio:

var audio = document.createElement('audio'); 
audio.src = 'audio.oga'; 
audio.controls = true; document.body.appendChild(audio);

这里有个方便的类构造函数Audio(),它是等效于通过createElement方法创建audio标签的,如果已经有一个需要加载的文件,他的第一个参数是等同于src属性的,此时另外要设置它的preload 属性为auto。

var audio = new Audio(); 
audio.src = 'audio.oga';
var audio = new Audio('audio.oga');

本文至此,剩余部分,我将展示的例子大部分会和video相关,而且大部分对于audio也是适用的。

但是,它并不能在Safari中运行!

Safari不支持Ogg/WebM,它支持H.264编码格式。针对当前这种编码冲突,有一些可行的方案:

把你的视频文件进行两次编码——一份是Ogg/WebM,另一份是MPEG-4。
  • 告诉那些Safari用户,让他们安装Xiph QuickTime Component。这个插件可以让video标签在Safari正常工作。
  • 当你检测到用户浏览器不支持Ogg/WebM格式时,通过Cortado Java applet来替换你的video标签。

为了把你的视频转换成MPEG-4/H.264/AAC格式,你可以利用类似HandBrake这样的插件来进行视频转换——它在Dive Into HTML5中有详细的介绍。

现在呢,假定你拥有了两个视频文件,你需要在你的代码中暴露两个文件,以便于浏览器可以播放他们所能识别的类型格式。为了解决这个,你可以使用source元素:

<video controls>
	<source src="video.ogv">
    <source src="video.mp4">
    video not supported 
</video>

此时,浏览器会先去阐释加载video.ogv,如果他搞不定它,他会尝试加载下一个source元素。如果你想节约“心爱”的带宽,你可以告诉浏览器每一个文件的MIME类型,设置之后,浏览器会按需下载它能够播放的文件。

<video controls>
	<source src="video.ogv" type="video/ogg">
    <source src="video.mp4" type="video/mp4">
    video not supported 
</video>

但是呢,这些MIME类型仅仅只是告诉你当前文件是哪一种视频格式(就像上面的Ogg或者MPEG-4)——它不会描述当前文件需要使用哪一种解码方式。打个比方,一个视频格式就像一个包含若干文件的ZIP归档;为了知道你的私人文件,你必须给这些私人文件加上一些信息,不是仅仅把它们归档成特定格式。针对video标签,我们用编码的MIME参数来达到此目的:

<video controls>
	<source src="video.ogv" type='video/ogg; codecs="theora, vorbis"'>
    <source src="video.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'>
    video not supported 
</video>

注意到咱们在编码参数中使用了双引号,这就意味着我们要在属性值最外层使用单引号。

Theora和Vorbis编码对应的参数字符串显得很简单直观,但是H.264和ACC会相对复杂一些,这是因为H.264和ACC的有不同的配置形式。上边提供的是基本配置的H.264和简单配置的ACC。这些玩意也被正式用到了YouTube,并且也被iPhone支持。更高配置的编码需要CPU去解码,但是他们却在压缩表现的更好,这将减少更少的带宽。

如果你不想去把你的视频编码成两种形式,你可以就仅仅显示一个友好提示给Safari用户。你可以放置一个任人都能看见的超链接,或者你可以当检测Ogg不支持时,弹一个对话框。第二个方案需要用到检测技术,让我来继续看看咱们应该怎么去折腾吧。

检测(分级)支持

这里有一系列的分级支持。首先,video元素可能完全不会被支持,这种情况是在使用Opera 10.10以下和IE 8以下的浏览器。这种情况下,你可以仅仅在video标签内容内加入一些将要渲染给用户看的提示语(就像上面的“video not supported”)。我们不想在这个层级上浪费时间。

其次,video标签可能会被识别,但是呢,哪些可恶的编码格式或视频格式并不兼容。Safari不支持Ogg/WebM格式,同时Opera和火狐不支持MPEG-4/H.264/AAC编码.为了检测这个,你可以通过使用媒体元素的canPlayType()方法,或者你可以使用onerror事件监听;如果一个video播放失败了,原因就是他的编码格式不被支持,此刻,error事件就被触发了。

canPlayType()方法需要传入一个MIME类型对应的字符串。这个方法会返回以下三种字符串:

一个空字符串——说明该视频格式不被支持;
  • "maybe"——说明该视频格式也许支持,但是没有确定他的编码格式;
  • "probably"——说明该视频格式和编码都是可能被支持,并不确定;

注意到,这里压根没有“yes”这种字符串——这是因为一个MIME类型并没有包含足够关于浏览器确认是否能播放某个视频的信息。比如,这个视频文件可能因为比特率太高而导致浏览器并不能去解码它。

MIME类型来自于video/ogg或者video/mp4; codecs="..."之类的字符串——就比如我们刚刚上述对服务器的配置支持MIME类型一样,还有source标签里的type属性,就是那些字符串了。

var video = document.getElementsByTagName('video')[0];
// Opera 10.50 gives “maybe” alert(video.canPlayType(‘video/ogg’));
// Opera 10.50 gives “probably” alert(video.canPlayType(‘video/ogg; codecs=”theora, vorbis”’));
/ Opera 10.50 gives “” alert(video.canPlayType(‘video/mp4’)); alert(video.canPlayType(‘video/mp4; codecs=”avc1.42E01E, mp4a.40.2”’));

如果你有一个Ogg格式的vedio,并且想去通过检测去支持他,你需要像下面那么弄:

var video = document.getElementsByTagName('video')[0];
if (video.canPlayType) { // <video>被浏览器支持了,存在canPlayType方法! 
	if (video.canPlayType('video/ogg; codecs="theora, vorbis"')) { // 也许能播放哦! 
    } else { // 视频文件格式和编码都不被支持
    // 我们回滚去操作或者检测?fallback(video)
    } 
}

注意一下:早期的HTML 5规范会在检测到不支持格式时,会返回字符串“no”,而不是空字符,这样的话会让上述代码永远都不能返回再去检测(要知道"no"在JavaScript里面强转是等值true的,而""则等值false),如果你想兼容较旧的浏览器,你必须对此做一下兼容处理,或者直接通过“maybe”或者“probably”去判断。

对于fallback方法将会从DOM里面移出video和source元素,但是仍然保留video的另外的子元素,这个方法可以像以下这样实现:

function fallback(video) { 
	while (video.firstChild) { 
    	if (video.firstChild instanceof HTMLSourceElement) {
        video.removeChild(video.firstChild); 
        } else {
        video.parentNode.insertBefore(video.firstChild, video); 
        } 
    } 
    video.parentNode.removeChild(video); 
}

另一个检测缺少解码支持的的方式是监听video标签的error事件:

<video src="video.ogv" controls onerror="fallback(this)"> video not supported </video>

但是这样做仍然不能让浏览器支持Ogg,我们可以通过使用source标签和它的onerror句柄来替换修复它。

<video controls>
<source src="video.ogv" type='video/ogg; codecs="theora, vorbis"' onerror="fallback(this.parentNode)"> 
video not supported 
</video>

此时,你可以为哪些使用Safari的用户添加一个连接到Xiph QuickTime组件的网页。

<video controls>
<source src="video.ogv" type='video/ogg; codecs="theora, vorbis"' onerror="fallback(this.parentNode)"> 
video not supported if you're using Safari, try installing <a href="http://www.xiph.org/quicktime/">XiphQT</a>
</video>

当你拥有多个source标签时,onerror事件一般会在最后一个source标签中触发:

<video controls> 
<source src="video.ogv" type='video/ogg; codecs="theora, vorbis"'> 
<source src="video.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' onerror="fallback(this.parentNode)"> video not supported 
</video>

每一个失败了的source标签都会触发一个error事件,因为他们是按自上而下的顺序触发的,当最后一个标签触发了error事件时,你可以推断所有的source标签都失败了。

回归插件

当一个视频播放失败时,如果你想尝试用一个插件来代替显示的一段提示文字,你可以使用可以播放Ogg格式的Cortado Java applet,或者你可以使用播放MP4格式的Flash(Flash的版本必须支持MPEG-4/H.264/AAC)。

当你仅仅只有一个Ogg格式的文件时,可以像这样:

<video controls> 
  <source src="video.ogv" type='video/ogg; codecs="theora, vorbis"' onerror="fallback(this.parentNode)"> 
  <object type="application/x-java-applet" width="480" height="288"> 
    <param name="archive" value="cortado-ovt-stripped-wm_r51500.jar"> 
    <param name="code" value="com.fluendo.player.Cortado.class"> 
    <param name="url" value="video.ogv"> 
    video and Java not supported   
  </object> 
</video>

当你有一个MP4的文件时,你可以像这样:

<video controls> 
  <source src="video.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' onerror="fallback(this.parentNode)"> 
  <object data="videoplayer.swf"> 
    <param name="flashvars" value="video.mp4"> 
    video and Flash not supported 
  </object> 
</video>

如果你同时拥有Ogg格式和MP4格式的文件,你可以尝试回头去嵌套这两个object标签。你可以在检测到缺少支持时构建这个动态可反馈操作的DOM标签,这样可以避免大量的冗余模板标签。html5media项目就是通过Flowplayer播放器来达到此目的的。

此刻,你的video应该是可以再所有主流浏览器中正常工作了——包括Opera 10.10 and IE,但是一定要确保Java或者Flash安装并且启用了。

<未完待续...>