h5點播播放mp4視訊遇到的坑,ios的h5不能播放視訊等
背景
h5的出現對多媒體在網頁上的視訊播放提供了支援,以前網頁播放視訊基本依賴於flash等外掛。而h5的video標籤實現了網頁播放視訊無外掛化。因此,h5的出現給網頁視訊播放帶來極大的便捷性,目前,PC端的Chrome,安卓端瀏覽器,微信瀏覽器,QQ瀏覽器(自帶播放器),以及IOS的safari都支援h5的video標籤。部分PC端瀏覽器比如IE還不支援。
基礎知識普及
h5的video標籤目前支援三種視視訊封裝格式,有"video/mp4",
"video/ogg", "video/mov"。mp4格式要求h264/aac。http點播時MIME TYPE即設定為"video/mp4"等格式,video標籤需要關聯視訊格式和視訊播放地址,瀏覽器請求到服務端的html檔案進行解析渲染,然後通過video標籤關聯的播放地址請求視訊播放流。
遇到的坑
最近點播專案中需要支援移動端的h5原生視訊播放,視訊格式為mp4。
(1)最初的實現遇到問題是通過VLC播放器能夠正常播放拖動(拖動的支援需要服務端返回206的http響應碼),但是在PC的h5上(此時在PC的chrome測試,未在移動端測試)能播放但是不能拖動。下圖為h5正常拖動時的請求響應https包。
究其原因是https響應缺少上圖標註的欄位。
1.Accept-Ranges代表接收為位元組
2.Content-Length代表接收資料長度
3.Content-Range代表接收資料的範圍,332693504-504863243代表起始資料和結束資料的自己位置(包含332693504
(2)按照如上傳輸協議支援了PC和安卓的h5播放拖動。但是IOS端safari不能播放視訊。
經過對比測試發現。
之前的做法是,請求一個視訊連結,然後預設返回一整個視訊檔案,對於pc的h5拖動是預設請求偏移位置後的整個檔案(安卓端未知,但是能正常播放拖動)。此時服務端的做法預設為網頁請求的是整個檔案。
而對於safari來說,他不是一次性請求全部檔案的(不論osx還是ios),一般首先會請求0-1位元組,這個寫在request
header的"range"欄位中:
range: 'bytes=0-1'
針對該問題,服務端修改Content-Range的起始和結束資料的位置值,即
Content-Range: bytes 0-1/504863244
另外需要返回兩個位元組的視訊資料,多了少了也不能播放。
為什麼safari行為不一樣:safari之所以分多次請求也有深層次原因。比方說先請求0-1位元組(其實是2個位元組),返回的時候資料並不多,但是可以通過分析"Content-Range"來獲取檔案總長度。然後分段請求,比如請求第一幀來渲染thumb nail等等。這樣做有個好處就是,只有當用戶點選播放了才請求完整檔案,對於PC還好,對於手機這類資料傳輸需要收費的裝置來說,必須要節省流量。
另外在iphone上chrome也用的是apple提供的核心,導致他們的行為基本上一致。(這是蘋果的規定)。 (3)在解決了上述兩個坑後,實際發現IOS還是不能播放,抓包現象為IOS只發出第一個請求收到服務端帶Content-Length欄位響應後無後續請求發出。通過分析發現,IOS的safari播放mp4時第一個請求為不帶range(表示請求偏移)欄位的請求,之前由於服務端nginx lua只過濾帶range欄位請求響應修改返回206狀態碼,因此第一個包返回IOS的是200狀態碼。因此,IOS收到第一個響應後無後續請求發出。通過修改為206後正常播放。