整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          HTML5 Video(視頻)

          多站點(diǎn)都會(huì)使用到視頻. HTML5 提供了展示視頻的標(biāo)準(zhǔn)。

          檢測您的瀏覽器是否支持 HTML5 視頻:

          檢測

          Web站點(diǎn)上的視頻

          直到現(xiàn)在,仍然不存在一項(xiàng)旨在網(wǎng)頁上顯示視頻的標(biāo)準(zhǔn)。

          今天,大多數(shù)視頻是通過插件(比如 Flash)來顯示的。然而,并非所有瀏覽器都擁有同樣的插件。

          HTML5 規(guī)定了一種通過 video 元素來包含視頻的標(biāo)準(zhǔn)方法。

          瀏覽器支持

          Internet Explorer 9+, Firefox, Opera, Chrome, 和 Safari 支持 <video> 元素.

          注意: Internet Explorer 8 或者更早的IE版本不支持 <video> 元素。

          HTML5 (視頻)- 如何工作

          如需在 HTML5 中顯示視頻,您所有需要的是:

          實(shí)例

          <video width="320" height="240" controls>

          <source src="movie.mp4" type="video/mp4">

          <source src="movie.ogg" type="video/ogg">

          您的瀏覽器不支持Video標(biāo)簽。

          </video>

          <video> 元素提供了 播放、暫停和音量控件來控制視頻。

          同時(shí)<video> 元素元素也提供了 width 和 height 屬性控制視頻的尺寸.如果設(shè)置的高度和寬度,所需的視頻空間會(huì)在頁面加載時(shí)保留。。如果沒有設(shè)置這些屬性,瀏覽器不知道大小的視頻,瀏覽器就不能再加載時(shí)保留特定的空間,頁面就會(huì)根據(jù)原始視頻的大小而改變。

          <video> 與</video> 標(biāo)簽之間插入的內(nèi)容是提供給不支持 video 元素的瀏覽器顯示的。

          <video> 元素支持多個(gè) <source> 元素. <source> 元素可以鏈接不同的視頻文件。瀏覽器將使用第一個(gè)可識(shí)別的格式:

          視頻格式與瀏覽器的支持

          當(dāng)前, <video> 元素支持三種視頻格式: MP4, WebM, 和 Ogg:

          瀏覽器MP4WebMOgg
          Internet ExplorerYESNONO
          ChromeYESYESYES
          FirefoxYESYESYES
          SafariYESNONO
          OperaYES (從 Opera 25 起)YESYES
          • MP4 = 帶有 H.264 視頻編碼和 AAC 音頻編碼的 MPEG 4 文件

          • WebM = 帶有 VP8 視頻編碼和 Vorbis 音頻編碼的 WebM 文件

          • Ogg = 帶有 Theora 視頻編碼和 Vorbis 音頻編碼的 Ogg 文件

          視頻格式

          格式MIME-type
          MP4video/mp4
          WebMvideo/webm
          Oggvideo/ogg

          HTML5 <video> - 使用 DOM 進(jìn)行控制

          HTML5 <video> 和 <audio> 元素同樣擁有方法、屬性和事件。

          <video> 和 <audio>元素的方法、屬性和事件可以使用JavaScript進(jìn)行控制.

          其中的方法有用于播放、暫停以及加載等。其中的屬性(比如時(shí)長、音量等)可以被讀取或設(shè)置。其中的 DOM 事件能夠通知您,比方說,<video> 元素開始播放、已暫停,已停止,等等。

          例中簡單的方法,向我們演示了如何使用 <video> 元素,讀取并設(shè)置屬性,以及如何調(diào)用方法。

          實(shí)例 1

          為視頻創(chuàng)建簡單的播放/暫停以及調(diào)整尺寸控件:

          播放/暫停 放大 縮小 普通

          上面的例子調(diào)用了兩個(gè)方法:play() 和 pause()。它同時(shí)使用了兩個(gè)屬性:paused 和 width。

          HTML5 Video 標(biāo)簽

          標(biāo)簽描述
          <video>定義一個(gè)視頻
          <source>定義多種媒體資源,比如 <video> 和<audio>
          <track>定義在媒體播放器文本軌跡

          照相機(jī)、留聲機(jī)誕生,解決了人們記錄影像、聲音的需求以來,人們就不斷地追求著在有限的條件下盡可能地提高這些記錄的品質(zhì),而從模擬時(shí)代過渡到數(shù)字時(shí)代以后,這方面的追求有一部分變成了在盡可能小的空間中提供盡可能好的內(nèi)容質(zhì)量,這就催生出了一系列不斷演進(jìn)著的媒體壓縮技術(shù)。

          不過這期課堂的主題尚未來到媒體編碼的歷史,在講音視頻圖像的壓縮算法進(jìn)化之路前,我們先來了解一下這些媒體內(nèi)容的載體——容器格式的進(jìn)化歷程。

          首先需要區(qū)分清楚的,就是容器格式與媒體編碼格式。

          何為容器(Container)

          對于數(shù)字媒體數(shù)據(jù)來說,容器就是一個(gè)可以將多媒體數(shù)據(jù)混在一起存放的東西,就像是一個(gè)包裝箱,它可以對音視頻數(shù)據(jù)進(jìn)行打包裝箱,將原來的兩塊數(shù)據(jù)整合到一起,也可以單單只存放一種類型的媒體數(shù)據(jù)。它就像電影膠片一樣,中央是一幀一幀的圖像,而兩旁則印有對應(yīng)的音軌。



          舉個(gè)簡單的例子,常見的MP4就是一種媒體容器格式而不是編碼格式,它里面的視頻編碼可以是現(xiàn)在最常見的AVC/H.264,也可以是它的前任H.263或者下一任——HEVC,音頻編碼可以是常見的AAC也可以是AC-3。

          另一個(gè)生僻點(diǎn)的例子:最常見的圖片格式——JPEG,它其實(shí)只是一種壓縮方式,而它的存放方式其實(shí)叫做JFIF(JPEG File Interchange Format),雖然在JPEG標(biāo)準(zhǔn)中定義了一種名為JIF(JPEG Interchange Format)的容器格式,但是因?yàn)槠淙狈δ承╆P(guān)鍵要素,造成了使用的不便而被后來第三方開發(fā)出來的JFIF容器給取代了,今天我們能夠看到的JPEG文件幾乎都是裝在JFIF容器中的。

          雖然今天我們能夠直接拿到的MP4文件里面裝的幾乎都是AVC+AAC的組合,但還是不能混淆了兩者的概念,容器就是個(gè)容器,它沒得靈魂。

          AVI: 老而彌堅(jiān)

          AVI可能是和筆者年齡相仿的朋友最早接觸的一個(gè)格式。確實(shí),它推出的時(shí)間相對較早,也是許久以前最為常見的一種容器格式。它全稱叫做音頻視頻交錯(cuò)( Audio Video Interleave),顧名思義,它就是簡單地將視頻與音頻交錯(cuò)在一起,幾幀視頻之后就是對應(yīng)的音頻段,這樣重復(fù),直到結(jié)束。



          AVI文件的結(jié)構(gòu)示意圖

          它由三部分組成,頭部、主體以及位于文件尾部的索引。頭部中含有文件的元數(shù)據(jù)(metadata),比如視頻的分辨率、碼率總幀數(shù)等信息。主體部分是媒體數(shù)據(jù)的存放區(qū),它使用了塊(chunk)的概念,將原本的視頻流和音頻流分成塊狀進(jìn)行交錯(cuò)放置,就是上面講的一段視頻一段音頻交錯(cuò)放置,而尾部則是用來放置索引,它用來記錄每個(gè)數(shù)據(jù)塊在文件中的偏移位置。



          紅框標(biāo)注為對軌道的標(biāo)識(shí)

          講到AVI,還可以聯(lián)動(dòng)一下WAV和蘋果那邊的AIFF,這些容器格式其實(shí)是同源的,來自于EA(對,就是現(xiàn)在那個(gè)做游戲的EA)為了讓不同公司開發(fā)出來的軟件之間進(jìn)行數(shù)據(jù)交換而在1985年開發(fā)出來的IFF(Interchange File Format)格式。蘋果在IFF的基礎(chǔ)上開發(fā)出了AIFF,而微軟與IBM將IFF格式使用的大端序改成小端序就成了RIFF(Resource Interchange File Format),也就是AVI、WAV這兩個(gè)容器的基本原型。




          AVI雖然老,但是因?yàn)樗詭瑸閱挝话褦?shù)據(jù)切成塊來存放的特性,使得它幾乎支持市面上幾乎所有的音視頻編碼。而它的缺點(diǎn)也有很多,首先因?yàn)樗饕谖募膊康年P(guān)系,所以它并不適合用來流傳輸;另外在容器中也沒有時(shí)間戳,只能通過幀數(shù)和幀率信息來進(jìn)行計(jì)算,在索引里面并沒有寫明時(shí)間戳—媒體位置的數(shù)據(jù),所以要在播放AVI時(shí)進(jìn)行快速跳轉(zhuǎn)還需要額外的技術(shù)手段;而媒體數(shù)據(jù)分塊存放也使得它對很多使用運(yùn)動(dòng)預(yù)測特性的視頻編碼的支持并不是太好,因?yàn)檫@些幀,比如P幀和B幀,都是通過I幀進(jìn)行計(jì)算得到的,這就需要訪問當(dāng)前幀以外的數(shù)據(jù)了。

          MPEG-PS:VCD、DVD的功臣

          用電腦播放過VCD的朋友一定還記得會(huì)在目錄里尋找那個(gè)最大的.DAT文件來播放,而DVD則是找那個(gè)最大的.VOB。其實(shí)這兩個(gè)格式都是MPEG-PS容器規(guī)范的一種,此PS非彼Photoshop,而是指Program Stream,是MPEG組織在1993年發(fā)布的一個(gè)容器標(biāo)準(zhǔn),并且隨后寫入ISO/IEC國際標(biāo)準(zhǔn),除了以上兩種后綴名之外,還有.mpg也用的是這個(gè)標(biāo)準(zhǔn)。

          MPEG-PS標(biāo)準(zhǔn)中引入了包的概念,整個(gè)文件由一個(gè)個(gè)包組成,每個(gè)包的大小并不相等,包里面含有這個(gè)包的時(shí)間碼以及對應(yīng)的音視頻數(shù)據(jù)。

          MPEG-PS已經(jīng)隨著時(shí)代的進(jìn)步被廢棄了,它只能存放MPEG-1、MPEG-2、MPEG-4這些出自同門的視頻編碼,限制性較大。但因?yàn)閂CD和DVD的廣泛流行,實(shí)際上它還是被用的相當(dāng)多的。

          MPEG-TS:專為流傳輸而生

          MPEG組織不僅僅為音視頻文件的存儲(chǔ)制定了容器標(biāo)準(zhǔn),還早早地順應(yīng)時(shí)代潮流,為它們的傳輸準(zhǔn)備了相應(yīng)的容器。我們的數(shù)字電視和IPTV用的就是MPEG組織在1995年制定的Transport Stream,也就是TS容器,當(dāng)然它也并不限于這兩個(gè)場景,在現(xiàn)在的低延時(shí)直播系統(tǒng)中,MPEG-TS仍然占據(jù)了絕對主流的地位,原因就是它的整個(gè)結(jié)構(gòu)就是為了流傳輸而設(shè)計(jì)的。



          從IP層到TS包內(nèi)部的結(jié)構(gòu)

          一個(gè)TS文件中可以容納多個(gè)TS流,不同的流上面可以帶有不同的音視頻數(shù)據(jù),這樣通過接收一個(gè)TS文件,用戶方面可以自由地在這個(gè)TS文件中的多個(gè)子TS流之間進(jìn)行切換,非常適合用于傳輸電視節(jié)目。而它同時(shí)針對復(fù)雜的傳輸環(huán)境進(jìn)行了針對性的優(yōu)化,TS流的基礎(chǔ)單位是一個(gè)個(gè)大小僅為188字節(jié)的包,每個(gè)包都有自己的獨(dú)立時(shí)基,并且由于采用了固定大小,所以在傳輸過程中即使遭遇丟包也很快就可以恢復(fù)正常播放。

          發(fā)展到今天,TS仍然在網(wǎng)絡(luò)流傳輸時(shí)代中發(fā)揮著自己重要的作用,在蘋果主導(dǎo)的HLS(Http Live Streaming)協(xié)議中使用的就是TS流,它比MPEG-DASH更加通用,因?yàn)楹笳邔τ贛P4文件進(jìn)行了一定的修改,在老平臺(tái)上面支持不太好,而HLS使用的TS仍然是規(guī)范中的,可以被大多數(shù)設(shè)備兼容。

          不過也因?yàn)門S分包較多的特性,會(huì)產(chǎn)生一些數(shù)據(jù)冗余,所以在存儲(chǔ)場景中一般不會(huì)使用TS作為容器。

          M2TS:專為高清時(shí)代而生

          M2TS多見于Blu-ray光盤和高清錄像(AVCHD)中,它由MPEG-TS修改而來,加入了對于高清時(shí)代新的音視頻編解碼支持。



          一張Blu-ray視頻光盤中的M2TS

          并且由于TS文件的特性,每一個(gè)小片上都有自己的獨(dú)立時(shí)間戳,這使得文件中一部分?jǐn)?shù)據(jù)即使遭到破壞也不會(huì)影響到其他部分的正常播放,而且可以從中隨意的進(jìn)行切片操作。

          ASF:先進(jìn)卻早夭

          見過ASF格式視頻的朋友我想應(yīng)該不會(huì)太多,但是見過WMV和WMA這兩個(gè)微軟以前主推的媒體編碼格式的朋友肯定有很多。其實(shí)WMV和WMA就是存放在ASF容器之中的,它全稱高級系統(tǒng)格式(Advanced Systems Format),微軟原本計(jì)劃是用它來作為AVI容器的后繼者的,它具有諸多先進(jìn)的特性,比如說它可以包含視頻除了規(guī)格以外的元數(shù)據(jù),如導(dǎo)演、電影名這些,它也可以提供數(shù)字版權(quán)管理(DRM),還有非常好的流傳輸支持——僅需要加載文件的最小部分即可開始播放,這點(diǎn)小編感受過一次。




          ASF文件開頭會(huì)用這32個(gè)字節(jié)來標(biāo)識(shí)自己是個(gè)ASF文件

          ASF身上的這些特性在當(dāng)時(shí)還算是比較先進(jìn)的,但不過這于事無補(bǔ),微軟建立它那套封閉媒體格式體系的做法并沒有得到太多廠商和用戶的支持,大家仍然更喜歡用其他更為開放一點(diǎn)的標(biāo)準(zhǔn),比如MP3就是一個(gè)很好的例子。ASF容器也隨著微軟媒體格式的衰亡而漸漸消失了,我們今天已經(jīng)幾乎看不到WMV、WMA這兩個(gè)曾經(jīng)還很常見的格式的影子了。

          RM:昔日王者,如今不見蹤影



          與ASF差不多同時(shí)代流行的就是RM和RMVB了,在那個(gè)AVC尚未開始普及,DivX和XviD應(yīng)用較少的年代中,RMVB在國內(nèi)的各大下載站中都占據(jù)了絕對主流的地位,很多視頻站也大多使用RM來提供“網(wǎng)絡(luò)視頻點(diǎn)播”的服務(wù)。



          RM容器的內(nèi)部結(jié)構(gòu)

          不過RM容器本身并不出彩,索引仍然位于文件尾部,不過由于數(shù)據(jù)段里面有加入時(shí)間戳,所以在流傳輸時(shí)還是可以應(yīng)付用戶的跳轉(zhuǎn)操作的。因?yàn)檫@個(gè)容器本身與RM編碼息息相關(guān)的原因,它本身也只能容納RM編碼的視頻流,所以在RM編碼沒落之后我們就很少再看到這些昔日王者了,一個(gè)容器格式想要長存,要么在設(shè)計(jì)上有其獨(dú)到之處,要么就是要開放,在眾多平臺(tái)上面提供支持。而RM兩個(gè)理由都不占,效果又比不過新興的AVC,所以它的沒落也是必然了。

          FLV:前高清時(shí)代的寵兒

          還記得十年前的土豆網(wǎng)嗎?彼時(shí)它還被稱為“國內(nèi)的Youtube”,當(dāng)時(shí)視頻網(wǎng)站普遍都還在用Flash寫播放器實(shí)現(xiàn)流視頻播放,而自然而然地,Adobe制定的Flash Video格式就成了這些視頻網(wǎng)站主要使用的容器格式,也就是我們熟知的FLV。



          FLV格式是在Flash Player 6中引入的,當(dāng)時(shí)更多的是被存放在SWF文件的內(nèi)部,不過后來因?yàn)轶w積越來越大而直接獨(dú)立了出來,它的結(jié)構(gòu)相對而言比較簡單,主要分為兩塊,位于文件頭部的元數(shù)據(jù)信息和后面的音視頻數(shù)據(jù)。不過在數(shù)據(jù)的存放上面,F(xiàn)LV是將數(shù)據(jù)分為多個(gè)標(biāo)簽進(jìn)行存儲(chǔ)的,每個(gè)標(biāo)簽都帶有自己的時(shí)間戳,所以這就保證了流傳輸時(shí)的音畫同步。

          由于FLV結(jié)構(gòu)簡單但是功能足夠用,并且被Flash Player天然支持,所以在當(dāng)時(shí)的視頻網(wǎng)站上面普遍都使用它作為容器,直到今天還有很多網(wǎng)站沒有放棄它,雖然其中的視頻編碼早已升級,它也有衍生出來的F4V作為后繼者,雖然后者的血統(tǒng)已經(jīng)不是Flash家族的了。

          F4V:換了血的繼任者

          小編還記得土豆網(wǎng)在2009、2010年左右在國內(nèi)率先開始使用H.264編碼,當(dāng)時(shí)如果將清晰度切換到“高清”就會(huì)播放這些用H.264編碼的視頻。而用飛速土豆加速會(huì)緩存到一些.f4v擴(kuò)展名的文件,乍一看還以為它就是FLV,但其實(shí)不然,F(xiàn)4V其實(shí)是MP4所在的ISO標(biāo)準(zhǔn)容器家族的,但也是Adobe搞出來的FLV的后繼者。關(guān)于后者的詳情,請往下看。

          MOV:蘋果向業(yè)界作出的貢獻(xiàn)

          MOV格式的正式名字叫QuickTime File Format。看到這個(gè)QuickTime第一反應(yīng)肯定是“哦,這是蘋果的東西”。確實(shí),QuickTime File Format是由蘋果在1998年推出的,它引入了原子(atom)的概念,在QTFF格式中,atom是基本的數(shù)據(jù)單元,它可以用來容納實(shí)際的音視頻數(shù)據(jù),也可以放置元數(shù)據(jù)和字幕等文本信息,atom中所容納的數(shù)據(jù)類型和大小在每個(gè)atom的頭部進(jìn)行描述,經(jīng)過一層層的嵌套之后,整個(gè)數(shù)據(jù)文件呈現(xiàn)了一種樹狀的結(jié)構(gòu),并且保留了強(qiáng)大的可擴(kuò)展性。



          MOV和MP4這些ISO標(biāo)準(zhǔn)容器格式的開頭都有一個(gè)ftyp用于標(biāo)記格式

          MOV作為蘋果QuickTime編碼的成員,在目前仍然被蘋果設(shè)備廣泛使用著,并且對于它的支持非常好。1998年推出QTFF的同時(shí),蘋果將這個(gè)格式交給了ISO組織,后者將它標(biāo)準(zhǔn)化為國際通用容器格式,而基于這個(gè)標(biāo)準(zhǔn)衍生出來的容器,又可以叫做ISO/IEC base media file format,同時(shí)被MPEG組織采納,寫入MPEG-4 Part 12標(biāo)準(zhǔn)中。

          ISO標(biāo)準(zhǔn)容器格式

          ISO標(biāo)準(zhǔn)容器格式是一個(gè)規(guī)范,它代表符合這個(gè)規(guī)范的容器類型,而不是特指某個(gè)格式。它是由蘋果的QuickTime File Format發(fā)展而來的,在MPEG-4 Part 12中被最終確定并被ISO/IEC組織寫入標(biāo)準(zhǔn)。它雖然沒有具體實(shí)現(xiàn),但是它定義了基于時(shí)間碼的多媒體文件的通用結(jié)構(gòu),并由此成為了MP4、3GP等格式的基礎(chǔ)。



          3GP、MP4與ISO標(biāo)準(zhǔn)容器格式的關(guān)系

          MP4:標(biāo)準(zhǔn),泛用

          MP4肯定是現(xiàn)在最通用最流行的媒體容器,甚至可以說沒有之一。但其實(shí)現(xiàn)在的MP4和早期的并不是同一個(gè)標(biāo)準(zhǔn),目前常見的MP4標(biāo)準(zhǔn)是在2003年完整的的MPEG-4 Part 14規(guī)范中制定的,到今天為止也經(jīng)過了多次的修訂。它其實(shí)與MOV之間并沒有太大的區(qū)別,基本上就是把MOV的atom改了個(gè)名字,叫成box,然后加了一點(diǎn)別的佐料。



          MP4的內(nèi)部結(jié)構(gòu)

          蘋果建立iTunes Store賣數(shù)字音樂的時(shí)候選擇了AAC-LC作為他們的音頻編碼格式,而容器格式上面他們并沒有選擇與AAC-LC處于同一時(shí)代(MPEG-2)的ADTS,而是選擇了比AAC-LC大一輩的MPEG-4標(biāo)準(zhǔn)容器,也就是MP4,不過因?yàn)樗缓纛l所以我們看到的擴(kuò)展名就是.m4a,iTunes Store還賣一種只有視頻沒有音頻的MV,它用的也是MP4,擴(kuò)展名為.m4v,本質(zhì)上它們就是同一種東西。

          目前很多視頻網(wǎng)站已經(jīng)從FLV切換到MP4上面了,而且還有一種新的MPEG-DASH格式就是借助于MP4可分割的特性實(shí)現(xiàn)的,它將一整段視頻切成許多段小塊,方便瀏覽器進(jìn)行加載,減少HTTP長連接對服務(wù)器的壓力。

          這里說一句題外話,當(dāng)年某站剛上HTML5播放器的時(shí)候,因?yàn)樗麄冊瓉淼囊曨l幾乎全部都用的是FLV存儲(chǔ)的,而HTML5標(biāo)準(zhǔn)并不支持它,所以要進(jìn)行一個(gè)容器轉(zhuǎn)換,某站當(dāng)時(shí)一位非常年輕的程序員寫出了一個(gè)在瀏覽器內(nèi)實(shí)時(shí)將FLV文件轉(zhuǎn)成MP4并喂給瀏覽器的媒體播放器的腳本,名為flv.js,這個(gè)腳本可能給某站省下了非常大的格式轉(zhuǎn)換成本。不久之后這位程序員因?yàn)槭懿涣四痴镜牡托蕉x職。這件事曾經(jīng)引起了很多社區(qū)的熱烈討論,因?yàn)榻裉焓浅绦騿T日所以特地寫了這么一段。

          3GP:精簡小巧,手機(jī)最愛

          3GP是MP4的同族兄弟,一樣是基于ISO標(biāo)準(zhǔn)容器格式,用過3GP的兄弟肯定還記得這格式最多出現(xiàn)的地方是哪里——以諾基亞為代表的前智能手機(jī)時(shí)代,手機(jī)錄像出來的文件大多都是3GP格式的。

          3GP這個(gè)容器格式標(biāo)準(zhǔn)其實(shí)不是由以往的MPEG啊這類專注于多媒體編碼的組織搞出來的,而是3GPP,對沒錯(cuò)就是制定通信行業(yè)標(biāo)準(zhǔn)的那個(gè)組織制定的。它在容器支持的格式上進(jìn)行了精簡,只面向于手機(jī)可以進(jìn)行的編碼,比如MPEG-4 Visual、H.263這些比較老的視頻編碼和AMR、AAC這兩種前智能手機(jī)時(shí)代使用較多的音頻編碼。

          因?yàn)榍爸悄苁謾C(jī)時(shí)代的手機(jī)性能并不強(qiáng)大,一般也不需要支持很多種格式,不用像MP4那么全面,所以3GP最終成為了一種被廣泛支持的格式,不過也因?yàn)樗С值母袷竭^于有限,最終在智能手機(jī)時(shí)代被同門大哥MP4給取代了。

          MPEG-DASH

          面對時(shí)下流行的流媒體,MPEG組織對MP4文件進(jìn)行了魔改,由于MP4天生可以進(jìn)行無損切割的特性,DASH方式將原本媒體文件中完整的文件頭的元數(shù)據(jù)信息和片段Box中的信息抽取出來單獨(dú)寫在一個(gè)文件(MPD)中,同時(shí)還包含了片段的URL等信息,播放器可以自適應(yīng)選擇需要的片段進(jìn)行播放,在自適應(yīng)程度上面比HLS更強(qiáng)一些。(其實(shí)MPEG-DASH也可以用TS作為容器,但用MP4更多一些)



          目前MPEG-DASH已經(jīng)成為了一項(xiàng)國際標(biāo)準(zhǔn),人們比較熟悉的應(yīng)用平臺(tái)就是Youtube和Netflix,在這些平臺(tái)上面你會(huì)發(fā)現(xiàn)瀏覽器在不斷地加載一些小的視頻文件,但是視頻的播放是連續(xù)的。

          MKV:強(qiáng)大無需多言,免費(fèi)讓它受愛

          說到MKV,喜歡收藏高清電影的朋友肯定不會(huì)陌生,這種容器格式大概是和高清時(shí)代一起發(fā)展起來的,但其實(shí)它在2002年底就已經(jīng)完成制定了,不過推廣的很緩慢,到了高清時(shí)代和UHD時(shí)代人們才開始發(fā)現(xiàn)這種容器的強(qiáng)大,并用的越來越多,連微軟都在Windows 10的初始版本中加入了對它的支持。



          MKV的內(nèi)部結(jié)構(gòu)

          MKV全名Matroska,它身上最大的特點(diǎn)就是開放標(biāo)準(zhǔn)、免費(fèi)使用,而且它可能是目前地球上最強(qiáng)大的數(shù)字媒體容器格式,一個(gè)文件中可以放音頻、視頻、字幕、字體還有章節(jié)信息等等等等,前面東西都是不限數(shù)量任你放多少都可以吃得下的,而且它是目前唯一一個(gè)支持封裝ASS字幕的格式。

          值得一提的是,這玩意兒是俄羅斯組織матрёшка搞出來的,其實(shí)本身是用于盜版的,俄羅斯的網(wǎng)絡(luò)情況跟我們挺像的,網(wǎng)絡(luò)上盜版橫行,而MKV也幫助了文件的傳播,目前來看,MKV可能是眾多容器格式里面最好用的,無論是編輯元數(shù)據(jù)還是抽取軌道重新封裝都有GUI工具支持,不過可惜的是眾多視頻編輯剪輯軟件還是沒有提供對它的支持。

          總結(jié)

          其實(shí)讀到最后你會(huì)發(fā)現(xiàn),這些容器格式內(nèi)部對于音視頻數(shù)據(jù)的處理都是大同小異的,區(qū)別點(diǎn)其實(shí)并不大。更多的差距在于它們對于不同編碼格式的支持程度、元數(shù)據(jù)的詳細(xì)程度以及對于是否能夠支持音視頻以外的數(shù)據(jù)。

          而發(fā)展到至今,MP4仍然夠用,在互聯(lián)網(wǎng)時(shí)代扮演著非常重要的角色;MKV在下載黨那里被奉為圭臬;而TS格式仍然在數(shù)字電視系統(tǒng)中被廣泛使用。但在他們之前的格式也不是說非常弱或者不好,只不過可能是他們支持的那些格式?jīng)]落了順帶著把它們也帶沒了,真正像AVI那樣確實(shí)在技術(shù)規(guī)格上落伍的容器并不多。

          而對于各種容器之間無損互轉(zhuǎn)的事情,小編這里推薦mp4box、mkvtoolnix和強(qiáng)大的ffmpeg這些工具。下一篇系列課堂,我們會(huì)轉(zhuǎn)向在如今多媒體領(lǐng)域中扮演無可替代角色的視頻編碼的變遷史,并且會(huì)看一看未來的AV1和VVC這兩種對于大眾來說還很陌生的下一代視頻編碼。

          所周知,16年無疑是直播行業(yè)的春天,同時(shí)也是H5的一次高潮。

          so,到現(xiàn)在用H5技術(shù)在移動(dòng)端做網(wǎng)頁直播也是見怪不怪了,但是!!!

          今天我們的主角是webApp下播放視頻

          參考文獻(xiàn):

          1)HTML5+CSS3+JQuery打造自定義視頻播放器

          簡介

          HTML5的<video>標(biāo)簽已經(jīng)被目前大多數(shù)主流瀏覽器所支持,包括還未正式發(fā)布的IE9也聲明將支持<video>標(biāo)簽,利用瀏覽器原生特性嵌入視頻有很多好處,所以很多開發(fā)者想盡快用上,但是真正使用前還有些問題要考慮,尤其是 Opera/Firefox 和IE/Safari瀏覽器所支持的視頻編碼不同的問題,Google幾個(gè)月前發(fā)布的開源視頻編碼VP8有望能解決這一問題,另外Google還發(fā)布了開放網(wǎng)絡(luò)媒體項(xiàng)目WebM,旨在幫助開發(fā)者為開放網(wǎng)絡(luò)制作出世界級媒體格式,Opera, Firefox, Chrome和IE9都將支持VP8,而且Flash Player也將可以播放VP8,這就意味著我們很快就可以只制作一個(gè)版本的視頻然后在所有主流瀏覽器上播放了。另外一個(gè)主要的問題就是如何構(gòu)建自定義的HTML5<video>播放器,這是目前Flash Player的優(yōu)勢所在,利用Flash的IDE所提供的接口可以很方便的構(gòu)建一個(gè)個(gè)性化的視頻播放器,那HTML5的<video>標(biāo)簽要怎樣才能實(shí)現(xiàn)呢?這個(gè)問題就是本文所要解決的!我們將開發(fā)一個(gè)HTML5<video>視頻播放器的jQuery插件,并且可以很方便的進(jìn)行自定義,將分為以下幾個(gè)部分:

          1.視頻控制工具條

          2.視頻控制按鈕

          3.打包成jQuery插件

          4.外觀和體驗(yàn)

          5.自定義皮膚

          視頻控制工具條

          做為一個(gè)專業(yè)的web開發(fā)人員,我們創(chuàng)建一個(gè)視頻播放器時(shí)一定希望它的外觀在各個(gè)瀏覽器中看起來一致(consistent),但是通過下面的圖可以看到目前各個(gè)瀏覽器提供的視頻控制工具條外觀各不相同:

          那就沒辦法了,我們得自己從頭來創(chuàng)建這個(gè)控制工具條,利用HTML和CSS再加上一些圖片實(shí)現(xiàn)起來并不算很難,另外通過HTML5多媒體元素提供的API我們可以很方便將創(chuàng)建的任何按鈕與播放/暫停等事件進(jìn)行綁定。

          視頻控制按鈕

          基本的視頻控制工具條要包含一個(gè)播放/暫停按鈕,一個(gè)進(jìn)度條,一個(gè)計(jì)時(shí)器和一個(gè)音量控制按鈕,我們將這些按鈕放在<video>元素下面,并用一個(gè)div作為父容器:

          Java代碼

          1. <div class="ghinda-video-controls">

          2. <a class="ghinda-video-play" title="Play/Pause"></a>

          3. <div class="ghinda-video-seek"></div>

          4. <div class="ghinda-video-timer">00:00</div>

          5. <div class="ghinda-volume-box">

          6. <div class="ghinda-volume-slider"></div>

          7. <a class="ghinda-volume-button" title="Mute/Unmute"></a>

          8. </div>

          9. </div>

          復(fù)制代碼

          注意,我們使用元素的class屬性來代替ID屬性是為了方便在一個(gè)頁面上使用多個(gè)播放器。

          打包成jQuery插件

          創(chuàng)建好控制按鈕后我們需要配合多媒體元素的API來實(shí)現(xiàn)視頻控制的目的,正如前面提到的一樣我們將我們的播放器打包成jQuery插件,這樣可以很好的實(shí)現(xiàn)復(fù)用,代碼如下:

          Java代碼

          1. $.fn.gVideo = function(options) {

          2. // build main options before element iteration

          3. var defaults = {

          4. theme: 'simpledark',

          5. childtheme: ''

          6. };

          7. var options = $.extend(defaults, options);

          8. // iterate and reformat each matched element

          9. return this.each(function() {

          10. var $gVideo = $(this);

          11. //create html structure

          12. //main wrapper

          13. var $video_wrap = $('<div></div>').addClass('ghinda-video-player').addClass(options.theme).addClass(options.childtheme);

          14. //controls wraper

          15. var $video_controls = $('<div class="ghinda-video-controls"><a class="ghinda-video-play" title="Play/Pause"></a><div class="ghinda-video-seek"></div><div class="ghinda-video-timer">00:00</div><div class="ghinda-volume-box"><div class="ghinda-volume-slider"></div><a class="ghinda-volume-button" title="Mute/Unmute"></a></div></div>');

          16. $gVideo.wrap($video_wrap);

          17. $gVideo.after($video_controls);

          這里先假設(shè)您了解jQuery并知道如何創(chuàng)建一個(gè)jQuery插件,因?yàn)檫@個(gè)不在本文的討論范圍之內(nèi),在上面這段腳本中我們使用jQuery動(dòng)態(tài)創(chuàng)建視頻控制工具條的元素,接下來為了綁定事件我們需要獲取對應(yīng)的元素:

          Java代碼

          1. //get newly created elements

          2. var $video_container = $gVideo.parent('.ghinda-video-player');

          3. var $video_controls = $('.ghinda-video-controls', $video_container);

          4. var $ghinda_play_btn = $('.ghinda-video-play', $video_container);

          5. var $ghinda_video_seek = $('.ghinda-video-seek', $video_container);

          6. var $ghinda_video_timer = $('.ghinda-video-timer', $video_container);

          7. var $ghinda_volume = $('.ghinda-volume-slider', $video_container);

          8. var $ghinda_volume_btn = $('.ghinda-volume-button', $video_container);

          9. $video_controls.hide(); // keep the controls hidden

          這里我們通過className方式獲取,先讓工具條隱藏直到所有資源加載完成,現(xiàn)在來實(shí)現(xiàn)播放/暫停按鈕:

          Java代碼

          1. var gPlay = function() {

          2. if($gVideo.attr('paused') == false) {

          3. $gVideo[0].pause();

          4. } else {

          5. $gVideo[0].play();

          6. }

          7. };

          8. $ghinda_play_btn.click(gPlay);

          9. $gVideo.click(gPlay);

          10. $gVideo.bind('play', function() {

          11. $ghinda_play_btn.addClass('ghinda-paused-button');

          12. });

          13. $gVideo.bind('pause', function() {

          14. $ghinda_play_btn.removeClass('ghinda-paused-button');

          15. });

          16. $gVideo.bind('ended', function() {

          17. $ghinda_play_btn.removeClass('ghinda-paused-button');

          18. });

          19. 大多數(shù)瀏覽器在右鍵點(diǎn)擊視頻時(shí)會(huì)提供一個(gè)獨(dú)立的菜單,它也提供了視頻控制功能,如果用戶通過這個(gè)右鍵菜單控制視頻那就會(huì)跟我們的自定義控件沖突,所以為了避免這一點(diǎn)我們需要綁定視頻播放器自身的“播放”,“暫停”和“結(jié)束”事件,在事件處理函數(shù)中處理播放/暫停按鈕,控制按鈕的樣式。

            為了創(chuàng)建進(jìn)度條的拖動(dòng)塊,我們使用了jQuery UI的Slider組件:

            Java代碼

            1. var createSeek = function() {

            2. if($gVideo.attr('readyState')) {

            3. var video_duration = $gVideo.attr('duration');

            4. $ghinda_video_seek.slider({

            5. value: 0,

            6. step: 0.01,

            7. orientation: "horizontal",

            8. range: "min",

            9. max: video_duration,

            10. animate: true,

            11. slide: function(){

            12. seeksliding = true;

            13. },

            14. stop:function(e,ui){

            15. seeksliding = false;

            16. $gVideo.attr("currentTime",ui.value);

            17. }

            18. });

            19. $video_controls.show();

            20. } else {

            21. setTimeout(createSeek, 150);

            22. }

            23. };

            24. createSeek();

            正如你所看到的,這里我們寫了一個(gè)遞歸函數(shù),通過循環(huán)比較video的readyState屬性來判斷視頻是否已經(jīng)準(zhǔn)備好,否則我們就不能獲得視頻的時(shí)長也無法創(chuàng)建滑動(dòng)塊,當(dāng)視頻準(zhǔn)備好后我們初始化滑動(dòng)塊并顯示控制工具條,下一步我們通過綁定video元素的timeupdate事件實(shí)現(xiàn)計(jì)時(shí)器功能:

            Java代碼

            1. var gTimeFormat=function(seconds){

            2. var m=Math.floor(seconds/60)<10?"0"+Math.floor(seconds/60):Math.floor(seconds/60);

            3. var s=Math.floor(seconds-(m*60))<10?"0"+Math.floor(seconds-(m*60)):Math.floor(seconds-(m*60));

            4. return m+":"+s;

            5. };

            6. var seekUpdate = function() {

            7. var currenttime = $gVideo.attr('currentTime');

            8. if(!seeksliding) $ghinda_video_seek.slider('value', currenttime);

            9. $ghinda_video_timer.text(gTimeFormat(currenttime));

            10. };

            11. $gVideo.bind('timeupdate', seekUpdate);

            這里我們用seekUpdate函數(shù)獲取video的currentTime屬性值然后調(diào)用gTimeFormat函數(shù)進(jìn)行格式化后得到當(dāng)前播放的時(shí)間點(diǎn)。

            至于音量控制控件我們還是利用jQuery UI的Slider組件然后利用自定義函數(shù)實(shí)現(xiàn)靜音和取消靜音的功能:

            Java代碼

            1. $ghinda_volume.slider({

            2. value: 1,

            3. orientation: "vertical",

            4. range: "min",

            5. max: 1,

            6. step: 0.05,

            7. animate: true,

            8. slide:function(e,ui){

            9. $gVideo.attr('muted',false);

            10. video_volume = ui.value;

            11. $gVideo.attr('volume',ui.value);

            12. }

            13. });

            14. var muteVolume = function() {

            15. if($gVideo.attr('muted')==true) {

            16. $gVideo.attr('muted', false);

            17. $ghinda_volume.slider('value', video_volume);

            18. $ghinda_volume_btn.removeClass('ghinda-volume-mute');

            19. } else {

            20. $gVideo.attr('muted', true);

            21. $ghinda_volume.slider('value', '0');

            22. $ghinda_volume_btn.addClass('ghinda-volume-mute');

            23. };

            24. };

            25. $ghinda_volume_btn.click(muteVolume);

            26. 最后當(dāng)我們自己的自定義視頻控制工具條構(gòu)造完成后需要移除<video>標(biāo)簽的controls屬性,這樣瀏覽器默認(rèn)的工具條就被去掉了。

              好了,我們的插件功能已經(jīng)全部完成了,調(diào)用方法:

              Java代碼

              1. $('video').gVideo();

              這會(huì)將我們的插件應(yīng)用到頁面上每一個(gè)video元素上。

              外觀和體驗(yàn)

              好的,現(xiàn)在到了比較有意思的部分,也就是播放器的外觀和體驗(yàn)了。當(dāng)插件功能已經(jīng)完成后利用一點(diǎn)CSS就可以很容易地自定義樣式了,我們將全部使用CSS3來實(shí)現(xiàn)。

              首先,我們給播放器主容器加一些樣式:

              Java代碼

              1. .ghinda-video-player {

              2. float: left;

              3. padding: 10px;

              4. border: 5px solid #61625d;

              5. -moz-border-radius: 5px; /* FF1+ */

              6. -ms-border-radius: 5px; /* IE future proofing */

              7. -webkit-border-radius: 5px; /* Saf3+, Chrome */

              8. border-radius: 5px; /* Opera 10.5, IE 9 */

              9. background: #000000;

              10. background-image: -moz-linear-gradient(top, #313131, #000000); /* FF3.6 */

              11. background-image: -webkit-gradient(linear,left top,left bottombottom,color-stop(0, #313131),color-stop(1, #000000)); /* Saf4+, Chrome */

              12. box-shadow: inset 0 15px 35px #535353;

              13. }

              14. 下一步,我們設(shè)置視頻控制工具條左邊浮動(dòng)使它們水平對齊,利用CSS3的opacity和transitions我們給播放/暫停和靜音/取消靜音按鈕添加了非常不錯(cuò)的懸浮效果:

                Java代碼

                1. .ghinda-video-play {

                2. display: block;

                3. width: 22px;

                4. height: 22px;

                5. margin-right: 15px;

                6. background: url(../images/play-icon.png) no-repeat;

                7. opacity: 0.7;

                8. -moz-transition: all 0.2s ease-in-out; /* Firefox */

                9. -ms-transition: all 0.2s ease-in-out; /* IE future proofing */

                10. -o-transition: all 0.2s ease-in-out; /* Opera */

                11. -webkit-transition: all 0.2s ease-in-out; /* Safari and Chrome */

                12. transition: all 0.2s ease-in-out;

                13. }

                14. .ghinda-paused-button {

                15. background: url(../images/pause-icon.png) no-repeat;

                16. }

                17. .ghinda-video-play:hover {

                18. opacity: 1;

                19. }

                20. 如果您仔細(xì)看了前面那段根據(jù)視頻播放狀態(tài)(Playing/Paused)添加和移除播放/暫停按鈕樣式的JavaScript代碼,就會(huì)明白為什么.ghinda-paused-button為什么要重寫.ghinda-video-play的背景屬性了。

                  現(xiàn)在輪到滑動(dòng)塊了,我們進(jìn)度條和音量控制的滑動(dòng)塊的實(shí)現(xiàn)都是利用了jQuery UI的Slider組件,這個(gè)組件它本身自帶了樣式,定義在jQuery UI對應(yīng)的css文件中,但是為了使滑動(dòng)塊和播放器其他控件外觀保持一致我們?nèi)恐貙懥怂臉邮剑?/p>

                  Java代碼

                  1. .ghinda-video-seek .ui-slider-handle {

                  2. width: 15px;

                  3. height: 15px;

                  4. border: 1px solid #333;

                  5. top: -4px;

                  6. -moz-border-radius:10px;

                  7. -ms-border-radius:10px;

                  8. -webkit-border-radius:10px;

                  9. border-radius:10px;

                  10. background: #e6e6e6;

                  11. background-image: -moz-linear-gradient(top, #e6e6e6, #d5d5d5);

                  12. background-image: -webkit-gradient(linear,left top,left bottombottom,color-stop(0, #e6e6e6),color-stop(1, #d5d5d5));

                  13. box-shadow: inset 0 -3px 3px #d5d5d5;

                  14. }

                  15. .ghinda-video-seek .ui-slider-handle.ui-state-hover {

                  16. background: #fff;

                  17. }

                  18. .ghinda-video-seek .ui-slider-range {

                  19. -moz-border-radius:15px;

                  20. -ms-border-radius:15px;

                  21. -webkit-border-radius:15px;

                  22. border-radius:15px;

                  23. background: #4cbae8;

                  24. background-image: -moz-linear-gradient(top, #4cbae8, #39a2ce);

                  25. background-image: -webkit-gradient(linear,left top,left bottombottom,color-stop(0, #4cbae8),color-stop(1, #39a2ce));

                  26. box-shadow: inset 0 -3px 3px #39a2ce;

                  27. }

                  28. 這時(shí)候音量控制的滑動(dòng)塊一直顯示在音量按鈕旁邊,我們需要將它改成默認(rèn)隱藏,當(dāng)鼠標(biāo)懸浮在音量按鈕上再動(dòng)態(tài)顯示出來,使用transitions來實(shí)現(xiàn)這個(gè)效果會(huì)是個(gè)不錯(cuò)的的選擇:

                    Java代碼

                    1. .ghinda-volume-box {

                    2. height: 30px;

                    3. -moz-transition: all 0.1s ease-in-out; /* Firefox */

                    4. -ms-transition: all 0.1s ease-in-out; /* IE future proofing */

                    5. -o-transition: all 0.2s ease-in-out; /* Opera */

                    6. -webkit-transition: all 0.1s ease-in-out; /* Safari and Chrome */

                    7. transition: all 0.1s ease-in-out;

                    8. }

                    9. .ghinda-volume-box:hover {

                    10. height: 135px;

                    11. padding-top: 5px;

                    12. }

                    13. .ghinda-volume-slider {

                    14. visibility: hidden;

                    15. opacity: 0;

                    16. -moz-transition: all 0.1s ease-in-out; /* Firefox */

                    17. -ms-transition: all 0.1s ease-in-out; /* IE future proofing */

                    18. -o-transition: all 0.1s ease-in-out; /* Opera */

                    19. -webkit-transition: all 0.1s ease-in-out; /* Safari and Chrome */

                    20. transition: all 0.1s ease-in-out;

                    21. }

                    22. .ghinda-volume-box:hover .ghinda-volume-slider {

                    23. position: relative;

                    24. visibility: visible;

                    25. opacity: 1;

                    26. }

                    27. 利用一些基礎(chǔ)的CSS屬性以及CSS3提供的新屬性我們打造了一個(gè)全新的播放器外觀,它看起來是這個(gè)樣子:

                      自定義皮膚

                      可能您已經(jīng)注意到,我們在編寫插件的時(shí)候已經(jīng)定義了一些默認(rèn)選項(xiàng),它們是theme和childtheme,可以在調(diào)用插件的時(shí)候根據(jù)需要方便的應(yīng)用自定義皮膚。

                      這里解釋下theme就是所有控件的一整套樣式定義,childtheme就是在theme基礎(chǔ)上重寫某些樣式,我們在調(diào)用插件的時(shí)候可以同時(shí)指定這兩個(gè)選項(xiàng)或者其中的一個(gè):

                      Java代碼

                      1. $('video').gVideo({

                      2. childtheme:'smalldark'

                      3. });

                      我們寫了一個(gè)示例的皮膚smalldark,它只重寫了部分的樣式,顯示效果是這樣的:

                      總結(jié)

                      利用HTML5 video,JavaScript和CSS3打造自定義的視頻播放器真的非常容易,t實(shí)現(xiàn)工具條功能用JavaScrip,外觀和體驗(yàn)交給CSS3,我們得到了一個(gè)功能強(qiáng)大并且易于定制的解決方案!

                      enjoy!

                      2)mui Html5 Video 實(shí)現(xiàn)方案

                      前言: 最近項(xiàng)目中需要用到html5 視頻播放功能,于是稍微研究了解了下,遇到了很多坑,特此記錄下.

                      一、 Html5 Video

                      參考來源: http://www.xuanfengge.com/html5-video-play.html

                      (這篇博文確實(shí)幫助很大)

                      1.1、 目的

                      將Html5 Video功能應(yīng)用到實(shí)際項(xiàng)目中,針對不同的平臺(tái)和環(huán)境,進(jìn)行個(gè)性化處理。

                      基本只考慮webkit瀏覽器兼容問題

                      1.2、 Html5 Video支持格式

                      只支持: .mp4后綴(.h264編碼格式),和.webm后綴(專用web視頻格式),以及.ogg后綴(音頻文件)

                      注意: Html5 Video 可以添加多個(gè)source源來進(jìn)行兼容適配,這樣,當(dāng)?shù)谝粋€(gè)源讀取出問題時(shí)會(huì)自動(dòng)讀取下一個(gè)源. 比如可以同時(shí)在前面加上.webm和.mp4源,這樣一個(gè)出錯(cuò)時(shí)會(huì)自動(dòng)讀取另一個(gè)可用源(因?yàn)椴煌瑸g覽器,支持的格式是不一樣的)

                      但是,Hybird模式的 Android 下,有些機(jī)型只能讀取第一個(gè)source來源(測試華為和聯(lián)想都是),所以也就是說在這種情況下,要確保第一個(gè)source源是正確的

                      各大瀏覽器兼容如圖所示:

                      見圖1

                      1.3、 不同平臺(tái)環(huán)境和對應(yīng)實(shí)現(xiàn)方案

                      說明: 這里分為兩大塊,普通瀏覽器環(huán)境(pc和手機(jī),主要是移動(dòng)端,pc不做特別處理)和Hybird模式的APP環(huán)境(Android和iOS).

                      注: Html5 video可以播放本地視頻或者網(wǎng)絡(luò)視頻

                      1.3.1、 普通瀏覽器環(huán)境

                      *用Html5 Video 自帶的播放欄控件

                      *用 Video 視頻統(tǒng)一處理方法處理后,點(diǎn)擊圖片手動(dòng)隱藏圖片,設(shè)置視頻大小,手動(dòng)播放視頻.

                      注: 播放效果則由各大瀏覽器自行實(shí)現(xiàn)

                      手機(jī)端瀏覽器實(shí)現(xiàn)的不同效果,比如:

                      QQ瀏覽器(包括QQ客戶端內(nèi)置的瀏覽器):播放時(shí)會(huì)自動(dòng)進(jìn)入全屏

                      華為自帶瀏覽器: 正常小窗口播放

                      1.3.2、 Hybird App環(huán)境

                      說明: 內(nèi)聯(lián)播放是指直接在video標(biāo)簽中播放視頻,沒有必要進(jìn)入全屏

                      1.3.2.1、 Android內(nèi)聯(lián)播放

                      *用Html5 Video 自帶的播放欄控件

                      *用 Video 視頻統(tǒng)一處理方法處理后,點(diǎn)擊圖片手動(dòng)隱藏圖片,設(shè)置視頻大小,手動(dòng)播放視頻.

                      *Android內(nèi)聯(lián)播放需要注意,必須開啟硬件加速,由于有些Android手機(jī) webview是默認(rèn)關(guān)閉硬件加速的,所以必須在創(chuàng)建這個(gè)帶視頻播放的webview時(shí)手動(dòng)添加 硬件加速屬性才行.(詳情見plus創(chuàng)建webview的style)

                      style.hardwareAccelerated = true;

                      1.3.2.2、 iOS內(nèi)聯(lián)播放

                      *用Html5 Video 自帶的播放欄控件

                      *用 Video 視頻統(tǒng)一處理方法處理后,點(diǎn)擊圖片手動(dòng)隱藏圖片,設(shè)置視頻大小,手動(dòng)播放視頻.

                      *內(nèi)聯(lián)播放注意要點(diǎn),由于iOS下默認(rèn)是全屏播放的,所以需要經(jīng)過設(shè)置才能正常內(nèi)聯(lián)播放

                      第一步:在項(xiàng)目的manifest里面配置允許webview內(nèi)聯(lián)播放

                      "plus": {
                       "splashscreen": {
                       "autoclose": true,/*是否自動(dòng)關(guān)閉程序啟動(dòng)界面,true表示應(yīng)用加載應(yīng)用入口頁面后自動(dòng)關(guān)閉;false則需調(diào)plus.navigator.closeSplashscreen()關(guān)閉*/
                       "waiting": true/*是否在程序啟動(dòng)界面顯示等待雪花,true表示顯示,false表示不顯示。*/
                       },
                       "allowsInlineMediaPlayback": true,/*設(shè)置ios下允許內(nèi)聯(lián)播放*/
                       "popGesture": "close"

                      第二步: 創(chuàng)建video標(biāo)簽時(shí),手動(dòng)加上內(nèi)聯(lián)播放的屬性(iOS不支持preload)

                      <!--
                       讓ios支持內(nèi)聯(lián)播放,必須添加 webkit-playsinline 標(biāo)簽
                       -->
                       <video webkit-playsinline id="videoMedia" controls="controls" preload>

                      這樣iOS手機(jī)在播放的時(shí)候才會(huì)采用內(nèi)聯(lián)播放

                      1.3.2.3、 Android非內(nèi)聯(lián)播放

                      *通過NJS使用原生播放器來播放視頻,傳入的url可以是本地的或網(wǎng)絡(luò)的地址

                      *用 Video 視頻統(tǒng)一處理方法處理后,點(diǎn)擊圖片之后,圖片保持不變(所以沒有必要隱藏圖片),直接獲取視頻的資源地址,傳給原生播放器播放

                      注: 這種模式下,性能要比直接html5自帶播放器播放高

                      1.3.2.4、 iOS非內(nèi)聯(lián)播放

                      *用Html5 Video 自帶的播放欄控件(非內(nèi)聯(lián)播放需要去除特定內(nèi)聯(lián)屬性”webkit-playsinline”,這樣才能全屏播放)

                      if(!isInlinePlay){
                       //如果是非內(nèi)斂,ios需要去除內(nèi)聯(lián)樣式
                       mediaTarget.removeAttribute('webkit-playsinline');
                       }

                      *用 Video 視頻統(tǒng)一處理方法處理后,點(diǎn)擊圖片之后,圖片保持不變(所以沒有必要隱藏圖片),直接調(diào)用video.play()播放視頻(這時(shí)候會(huì)用一個(gè)全屏播放器來播放視頻)

                      1.3.3、 注意要點(diǎn)

                      如果采用NJS通過Android原生播放器播放視頻,目前無法監(jiān)聽到視頻的一些自定義事件.(如下載中,播放完畢,暫停,播放時(shí)間等)

                      而如果采用Html5 Video自帶播放,這些是可以通過腳本控制的.

                      所以選定方案時(shí)需要進(jìn)行衡量

                      *另外,在Html5 Video播放時(shí),無法監(jiān)聽到規(guī)定的結(jié)束事件seeked,只能在timeUpdate里面判斷,如果ended為true就代表結(jié)束了.

                      *在NJS通過Android原生播放器播放時(shí),可以通過document監(jiān)聽resume和pause事件判斷是否進(jìn)入播放和退出播放

                      1.4、 Tips

                      1.4.1、 關(guān)于Video 視頻統(tǒng)一處理的方案

                      說明: 由于將一個(gè)<Video>直接顯示在頁面中,會(huì)有各種五花八門的播放器效果,如圖:

                      (這里引用了參考來源的圖)

                      見圖2

                      顯然,體驗(yàn)效果并不好,所以現(xiàn)在的做法是用一張模擬播放的圖片來替代<Video>所在的地方,而將Video元素設(shè)置為1*1像素大小.然后給圖片設(shè)置點(diǎn)擊監(jiān)聽,監(jiān)聽到點(diǎn)擊時(shí),播放視頻.

                      注意:

                      *這里不要用{display: none}或者{width:0;height:0;}的方式,因?yàn)檫@樣視頻元素會(huì)處于未激活的狀態(tài),給后續(xù)的處理帶來麻煩.

                      *這里沒有考慮ios<6和一些低版本的Android的兼容性問題了(這些版本里,無法直接通過video.play()來播放),因?yàn)轫?xiàng)目環(huán)境基本上要求Android>4.0 iOS 7.0以上的.

                      *關(guān)于點(diǎn)擊圖片播放視頻后,如果是內(nèi)聯(lián)播放模式下(或者是普通瀏覽器),就應(yīng)該將圖片隱藏,然后將視頻大小設(shè)置為本來的大小(一般為圖片大小);如果是非內(nèi)聯(lián)播放模式(全屏模式),就沒有必要隱藏圖片了,因?yàn)閕OS下會(huì)自動(dòng)打開一個(gè)全屏播放器來播放視頻,Android下考慮到Html5 video較卡,所以也會(huì)通過NJS使用原生播放器來全屏播放視頻.

                      1.4.2、 Android NJS播放視屏的實(shí)現(xiàn)代碼

                      說明: 這個(gè)是Dcloud論壇中有人分享的

                      //非內(nèi)聯(lián)模式下的plus下的android才用到
                       var Intent = plus.android.importClass("android.content.Intent");
                       var Uri = plus.android.importClass("android.net.Uri");
                       var main = plus.android.runtimeMainActivity();
                       var intent = new Intent(Intent.ACTION_VIEW);
                       var uri = Uri.parse(url);
                       intent.setDataAndType(uri, "video/*");
                       main.startActivity(intent);

                      1.4.3、 如何讀取元素的寬高

                      *在獲取視頻的寬度時(shí),發(fā)現(xiàn)用 video.style.width無法獲取到寬度.

                      后來查了資料,發(fā)現(xiàn)dom.style.width(height)只能獲取在stye直接賦予的值.而如果是通過css樣式表賦予的值是無法直接獲取的,只能通過dom.offsetWidth(offsetHeight)獲取.

                      *設(shè)置元素寬和高是不要直接在style里設(shè)置,而是最好通過css樣式表賦予

                      *讀取元素寬和高時(shí),用offsetWidth(offsetHeight)

                      1.4.4、 關(guān)于全屏播放的問題

                      在PC端webkit瀏覽器下,全屏代碼如下:

                      進(jìn)入全屏: videoContainer(對應(yīng)的dom).webkitRequestFullscreen();

                      退出全屏: document.webkitCancelFullScreen();

                      *但是經(jīng)測試,在手機(jī)瀏覽器和Hybird模式下的手機(jī)環(huán)境中都無法使用,

                      應(yīng)該是手機(jī)瀏覽器中video 播放器的全屏模式和pc端的有區(qū)別,已經(jīng)脫離了webkit的全屏組件,而是用原生自己實(shí)現(xiàn)的.

                      1.5、 遇到問題及解決方法

                      1.5.1、 Video.currentTime 設(shè)置值時(shí)設(shè)置無效,或者變?yōu)?

                      原因分析:

                      與測試的服務(wù)器和端口有關(guān),測試環(huán)境是放在hbuild本地瀏覽器的,沒有處理好視頻快進(jìn)問題,所以會(huì)導(dǎo)致每次快進(jìn)后,視頻都會(huì)重置-在某些測試服務(wù)器上,則出現(xiàn)快進(jìn)無效,但不會(huì)重置

                      解決方法:

                      將網(wǎng)頁用其它正式服務(wù)器打開均可正常,如tomcat,wampserver,甚至直接在本地打開也行.

                      1.5.2、 無法通過代碼Video.src獲取資源路徑

                      原因分析:

                      本實(shí)例中,Video是通過source添加src的,無法直接讀取video的src

                      解決方法:

                      可以通過讀取到第一個(gè)source的標(biāo)簽,再獲取source的src

                      注:本來這個(gè)方法有一個(gè)缺點(diǎn)就是有可能第一個(gè)source的src不可用.但是由于Android中第一個(gè)source必須有用才行.否則無法正常播放.所以在確保第一個(gè)source正確的情況下能這樣用.

                      1.5.3、 部分Android機(jī)型無法退出全屏

                      描述:

                      在使用Html5 Video自帶播放器播放時(shí),部分Android機(jī)型(如聯(lián)想K860點(diǎn)擊全屏按鈕進(jìn)入全屏后,無法退出全屏-因?yàn)檫M(jìn)入全屏后,全屏按鈕不見了)

                      原因分析: 可能是手機(jī)廠商擅自劫持了瀏覽器或者篡改了瀏覽器實(shí)現(xiàn)方式

                      解決方法:

                      目前無法解決,在這類機(jī)型中,建議直接采用非內(nèi)聯(lián)模式播放或者是盡量不要手動(dòng)進(jìn)入全屏

                      3)移動(dòng)端HTML5<video>視頻播放優(yōu)化實(shí)踐

                      遇到的挑戰(zhàn)

                      移動(dòng)端HTML5使用原生<video>標(biāo)簽播放視頻,要做到兩個(gè)基本原則,速度快和體驗(yàn)佳,先來分析一下這兩個(gè)問題。

                      下載速度

                      以一個(gè)8s短視頻為例,wifi環(huán)境下提供的高清視頻達(dá)到1000kbps,文件大小大約1MB;非wifi環(huán)境下提供的低碼率視頻是500kbps左右,文件大小大約500KB;參考QzoneTouch多普勒測速,2g網(wǎng)絡(luò)的平均速度是14KB/s,那么下載一個(gè)低碼率視頻耗時(shí)35s;那么要想流暢播放視頻,就需要一個(gè)加載等待的過程,這個(gè)過程要有明確的反饋,不能讓用戶有“壞掉了”的感覺。

                      多普勒測速數(shù)據(jù)參考

                      #dns(s)conn(s)rtt(s)tran(kb/s)
                      2g3.857852.334822.5747814.0374
                      3g1.606430.7431090.60804760.1967
                      wifi0.9869210.5502080.44433270.8728

                      用戶體驗(yàn)

                      視頻是否可以自動(dòng)播放,是否能循環(huán)播放,是否能顯示下載進(jìn)度,播放的時(shí)候如何隱藏控制條,暫停的時(shí)候又能顯示出來呢。這些問題看上去貌似簡單,但是由于PC/iOS/Android這些不同平臺(tái)、不同的瀏覽器內(nèi)核、甚至相同內(nèi)核的不同版本,所實(shí)現(xiàn)的<video>屬性、方法和事件差異較大,解決兼容性問題又給開發(fā)造成了很大困擾。

                      分析原因

                      事件差異

                      下面是播放一個(gè)短視頻,在不同平臺(tái)觸發(fā)事件和獲取屬性的差異表現(xiàn)。

                      PC

                      #eventreadyStatecurrentTime (s)buffered (s)duration (s)視頻狀態(tài)
                      1loadstartNOTHING0
                      2suspendNOTHING0
                      3playNOTHING0
                      4waitingNOTHING0
                      5durationchangeMETADATA05.357.91獲取到視頻長度
                      6loadedmetadataMETADATA00.667.91獲取到元數(shù)據(jù)
                      7loadeddataENOUGHDATA00.667.91
                      8canplayENOUGH_DATA00.667.91
                      9playingENOUGH_DATA00.667.91開始播放
                      10canplaythroughENOUGH_DATA00.667.91可以流暢播放
                      11progressENOUGH_DATA0.113.687.91持續(xù)下載
                      12timeupdateENOUGH_DATA0.144.447.91播放進(jìn)度變化
                      23progressENOUGH_DATA1.777.917.91下載完畢
                      24suspendENOUGH_DATA1.777.917.91
                      25timeupdateENOUGH_DATA1.97.917.91繼續(xù)播放中
                      48timeupdateENOUGH_DATA7.77.917.91
                      49timeupdateENOUGH_DATA07.917.91
                      50seekingMETADATA07.917.91
                      51waitingMETADATA07.917.91
                      52timeupdateENOUGH_DATA07.917.91
                      53seekedENOUGH_DATA07.917.91播放完畢進(jìn)度回到起點(diǎn)
                      54canplayENOUGH_DATA07.917.91
                      55playingENOUGH_DATA07.917.91循環(huán)播放
                      56canplaythroughENOUGH_DATA07.917.91
                      57timeupdateENOUGH_DATA0.197.917.91

                      iOS

                      #eventreadyStatecurrentTime (s)buffered (s)duration (s)視頻狀態(tài)
                      1loadstartNOTHING0
                      2playNOTHING0
                      3waitingNOTHING0
                      4durationchangeMETADATA07.91獲取到視頻長度
                      5loadedmetadataMETADATA07.91獲取到元數(shù)據(jù)
                      6loadeddataENOUGHDATA07.91
                      7canplayENOUGH_DATA07.917.91
                      8canplaythroughENOUGH_DATA07.917.91可以流暢播放
                      9playingENOUGH_DATA07.917.91開始播放
                      10progressENOUGH_DATA07.917.91下載完畢
                      11suspendENOUGH_DATA07.917.91
                      12timeupdateENOUGH_DATA0.027.917.91播放進(jìn)度變化
                      43timeupdateENOUGH_DATA7.87.917.91
                      44timeupdateENOUGH_DATA07.917.91
                      45seekedENOUGH_DATA07.917.91播放完畢進(jìn)度回到起點(diǎn)
                      46timeupdateENOUGH_DATA0.227.917.91循環(huán)播放

                      Android

                      #eventreadyStatecurrentTime (s)buffered (s)duration (s)視頻狀態(tài)
                      1loadstartNOTHING0
                      2playNOTHING0
                      3waitingNOTHING00
                      4durationchangeENOUGH_DATA000
                      5durationchangeENOUGH_DATA007.91獲取到視頻長度
                      6loadedmetadataENOUGH_DATA007.91獲取到元數(shù)據(jù)
                      7loadeddataENOUGHDATA007.91
                      8canplayENOUGH_DATA007.91
                      9canplaythroughENOUGH_DATA007.91
                      10playingENOUGH_DATA007.91
                      11timeupdateENOUGH_DATA007.91
                      12progressENOUGH_DATA03.577.91下載中
                      13timeupdateENOUGH_DATA0.26.897.91開始播放
                      14progressENOUGH_DATA07.917.91下載完畢
                      49timeupdateENOUGH_DATA7.797.917.91
                      50progressENOUGH_DATA7.877.917.91
                      51timeupdateENOUGH_DATA07.917.91
                      52seekingENOUGH_DATA07.917.91播放完畢進(jìn)度回到起點(diǎn)
                      53timeupdateENOUGH_DATA07.917.91
                      54seekedENOUGH_DATA07.917.91循環(huán)播放失敗卡住了
                      55progressENOUGH_DATA07.917.91
                      56stalledENOUGH_DATA07.917.91

                      一些常用且需要重點(diǎn)關(guān)注的<video>事件

                      eventiOSAndroid
                      ****************************************************************************************************************
                      play只是要播放視頻,響應(yīng)的是video.play()方法,并不代表已經(jīng)開始播放和iOS一樣,僅是響應(yīng)video.play()方法
                      durationchange會(huì)執(zhí)行一次,一定會(huì)獲取到視頻的duration可能會(huì)執(zhí)行多次,只有最后一次才能獲取到真實(shí)的duration,前面的duration都是0;但低版本Android可能獲取到的duration是0或1;(本文提到的低版本Android大部分是4.1以下)
                      canplay可以認(rèn)為是視頻元素沒有問題,可以運(yùn)行,沒有更多含義了,基本用不上同iOS
                      canplaythrough會(huì)有明確的緩沖,表示可以流暢播放了;沒有什么用,視頻仍然會(huì)卡住,數(shù)據(jù)可能還沒有開始加載;
                      playing明確表示播放開始了;依然沒有用,視頻可能并沒有開始播放;
                      progress有明確的下載,可以獲取到當(dāng)前的buffer,并且全部下載完畢后不在觸發(fā);不一定有明確的數(shù)據(jù)下載,并且全部下載完畢后依然繼續(xù)觸發(fā);
                      timeupdate會(huì)有明確的進(jìn)度變化,可以獲取到currentTime;進(jìn)度不一定變化,currentTime可能總是0,但是第一次有currentTime變化的timeupdate事件一定代表了視頻開始播放了;
                      erroriOS中會(huì)有明確的錯(cuò)誤拋出;Android中某些瀏覽器會(huì)莫名其妙的拋出error;
                      stalled網(wǎng)絡(luò)狀況不佳,導(dǎo)致視頻下載中斷;在沒有play之前,也可能會(huì)拋出該事件。

                      屬性差異

                      attributesiOSandroid
                      ****************************************************************************************************************
                      poster

                      封面圖片

                      支持,但是加載速度明顯比在<img>中要慢;不一定支持(瀏覽器廠商的實(shí)現(xiàn)標(biāo)準(zhǔn)不統(tǒng)一);
                      preload

                      預(yù)加載

                      iPhone不支持;可能支持;
                      autoplay

                      自動(dòng)播放

                      iPhone Safari中不支持,但在webview中可能被開啟;iOS開發(fā)文檔明確說明蜂窩網(wǎng)絡(luò)下不允許autoplay;可能支持;
                      loop

                      循環(huán)播放

                      支持可能支持;
                      controls

                      控制條

                      支持,但是需要開始播放了才顯示基本都支持顯示或者不顯示
                      width和height一定給出明確的屬性設(shè)置,切不能為0;如果不設(shè)置,僅僅通過CSS樣式去控制視頻大小,可能會(huì)導(dǎo)致標(biāo)簽失效。

                      其他怪異bug和不友好表現(xiàn)

                      iOSandroid
                      ******************************************************************************************************************
                      物理位置覆蓋在<video>區(qū)域上的元素,click和touch等事件會(huì)失效,比如一個(gè)<a>鏈接如果覆蓋在<video>上,那么點(diǎn)擊后沒有任何效果。
                      iOS8.0+中,單頁面播放視頻超過16個(gè),再播放的視頻全部MediaError解碼異常無法播放。
                      iPhone的Safari會(huì)彈出一個(gè)全屏的播放器來播放視頻,iPad則支持內(nèi)聯(lián)播放。iOS7+ 如果webview(比如微信)開啟了webview.allowsInlineMediaPlayback = YES;,可以通過設(shè)置webkit-playsinline屬性支持內(nèi)聯(lián)播放;支持內(nèi)聯(lián)播放,但某些廠商會(huì)用自己的播放器劫持原生的視頻播放;
                      下載視頻時(shí),會(huì)先發(fā)送一個(gè)2字節(jié)的請求來獲取視頻元數(shù)據(jù)(比如時(shí)長),然后再不斷的發(fā)送分包續(xù)傳(206)請求來下載視頻,抓包顯示請求數(shù)和請求量至少有一倍的冗余(x2),這個(gè)嚴(yán)重的bug在iOS8中有明顯的修復(fù),但是分包的206請求仍然會(huì)有冗余數(shù)據(jù)的下載,浪費(fèi)了流量。比iOS的處理方式好,沒有第一個(gè)2字節(jié)請求,沒有流量損耗;
                      低版本Android(<=4.0.4)中,<video>如果在有相對和決定定位的層中,可能會(huì)導(dǎo)致整個(gè)頁面錯(cuò)位。
                      某些瀏覽器廠商會(huì)劫持<video>,用其“自己”的播放器來播放視頻,“破壞”了產(chǎn)品本身的播放體驗(yàn),那么只能case by case的解決了。
                      加載視頻時(shí)沒有進(jìn)度提示,視覺上看不出是播放完了還是卡住了;加載視頻時(shí),大都會(huì)顯示一個(gè)自帶的loading UI(菊花)。

                      最佳實(shí)踐

                      視頻初始化

                      如果將一個(gè)<video>直接顯示在頁面中,那么就會(huì)看到各種五花八門的播放器初始效果;

                      這顯然不是一個(gè)好的視覺體驗(yàn),那么通常的做法是制作一個(gè)模擬的視頻播放視圖,比如一個(gè)封面加一個(gè)播放按鈕。

                      而真實(shí)的<video>視頻元素要隱藏起來,如何隱藏呢?最好不要用{display: none}或者{width:0;height:0;}的方式,因?yàn)檫@樣視頻元素會(huì)處于未激活的狀態(tài),給后續(xù)的處理帶來麻煩。最佳的方式是將視頻設(shè)置成1×1像素大小,放在視覺邊緣的位置。

                      1

                      2

                      3

                      4

                      5

                      <!--iOS-->

                      <video webkit-playsinline width="1"height="1"class="vplayinside notaplink"x-webkit-airplay controls loop="loop"src="<%=src%>"></video>

                      <!--Android-->

                      <video width="1"height="1"controls loop="loop"src="<%=src%>"></video>

                      自動(dòng)播放

                      autoplay的支持依賴內(nèi)核和網(wǎng)絡(luò)狀況,比如iPhone在蜂窩網(wǎng)絡(luò)下明確禁用了autoplay;

                      經(jīng)過試驗(yàn),在沒有明確的用戶操作的情況下,直接通過video.play()也是無法激活播放的;

                      并且在產(chǎn)品設(shè)計(jì)上,自動(dòng)播放也不是一個(gè)舒服的用戶體驗(yàn),所以產(chǎn)品設(shè)計(jì)上盡量避免使用自動(dòng)播放。

                      點(diǎn)擊播放

                      之前提到,視頻最好通過1px大小隱藏起來,那么這時(shí)如何觸發(fā)播放呢?

                      經(jīng)過試驗(yàn),當(dāng)在明確的用戶操作(touch、click)時(shí),通過這些用戶行為事件的回調(diào)函數(shù),用video.play()是可以觸發(fā)視頻播放的,那么能否在用戶操作后,再去同步的創(chuàng)建和播放視頻呢?答案是肯定的,這無疑是一個(gè)視頻元素初始化的最佳實(shí)踐,但是有些差異需要注意。

                      iOS6+

                      可以在用戶的touch時(shí)間中動(dòng)態(tài)創(chuàng)建并播放視頻。

                      iOS < 6

                      可以在用戶的touch時(shí)間中動(dòng)態(tài)創(chuàng)建視頻,但不能播放;要再追加一個(gè)click事件來啟動(dòng)播放;也就是說,給偽造的視頻播放按鈕同時(shí)綁定tap和click事件,在tap的時(shí)候創(chuàng)建,在之后300毫秒的click中去播放。

                      Android

                      大部分高版本Android可以像iOS6+那樣去處理,但是低版本的不行,必須要通過click事件去傳遞video.play(),為了保持兼容,最好是用幫tap和click兩個(gè)事件來分別完成視頻的初始化和播放。

                      我們還發(fā)現(xiàn),有些低版本Android中,無法通過video.play()來播放視頻,必須有真實(shí)的用戶點(diǎn)擊視頻元素才能播放;這種情況,有一個(gè)技巧就是在tap的時(shí)候初始化并放大視頻覆蓋在播放視圖中,讓300毫秒后的真實(shí)點(diǎn)擊行為穿透點(diǎn)擊在視頻元素上來實(shí)現(xiàn)播放。

                      循環(huán)播放

                      如果視頻需要循環(huán)播放,那么就增加loop屬性,是否能循環(huán)播放就看瀏覽器是否支持了,因?yàn)檫€沒有找到hack技巧來強(qiáng)制循環(huán)播放;

                      即使,在不支持循環(huán)播放的Android中,通過監(jiān)聽seeked事件知道了播放進(jìn)度到了終點(diǎn)或起點(diǎn)暫停了,此時(shí)也無法通過video.play()來讓視頻重新播放。

                      監(jiān)控下載進(jìn)度

                      如何獲取視頻時(shí)長和已經(jīng)下載的時(shí)長?

                      1

                      2

                      3

                      4

                      5

                      6

                      7

                      8

                      9

                      10

                      11

                      12

                      13

                      // 視頻時(shí)長

                      varduration=video.duration

                      // 獲取視頻已經(jīng)下載的時(shí)長

                      functiongetEnd(video){

                      varend=0

                      try{

                      end=video.buffered.end(0)||0

                      end=parseInt(end*1000+1)/1000

                      }catch(e){

                      }

                      returnend

                      }

                      progress事件表示視頻在加載,但是它的觸發(fā)頻率和時(shí)機(jī)并不規(guī)律,最佳做法是通過一個(gè)定時(shí)器去實(shí)時(shí)獲取end,當(dāng)end >= duration時(shí),表示已經(jīng)下載完畢,再終止定時(shí)器。

                      1

                      2

                      3

                      4

                      5

                      6

                      7

                      8

                      9

                      10

                      vartimer=setInterval(function(){

                      varend=getEnd(video),

                      duration=video.duration

                      if(end<duration){

                      return

                      }

                      clearInterval(timer)

                      },1000)

                      全部下載后再播放

                      假設(shè)播放短視頻,如果網(wǎng)絡(luò)不佳,會(huì)造成播放斷斷續(xù)續(xù),在iOS中這種停頓還沒有一個(gè)明確的等待提示,這不是一個(gè)好的體驗(yàn),那么是否可以將視頻全部下載完畢再播放呢?

                      在iOS中,可以在視頻剛開始下載的時(shí)候馬上暫停,此時(shí)下載還將繼續(xù),可以做一個(gè)loading的菊花告知視頻正在加載,然后等到視頻全部下載完再開始播放。

                      1

                      2

                      3

                      4

                      5

                      6

                      7

                      8

                      9

                      10

                      11

                      12

                      13

                      14

                      15

                      16

                      17

                      18

                      19

                      20

                      21

                      22

                      23

                      24

                      25

                      $(video).one('loadeddata',function(){

                      // 暫停,但下載還在繼續(xù)

                      video.pause()

                      // 啟動(dòng)定時(shí)器檢測視頻下載進(jìn)度

                      vartimer=setInterval(function(){

                      varend=getEnd(video),

                      duration=video.duration

                      if(end<duration){

                      return

                      }

                      varwidth=$(video).parent().width()

                      // 下載完了,開始播放吧

                      $(video).attr{

                      width:width,

                      height:width

                      }

                      video.play()

                      clearInterval(timer)

                      },1000)

                      })

                      緩沖播放——邊下邊播時(shí),選擇開始播放的最佳時(shí)間點(diǎn)

                      當(dāng)視頻越來越長或者網(wǎng)絡(luò)慢時(shí),等待視頻全部下載完再播放也不是好的體驗(yàn),最好能邊下邊播,緩沖到流暢狀態(tài)就開始播放,那什么時(shí)候播放才是最佳時(shí)間點(diǎn)呢?

                      在iOS中,canplaythrough事件就是這個(gè)最佳時(shí)間點(diǎn),它是通過動(dòng)態(tài)計(jì)算緩沖量和下載速度得出的視頻可以流暢播放的狀態(tài)反饋。

                      canplaythrough event: The user agent estimates that if playback were to be started now, the media resource could be rendered at the current playback rate all the way to its end without having to stop for further buffering.

                      注意:下載完再播放和緩沖播放只適用于iOS。

                      統(tǒng)計(jì)播放時(shí)間和播放次數(shù)

                      要統(tǒng)計(jì)實(shí)際的播放時(shí)間,要累加timeupdate事件變化的時(shí)間,再減去中間可能暫停的時(shí)間。

                      1

                      2

                      3

                      4

                      5

                      6

                      7

                      8

                      9

                      10

                      11

                      12

                      13

                      14

                      15

                      16

                      17

                      18

                      19

                      20

                      21

                      22

                      23

                      24

                      25

                      26

                      27

                      28

                      29

                      30

                      $video.on('playing',function(){

                      // 開始播放是打點(diǎn)

                      $video.attr('data-updateTime',+newDate())

                      })

                      $video.on('pause',function(){

                      // 暫停播放時(shí)清除打點(diǎn)

                      $video.removeAttr('data-updateTime')

                      })

                      // 累加播放時(shí)間

                      $video.on('timeupdate',function(event){

                      var$video=$(event.target),

                      updateTime=parseInt($video.attr('data-updateTime')||0),

                      playingTime=parseInt($video.attr('data-playingTime')||0),

                      times=parseInt($video.attr('data-times')||0),

                      newtimes=0,

                      video=$video.get(0),

                      duration=parseFloat($video.attr('data-duration')||0),

                      now=+newDate()

                      // 播放時(shí)間

                      playingTime=playingTime+now-updateTime

                      // 播放次數(shù)

                      newtimes=Math.ceil(playingTime/1000/duration)

                      $video.attr('data-playingTime',playingTime)

                      $video.attr('data-updateTime',now)

                      })

                      異常處理

                      對error事件做詳細(xì)的上報(bào);

                      對stalled事件做統(tǒng)計(jì)上報(bào),并提示用戶網(wǎng)絡(luò)慢等。

                      參考數(shù)據(jù)

                      微視觸屏版iOS視頻測速

                      網(wǎng)絡(luò)環(huán)境視頻碼率獲取到視頻時(shí)長

                      時(shí)間點(diǎn)(s)

                      開始流暢播放

                      時(shí)間點(diǎn)(s)

                      全部下載完畢

                      時(shí)間點(diǎn)(s)

                      視頻長度(s)
                      wifi1000kbps2.863.975.858.69
                      非wifi500kbps4.56810.628.67

                      搬好凳子看HTML

                      首先我們在HB下創(chuàng)建一個(gè)新的app項(xiàng)目,名稱為 欠債

                      新建一個(gè)video.html

                      webkit-playsinline : 在ios中,加入此屬性,可以關(guān)閉自動(dòng)全屏播放

                      object-fit:fill : 視頻充滿video容器的大小

                      詳細(xì)理由請看參考文獻(xiàn)2or3

                      在此我們向項(xiàng)目里放置一個(gè)mp4格式的視頻,視頻內(nèi)容不限,可以是小動(dòng)畫,也可以是

                      ps:要在meta中加上,否則視頻會(huì)擴(kuò)充變形哦

                      <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />

                      OK,現(xiàn)在布局已經(jīng)完成,一個(gè)視頻已經(jīng)在頁面中了

                      旁白:尼瑪,點(diǎn)了沒反應(yīng),那這怎么播放?

                      樓主:你們這群家伙看別的小視頻等個(gè)1小時(shí)都行。。。

                      旁白:一個(gè)簡單的播放器,至少要有 暫停/播放,進(jìn)度條,視頻時(shí)長,全屏等控件吧

                      樓主:來來來,不要急,先來個(gè)播放按鈕寫在video標(biāo)簽后面

                       <div class="bad-video">
                       <video class="" webkit-playsinline style="object-fit:fill;">
                       <source src='xx.mp4' type="video/mp4"></source>
                       <p>設(shè)備不支持</p>
                       <video>
                       <img src="img/play.png"/>
                       </div>

                      寫好樣式、

                       .bad-video { position: relative; overflow: hidden; background-color: #CCCCCC;
                       } 
                       .bad-video .vplay{ position: absolute; width: 15%; z-index: 99; top: 50%; left: 50%; -webkit-transform: translate(-50%, -50%); transform: translate(-50%, -50%);
                       }

                      樓主:當(dāng)當(dāng)當(dāng)

                      再在后面加一個(gè)控制條

                       <img src="img/play.png" class="vplay" /> <div class="controls">
                       <div>
                       <div class="progressBar">
                       <div class="timeBar"></div>
                       </div>
                       </div>
                       <div><span class="current">00:00</span>/<span class="duration">00:00</span></div>
                       <div><span class="fill">全屏</span></div>
                       </div>
                      .bad-video .controls { width: 100%; height: 2rem; line-height: 2rem; font-size: 0.8rem; color: white; display: block; position: absolute; bottom: 0; background-color: rgba(0, 0, 0, .55); display: -webkit-flex; display: flex;
                      }.bad-video .controls>* { flex: 1;
                      }.bad-video .controls>*:nth-child(1) { flex: 6;
                      }.bad-video .controls>*:nth-child(2) { flex: 2; text-align: center;
                      }.bad-video .controls .progressBar { margin: .75rem 5%; position: relative; width: 90%; height: .5rem; background-color: rgba(200, 200, 200, .55); border-radius: 10px;
                      }.bad-video .controls .timeBar { position: absolute; top: 0; left: 0; width: 0; height: 100%; background-color: rgba(99, 110, 225, .85); border-radius: 10px;
                      }

                      總算有個(gè)看起來像樣的了

                      旁白:樓主,可是還是不能播放啊

                      樓主:叫你別急,要不你先去擼一把,我寫好了文字@你

                      旁白:好啊,早說嘛,我先走了,記得@我

                      樓主:你走,省的我精神分裂碼兩個(gè)人的字

                      好,現(xiàn)在Html元素已經(jīng)基本上弄好啦,看起來不是那么low了


          主站蜘蛛池模板: 在线不卡一区二区三区日韩| 文中字幕一区二区三区视频播放 | 国产一区二区电影| 精品视频一区二区三区四区 | 乱精品一区字幕二区| 五十路熟女人妻一区二区| 亚洲不卡av不卡一区二区| 色妞AV永久一区二区国产AV| 亚洲乱码一区二区三区国产精品| 一区二区三区四区在线播放| 无码av中文一区二区三区桃花岛| 亚洲图片一区二区| 最美女人体内射精一区二区| 无码精品人妻一区二区三区影院| 人妻视频一区二区三区免费 | 国产日韩一区二区三区在线观看 | 国产福利电影一区二区三区久久老子无码午夜伦不 | 中文字幕一区二区三区有限公司| 3d动漫精品啪啪一区二区中文| 国产一区二区三区不卡AV| 久久精品免费一区二区三区| 国精产品一区一区三区免费视频| 国产无码一区二区在线| 相泽亚洲一区中文字幕| 伊人色综合一区二区三区| 无码精品人妻一区二区三区免费看| 久久毛片免费看一区二区三区 | 久久精品无码一区二区无码| 日本一区二区在线播放| 麻豆精品人妻一区二区三区蜜桃 | 一区二区三区日本视频| 国产一区二区在线看| 日韩毛片基地一区二区三区| 日韩在线视频一区二区三区| 亚洲人成人一区二区三区| 中文字幕无码不卡一区二区三区| 日本在线视频一区二区| 日韩人妻无码一区二区三区久久99 | 精品成人一区二区三区免费视频| 国模一区二区三区| 国产剧情国产精品一区|