"今天又是充滿希望的一天"背景
最近在做一個視頻播放的需求,因為比較簡單,只需要實現基本的,播放,暫停等功能,所以就用系統的播放器。本來開開心心打完了工,正偷偷給妹妹發微信,測試大姐拿著手機過來就噼里啪啦一頓輸出
“啊,你們的視頻加載怎么這么慢?!”
“你看看人家iOS就不這樣,這樣能上線嗎?!”
我X,我測的時候明明好好的啊,怎么現在加載個視頻就要30多秒。看著不斷轉圈圈的圖,我心里大罵
“又tm有坑是吧”
為了不耽誤各位男哥哥女哥哥的時間,直接上結論:視頻元數據位置不對
???什么是視頻元數據?哪里位置不對?你特么寫技術文還要別人百度是吧?
別別別,聽我解釋
關鍵的一句話
實際項目中用到的視頻格式大多是MP4,MP4格式的視頻是由一個個Box組成的。這個Box可以理解為數據塊。Box里面可以嵌套Box:
(如果哥哥們想自己體驗一把, mac可以用, 用)
ftyp,moov,mdat就是Box的名字。這里需要重點關注的是moov和mdat兩個Box。
moov就是視頻的元數據視頻加載完才能播放,存放著視頻的總體信息,時長啦,碼率啦,寬高等等
mdat是具體的媒體數據,也就是我們播放的內容
下面這句話很關鍵
播放器獲取到moov box才能開始播放視頻!!!
播放器獲取到moov box才能開始播放視頻!!!
播放器獲取到moov box才能開始播放視頻!!!
這句話是這篇文章的核心。其他可以不管,這個起碼要記住
所以關于播放器加載視頻慢的原因,聰明的哥哥一定早就有答案了,繼續看無非就是驗證一下啦
原因
上面那張圖是理想狀態下視頻box的位置。
但一些視頻在壓制的時候,會把moov box放在視頻尾部,也就是mdat之后。這就造成播放器必須把整個視頻下載完才能獲取到moov box,然后才能播放。
相當于你和妹子去約會,剛見面老板說線上有問題讓你解決,你哼哧哼哧解決完繼續約會你看妹妹會不會當場跟你分手
方案一
直接原因是找到了。聰明的哥哥一定會提出另一個問題
既然moov box這么關鍵,為什么有的視頻會把它放在最后呢?
這個我做了一下實驗,發現在轉換視頻格式的時候,會默認把moov box放在視頻尾部。我猜是轉化完整個視頻之后才能確切知道新視頻的時長,碼率等信息,所以順手就把它放到新視頻的末尾了。
其實也提供了移動moov box到視頻頭部的命令
ffmpeg -i input.mp4 -c copy -f mp4 -movflags faststart output.mp4
這不就是解決方案之一嗎?
用新的視頻一試,加載時間果然變成2~3秒了
真相大白!!!
方案二
正當我神清氣爽準備再找妹妹交流感情之時,產品阿姨告訴我,我們視頻有幾萬個,項目馬上要上線了,誰給你時間一個個轉換,你說啊,你說啊!!!
我就是個打工的.. 別罵我嘛..
實際開發中會有各種情況無法對視頻源做修改,這時候我們只能自己想辦法。
視頻播放的前提是要獲取到moov box,而視頻源moov box在尾部,那么我們能不能
先請求視頻的尾部獲取到moov box,然后再從頭請求視頻呢?
當然可以。流媒體的請求并不是一次請求完成的,而是分片請求。 先發起一個http請求,讀取響應body的開頭,如果發現moov在開頭就繼續往下讀mdat。如果沒有發現,第二個請求直接讀取文件末尾的數據,這樣用兩個請求也能獲取到moov。這個方案要求服務端能支持-Range請求,也就是能通過Range直接讀取文件尾部,不過一般的oss服務都支持。
這個方案可以耶!可是難道要我重寫一遍的請求??那我的妹妹怎么辦?!
轉念一想,這個問題應該很普遍,聰明的哥哥們一定已經填過坑了。于是我用和分別測了一下,果然這兩個播放器都已經對這種情況做了處理,直接替換就好。的官方so庫不支持https請求,于是最終采用了
耶!終于結束了!雖然妹妹早就不耐煩地不回我消息了視頻加載完才能播放,但我相信只要堅持對她好她一定會感動的。下個坑,我一定不會再讓妹妹久等了