大家都有在網頁中浏覽視訊的經曆,但在Html5之前,對視訊乃至音頻都還沒有一個标準。是以,在網頁中看到的視訊,都是通過第三插件的方式嵌入的,可能是QuickTime,也可能是RealPlayer 或者 Flash。浏覽器很好的整合了這些插件,你完全意識不到它們的存在。
在介紹Html5中的音視訊标簽前,我們需要了解一些概念。
1 基本概念
1.1 容器
大多數人會認為視訊檔案就是 .avi .mp4,但事實上 avi和mp4僅僅是容器的格式,它隻決定怎麼将視訊存儲起來,而不關系存儲的内容。有點類似于.zip。不管是音頻檔案或視訊檔案,實際上都隻是一個容器檔案。這點類似于壓縮了一組檔案的ZIP檔案。
視訊檔案(視訊容器)包含了音頻軌道、視訊軌道和其他一些中繼資料。視訊播放的時候,音頻軌道和視訊軌道是綁定在一起的。中繼資料包含了視訊的封面、标題、子标題、字幕等相關資訊。
主流的視訊檔案格式(容器格式):
格式 | 擴充名 |
MPEG-4 | .mp4 |
Flash視訊 | .flv |
Ogg | .ogv |
WebM | .webm |
主流的音頻檔案格式:
格式 | 擴充名 |
MPEG-3 | .mp3 |
Acc音頻 | .acc |
Ogg音頻 | .ogg |
音頻視訊交錯: 通常以.avi為擴充名
1.2 編解碼器
音頻和視訊編碼/解碼是一組算法,用來對一段特定音頻或視訊進行解碼和編碼,以便
音頻和視訊能夠播放。原始的媒體檔案體積非常巨大,如果不對其進行編碼,那麼資料量是非常驚人的,在網際網路上傳播則要耗費無法忍受的時間;如果不對其進行解碼,就無法将編碼後的資料重組為原始的媒體資料。
視訊編解碼器 | 音頻編解碼器 |
H.264 | AAC |
VP8 | MPEG-3 |
Ogg Theora | Ogg Vorbis |
H.264: 别名 MPEG-4的第十部分,由MPEG研發并于2003年标準化。它的目的支援一切裝置,無論是低帶寬低cpu,還是高帶寬高cpu 或者是兩者之間。 要做到這一點,H.264标準被分成不同的幾種配置。高配置使用了更多特性, 這會導緻在解碼過程中更加消耗CPU,但視訊檔案本身會更小,視訊效果也更好 。
裝置 | 配置 |
蘋果iphone手機 | 基本配置(BaseLine) |
正常的電視機支援 | 基本配置(BaseLine) 和 主配置(Main)兩種 |
正常的電腦支援 | 基本配置(BaseLine) 和 主配置(Main) 進階配置(high)三種 |
當然有一些編解碼器受專利的保護,有一些則是免費的,例如Ogg的Vorbis音頻編解碼器。Ogg的Theora視訊編解碼器也是可以免費使用的。而想使用H.264的話就需要支付相關的費用了。
現在的視訊編解碼器會使用各種技巧減少從一幀到另一幀過程中傳遞的資訊數量,它們不會存儲每一幀的所有資訊,而隻是存儲兩幀之間的差異資訊。編碼器也分有損和無損,無損視訊檔案一般太大,在網頁中沒有優勢,是以我們重點研究有損編解碼器。有損編解碼器中,資訊在編碼過程中丢失是無法避免的,反複的對視訊編碼會導緻其畫面不均勻。
1.3 浏覽器對于容器和編解碼器支援的情況
Browser | MP4(H.264 + AAC) | WebM(VP8 + Vorbis ) | Ogg(Theora + Vorbis) |
Internet Explorer 9 | YES | NO | NO |
Firefox 4.0 | NO | YES | YES |
Google Chrome | YES | YES | YES |
Apple Safari 5 | YES | NO | NO |
Opera 10.6 | NO | YES | YES |
更多内容可以參見:http://www.html5videoplayer.net/html5video/html5-video-browser-compatibility/。
【注意】:目前還沒有一種編解碼和容器的組合能應用于所有的浏覽器中。
1.4 處理視訊的一個流程
- 制作一個Ogg容器中使用Theora視訊和Vorbis音頻的版本
- 制作另外一個版本,使用WebM視訊容器(VP8 + Vorbis)
- 再制作一個版本,使用MP4視訊容器,并使用H.264基本配置的視訊和ACC低配的音頻
- 連結上面3個檔案到同一個video元素,并向後相容基于Flash的視訊播放器
1.5 格式轉化
工具 | 轉化 |
用 FFmpeg 制作MP4 視訊 | ffmpeg -i test.mp4 -c:v libx264 -s 1280x720 -b:v 1500k -profile:v high -level 3.1 -c:a aac -ac 2 -b:a 160k -movflags faststart OUTPUT.mp4 |
用 FFmpeg 制作 WebM 視訊 | ffmpeg -i test.mp4 -c:v libvpx -s 1280x720 -b:v 1500k -c:a libvorbis -ac 2 -b:a 160k OUTPUT.webm |
FFmpeg 制作 Ogg 視訊 | ffmpeg -i test.mp4 -c:v libtheora -s 1280x720 -b:v 1500k -c:a libvorbis -ac 2 -b:a 160k OUTPUT.ogv |
FFmpeg 制作Mp3音頻 | ffmpeg -i test.mp3 -c:a libmp3lame -ac 2 -b:a 160k OUTPUT.mp3 |
FFmpeg 制作Ogg音頻 | ffmpeg -i test.mp3 -c:a libvorbis -ac 2 -b:a 160k OUTPUT.ogg |
FFmpeg 制作ACC音頻 | ffmpeg -i test.mp3 -c:a aac -ac 2 -b:a 160k OUTPUT.aac |
2 html5标簽
2.1
Html5提供的播放視訊的标簽
- src:資源位址
- controls:該屬性定義是顯示還是隐藏使用者控制界面
2.2
Html5提供的播放音頻的标簽
- src:資源位址
- controls:該屬性定義是顯示還是隐藏使用者控制界面
2.3
2.3.1 視訊:
type='video/webm; codecs="vp8, vorbis"'
type='video/ogg; codecs="theora, vorbis"'
type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'
2.3.2 音頻:
type='audio/ogg; codecs="vorbis"'
type='audio/aac; codecs="aac"'
type='audio/mpeg'
3 video标簽的屬性
- width :視訊顯示區域的寬度,機關是CSS像素
- height :視訊展示區域的高度,機關是CSS像素
- poster :一個海報幀的URL,用于在使用者播放或者跳幀之前展示
- src : 要嵌到頁面的視訊的URL
- controls : 顯示或隐藏使用者控制界面
- autoplay : 媒體是否自動播放
- loop : 媒體是否循環播放
- muted : 是否靜音
- preload : 該屬性旨在告訴浏覽器作者認為達到最佳的使用者體驗的方式是什麼
- none: 提示作者認為使用者不需要檢視該視訊,伺服器也想要最小化通路流量; 換句話說就是提示浏覽器該視訊不需要緩存。
- metadata: 提示盡管作者認為使用者不需要檢視該視訊,不過抓取中繼資料(比如:長度)還是很合理的。
- auto: 使用者需要這個視訊優先加載;換句話說就是提示:如果需要的話,可以下載下傳整個視訊,即使使用者并不一定會用它。
- 空字元串:也就代指 auto 值。
4 audio标簽的屬性
- src
- controls
- autoplay
- loop
- muted
- preload
5 音視訊js相關屬性
5.1 音視訊共有部分:
屬性 | 說明 |
duration | 媒體總時間(隻讀) |
currentTime | 開始播放到現在所用的時間(可讀寫) |
muted | 是否靜音(可讀寫,相比于volume優先級要高) |
volume | 0.0-1.0的音量相對值(可讀寫) |
paused | 媒體是否暫停(隻讀) |
ended | 媒體是否播放完畢(隻讀) |
error | 媒體發生錯誤的時候,傳回錯誤代碼 (隻讀) |
currentSrc | 以字元串的形式傳回媒體位址(隻讀) |
5.2 視訊多的部分:
屬性 | 說明 |
poster | 視訊播放前的預覽圖檔(讀寫) |
width、height | 設定視訊的尺寸(讀寫) |
videoWidth、 videoHeight | 視訊的實際尺寸(隻讀) |
6 音視訊js相關函數
函數 | 說明 |
play() | 媒體播放 |
pause() | 媒體暫停 |
load() | 重新加載媒體 |
7 js相關事件
7.1 視訊:
事件 | 說明 |
abort | 在播放被終止時觸發,例如, 當播放中的視訊重新開始播放時會觸發這個事件。 |
canplay | 在媒體資料已經有足夠的資料(至少播放數幀)可供播放時觸發。這個事件對應CAN_PLAY的readyState。 |
canplaythrough | 在媒體的readyState變為CAN_PLAY_THROUGH時觸發,表明媒體可以在保持目前的下載下傳速度的情況下不被中斷地播放完畢。注意:手動設定currentTime會使得firefox觸發一次canplaythrough事件,其他浏覽器或許不會如此。 |
durationchange | 元資訊已載入或已改變,表明媒體的長度發生了改變。例如,在媒體已被加載足夠的長度進而得知總長度時會觸發這個事件。 |
emptied | 媒體被清空(初始化)時觸發。 |
ended | 播放結束時觸發。 |
error | 在發生錯誤時觸發。元素的error屬性會包含更多資訊。參閱Error handling獲得詳細資訊。 |
loadeddata | 媒體的第一幀已經加載完畢。 |
loadedmetadata | 媒體的中繼資料已經加載完畢,現在所有的屬性包含了它們應有的有效資訊。 |
loadstart | 在媒體開始加載時觸發。 |
mozaudioavailable | 當音頻資料緩存并交給音頻層處理時 |
pause | 播放暫停時觸發。 |
play | 在媒體回放被暫停後再次開始時觸發。即,在一次暫停事件後恢複媒體回放。 |
playing | 在媒體開始播放時觸發(不論是初次播放、在暫停後恢複、或是在結束後重新開始)。 |
progress | 告知媒體相關部分的下載下傳進度時周期性地觸發。有關媒體目前已下載下傳總計的資訊可以在元素的buffered屬性中擷取到。 |
ratechange | 在回放速率變化時觸發。 |
seeked | 在跳躍操作完成時觸發。 |
seeking | 在跳躍操作開始時觸發。 |
stalled | 在嘗試擷取媒體資料,但資料不可用時觸發。 |
suspend | 在媒體資源加載終止時觸發,這可能是因為下載下傳已完成或因為其他原因暫停。 |
timeupdate | 元素的currentTime屬性表示的時間已經改變。 |
volumechange | 在音頻音量改變時觸發(既可以是volume屬性改變,也可以是muted屬性改變)。 |
waiting | 在一個待執行的操作(如回放)因等待另一個操作(如跳躍或下載下傳)被延遲時觸發 |
7.2 音頻:
事件 | 說明 |
abort | 在播放被終止時觸發,例如, 當播放中的視訊重新開始播放時會觸發這個事件。 |
canplay | 在媒體資料已經有足夠的資料(至少播放數幀)可供播放時觸發。這個事件對應CAN_PLAY的readyState。 |
canplaythrough | 在媒體的readyState變為CAN_PLAY_THROUGH時觸發,表明媒體可以在保持目前的下載下傳速度的情況下不被中斷地播放完畢。注意:手動設定currentTime會使得firefox觸發一次canplaythrough事件,其他浏覽器或許不會如此。 |
durationchange | 元資訊已載入或已改變,表明媒體的長度發生了改變。例如,在媒體已被加載足夠的長度進而得知總長度時會觸發這個事件。 |
emptied | 媒體被清空(初始化)時觸發。 |
ended | 播放結束時觸發。 |
error | 在發生錯誤時觸發。元素的error屬性會包含更多資訊。參閱Error handling獲得詳細資訊。 |
loadeddata | 媒體的第一幀已經加載完畢。 |
loadedmetadata | 媒體的中繼資料已經加載完畢,現在所有的屬性包含了它們應有的有效資訊。 |
loadstart | 在媒體開始加載時觸發。 |
mozaudioavailable | 當音頻資料緩存并交給音頻層處理時 |
pause | 播放暫停時觸發。 |
play | 在媒體回放被暫停後再次開始時觸發。即,在一次暫停事件後恢複媒體回放。 |
playing | 在媒體開始播放時觸發(不論是初次播放、在暫停後恢複、或是在結束後重新開始)。 |
progress | 告知媒體相關部分的下載下傳進度時周期性地觸發。有關媒體目前已下載下傳總計的資訊可以在元素的buffered屬性中擷取到。 |
ratechange | 在回放速率變化時觸發。 |
seeked | 在跳躍操作完成時觸發。 |
seeking | 在跳躍操作開始時觸發。 |
stalled | 在嘗試擷取媒體資料,但資料不可用時觸發。 |
suspend | 在媒體資源加載終止時觸發,這可能是因為下載下傳已完成或因為其他原因暫停。 |
timeupdate | 元素的currentTime屬性表示的時間已經改變。 |
volumechange | 在音頻音量改變時觸發(既可以是volume屬性改變,也可以是muted屬性改變)。 |
waiting |
8 執行個體代碼
8.1 class操作函數
function addClass(node,className){
var reg=new RegExp("\\b"+className+"\\b");
if(!reg.test(node.className)){
node.className +=(" "+className);
}
}
function removeClass(node,className){
if(node.className){
var reg=new RegExp("\\b"+className+"\\b");
var classes = node.className;
node.className=classes.replace(reg,"");
if(/^\s*$/g.test(node.className)){
node.removeAttribute("class");
}
}else{
node.removeAttribute("class");
}
}
8.2 全屏實作
full.onclick=function() {
if(isFullScreen) {
isFullScreen = false
if (document.exitFullscreen) {
document.exitFullscreen();
}
else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
}
else if (document.webkitCancelFullScreen) {
document.webkitCancelFullScreen();
}
else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
} else {
isFullScreen = true
var docElm = document.documentElement;
//W3C
if (docElm.requestFullscreen) {
docElm.requestFullscreen();
}
//FireFox
else if (docElm.mozRequestFullScreen) {
docElm.mozRequestFullScreen();
}
//Chrome等
else if (docElm.webkitRequestFullScreen) {
docElm.webkitRequestFullScreen();
}
//IE11
else if (docElm.msRequestFullscreen) {
docElm.msRequestFullscreen();
}
}
}
8.3 video寫法
<video width="800" height="">
<source src="myvideo.mp4" type="video/mp4"></source>
<source src="myvideo.ogv" type="video/ogg"></source>
<source src="myvideo.webm" type="video/webm"></source>
<object width="" height="" type="application/x-shockwave-flash" data="myvideo.swf">
<param name="movie" value="myvideo.swf" />
<param name="flashvars" value="autostart=true&file=myvideo.swf" />
</object>
目前浏覽器不支援 video直接播放,點選這裡下載下傳視訊: <a href="myvideo.webm">下載下傳視訊</a>
</video>
8.4 功能點邏輯
- 播放按鈕點選時:
- 切換播放按鈕的樣式
- 控制視訊的播放暫停
- 播放:控制進度條的前進(通過開啟定時器來實作)
- 暫停:要關閉定時器不讓進度條前進
- 停止按鈕點選時:
- 切換播放按鈕的樣式
- 控制視訊暫停
- 暫停:要關閉定時器不讓進度條前進
- 進度條重置為0
- 視訊時間調整為0
- 拖拽時:根據拖拽距離控制視訊時間
- 點選進度條時:
- 根據點選位置控制視訊時間
- 預設就應該是播放操作
- 切換播放按鈕的樣式
- 控制視訊的播放
- 控制進度條的前進:通過開啟定時器來實作