html5中video在安卓與ios實際應用中遇到的問題及解決
昨天公司指派給我了一個任務,是關於視訊播放後展示頁面的單頁應用,具體需求如下:
1)使用者在進入頁面後視訊開始自動播放,期間不得操作; 2)視訊播放完成後順滑切換到主體頁。 複製程式碼
看起來是不是特別簡單粗暴,乍一看好像也是就是不到一小時的工作量,卻讓我足足熬到了深夜兩點鐘,說起來都是淚~~。這期間遇到了不少問題,我都會在下面一一列舉(以下所說的瀏覽器均為移動端瀏覽器,不再一一標註)。
一、video的預設顯示
在我開發完基本程式碼之後,push到githook上在手機上展示時,遇到了第一個問題: 眾所周知,html中video的autoplay在移動端瀏覽器上基本失效(其一,移動端要有使用者互動才能觸發事件,如click、touch;其二,ios協議蜂窩資料下不得開啟音視訊的自動播放),所以我在載入後取巧的加了一個懸浮播放圖示,引導使用者點選開始業務流程。
但可能因為核心不同,在微信瀏覽器/safari/chrome上預設展示的poster各有不同,chrome應用了預設行為截取了視訊第一幀作為顯示,微信瀏覽器和safari卻顯示空白,效果就是孤零零的播放圖放在一張白紙上。解決方案是:通過canvas擷取視訊第一幀作為預設顯示的圖片:
var cut = function() { let canvas = document.createElement("canvas");//建立畫布 canvas.width = video.videoWidth * scale; canvas.height = video.videoHeight * scale;//設定寬高比 canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);//將視訊此刻幀數畫入畫布 let img = document.createElement("img"); img.src = canvas.toDataURL("image/png"); Dom.appendChild(img);//寫入到Dom }; video.addEventListener('loadeddata',cut);//在視訊幀數已載入時執行擷取 複製程式碼
二、video控制欄的隱藏
html文件裡寫有,如果controls屬性不出現,則預設不顯示,但其實在實際應用中,瀏覽器一般都是呼叫預設播放器進行播放,再加上雙端差異,實際展示效果更是精彩紛呈。說到這裡,要寫一下目前各個瀏覽器的核心情況:
微信瀏覽器
- 安卓
微信6.1版本以上的android使用者,都是使用的QQ瀏覽器的X5核心。 5.4-6.1之間的版本,若使用者安裝了QQ瀏覽器就是使用的X5核心,若使用者未安裝瀏覽器,使用的是系統核心。
- IOS
Webkit。
大部分手機瀏覽器
Webkit。(UC的U3核心和X5核心一樣,是基於webkit修改的核心)。
由上可知,在移動端開發遇到的百分之九十的問題,都是系統和機型問題。
我們回到問題本身,在使用htmlvideo標籤時,我們會發現,點選播放之後首先會進入播放器佔用整個螢幕,之後開始播放,再次點選視訊會出現控制欄。
好,捋一捋思路。第一步,要解決脫離螢幕的播放問題。
<videoposter="img/test.jpg" webkit-playsinline="true" playsinline> <source src="img/movie.mp4" type="video/mp4"> <source src="img/movie.ogg" type="video/ogg"> 您的瀏覽器不支援該視訊格式。 </video> 複製程式碼
webkit-playsinline playsinline:這個屬性作用是讓視訊播放時局域播放(不全屏,在原有位置上播放),不脫離文件流 。但這個屬性需要嵌入網頁的APP比如WeChat中UIwebview 的allowsInlineMediaPlayback = YES webview.allowsInlineMediaPlayback = YES,才能生效。換句話說,安卓不支援,而IOS的wechat卻支援,因為APP不支援playsinline,所以安卓是預設全屏播放的。
第二步,隱藏掉控制欄。
<video x5-video-player-type="h5"id="video"> <source src="img/movie.mp4" type="video/mp4"> <source src="img/movie.ogg" type="video/ogg"> 您的瀏覽器不支援該視訊格式。 </video> 複製程式碼
x5-video-player-type='h5' 啟用同層H5播放器,學名叫沉浸式播放。播放的時候除去了control和微信的導航欄,只留下"X"和"<"兩鍵。
一般來說,這種已經足夠‘沉浸’了,但專案對定製化要求比較高,要求這種也不要出現。我苦思冥想,查了好多文件,方法卻都大同小異。直到最後靈光一閃,放棄了通過屬性或方法來限制的思路,決定用視覺遮擋來實現效果:
將video的控制欄擠出可視區域,不就相當於隱藏了控制欄嘛。
/*這是CSS*/ html,body,.main{ width: 100%; height: 100%; overflow: hidden;//隱藏 background: #FFF; box-sizing:border-box; } .videobox{ z-index: 12; position: fixed; left: 0; top: 0; width: 100%; height: 100%; } #video{ position: absolute; top: -2%; width: 100%; height: 110%; } <!--這是HTML--> <div class="videobox" ontouchmove="return false;"> <videoposter="img/test.jpg" webkit-playsinline="true" playsinline x5-video-player-type="h5"x-webkit-airplay="true" id="video"> <source src="img/movie.mp4" type="video/mp4"> <source src="img/movie.ogg" type="video/ogg"> 您的瀏覽器不支援該視訊格式。 </video> </div> 複製程式碼
這樣就實現了播放時不得操作的需求。
三、IOS當視訊被開啟在safari瀏覽器時播放白屏。
這就牽扯到兩個個問題,我們分開來說。
video標籤對視訊格式以及編碼的支援
-
MPEG4 = 帶有H.264視訊編碼和AAC音訊編碼的MPEG4檔案
-
WebM = 帶有VP8視訊編碼和Vorbis音訊編碼的 WebM檔案
-
Ogg = 帶有Theora視訊編碼和Vorbis音訊編碼的Ogg檔案
如上所示,只有h264編碼的MP4視訊(MPEG-LA公司)、VP8編碼的webm格式的視訊(Google公司)和Theora編碼的ogg格式的視訊(iTouch開發)可以支援html5的<video>
標籤。
那麼在實際程式碼上我們應該這麼佈置:
<videoposter="img/test.jpg" webkit-playsinline="true" playsinline x5-video-player-type="h5"x-webkit-airplay="true" id="video"> <source src="img/movie.mp4" type="video/mp4"> <source src="img/movie.ogg" type="video/ogg"> 您的瀏覽器不支援該視訊格式。 </video> 複製程式碼
首先會判斷是否支援MP4,如否,判斷是否支援OGG,如否,展示文字。這也是我最後選擇的解決方式,簡單粗暴可以早睡覺 :)。
備註:網上有文章說,用格式工廠將mp4編碼轉成H264即可,但我實際應用中發現H264在safari和chrome中竟然無法開啟,具體原因究竟是我編碼錯誤還是與文件衝突,暫未知曉。
iOS上播放視訊,http協議中應用rang請求頭
視訊格式MP4是正確的,但是你的後臺沒有對ios的視訊播放器做適配。如果想要在iOS上播放視訊,那麼必須在http協議中應用rang請求頭。 對於有的朋友還對ios播放器http的range標記不是很懂。我再講解下。 視訊檔案總長度是123456789 range是播放器要求的區間也就是客戶端傳送請求的時候http會帶有這個標記,這個區間的值在http.headers.range中獲取,一般是bytes=0-1這樣的。 我們需要做的處理是返回檔案的指定區間(如上面的例子,我們就應該返回0到1的字元),並新增Content-Range:btyes 0-1、Accept-Ranges:bytes、'Content-Length: 123456789','Content-Type: video/mp4'到http.headers中 複製程式碼
具體效果因為時間關係並沒有親自測試,有興趣的朋友可以研究一下。
四、關於其他屬性的補充
- 讓你的視訊充滿螢幕。
#video{ object-fit: fill; } 複製程式碼
- 把當前的視訊投放到其他支援此技術的裝置上。
<video x-webkit-airplay="true"></video> 複製程式碼
- 在視訊結束時執行事件。
$("#video").get(0).addEventListener("ended", function() { }, false); 複製程式碼
- 微信瀏覽器下實現自動播放。
document.addEventListener("WeixinJSBridgeReady", function() { video.play() }, false) 複製程式碼