首頁  >  文章  >  web前端  >  學javascript如何截取影片第一幀

學javascript如何截取影片第一幀

coldplay.xixi
coldplay.xixi轉載
2020-09-10 17:34:265225瀏覽

學javascript如何截取影片第一幀

相關學習推薦:javascript影片教學

JavaScript截取影片第一幀

一、背景

在企業資料的開發中,除了涉及到影片上傳之外,還需要使用影片中的第一幀或或許幾幀作為影片封面展示。

產生的問題:

因此,JS截取影片第一幀的難點就此誕生,但是查閱了資料發現,網路上提供的資料無外乎兩個品種,第一種是wasm ffmpeg 配合後端去截取,第二種是JS自行截取。優缺點也是顯而易見的,第一種,配合成本比較高,而且不是很靈活;第二種可以滿足一般條件下的使用,但是會有兼容問題(IE再見)以及截取黑屏的問題。

二、wasm ffmpeg

這種方式優缺點也是顯而易見的,配合成本比較高,而且會造成web內存的急劇飆升,但是支持的視頻種類已經截取的幀數是很靈活的;由於涉及到服務端,具體可以參考wasm ffmpeg 截取視訊。

三、JavaScript 前端截取

這裡前端截取的話就需要了解 video、canvas 標籤的兼容性和回應事件了。而且對IE可能沒那麼友善。

1. canvas的知識這裡不做過多補充,下面主要看一下video標籤的回應事件有哪些:

學javascript如何截取影片第一幀

執行結果

學javascript如何截取影片第一幀

根據順序,第一個被觸發的竟然是timeupdate 事件,按設想來說,最先執行的應該是loadedmetadata,元資料載入完畢。關於這一點,在MDN上沒有明確的說明,但是可以推理一下:

currentTime 更新時會觸發timeupdate 事件

#結論:雖然最先觸發,但此時視訊檔案尚未加載,截取的是canvas 的無內容本身。註:timeupdate 事件依使用的系統不同,每秒觸發4-66次,且由於觸發頻率高,單位過小(毫秒等級),事件回應需要延遲等原因,無法完全精準的控制。

  • loadedmetadata 上文提到,元資料載入完畢之後即觸發,但資料中並不包括影片檔案本身。結論:如果影片檔案較大,載入時間較長,仍然無法截取到已載入的第一幀。補充:透過 URL.createObjectURL()方法能夠基本做到無察覺,但不保險。

  • loadeddata 目前幀數(第一幀)載入完畢觸發,沒毛病。結論:可用。補充:萬一第一幀是黑屏想用下一幀怎麼辦,對不起,餘下幀數加沒加載完不在它的考慮範圍之類,這個事件不管。

  • canplay 影片能夠開始播放時觸發,也就是根據上傳的影片畫面數決定載入多少影格(24/25/30/60等等)後滿足播放畫面後觸發。總結:因為載入相對於 loadeddata的事件來說更多(多一丟丟),整體可行。補充:透過控制 currentTime可以滿足(但不可能是第二幀那麼準確),可以看做「目前播放幀」。

  • play 開始播放時才會觸發,和上傳快速截取的需求不是很符合。

  • waiting 已播放但下一畫面未緩衝好時觸發,適合插播小廣告。

2. 在了解上面的回應事件之後,讓我們來看看接下來截取動作:

學javascript如何截取影片第一幀
##上面的的結果是什麼呢?

學javascript如何截取影片第一幀
可以看到已經很成功的截取到了影片的第一幀,那麼到此階段,其實已經基本實現了需求,但是圖片是否是有效的,這個還未可知,所以需要我們進一步去判斷。

3. 第一幀是否有效

其實,截取到的第一幀圖片,有些時候由於影片的品質不佳或一些其他因素影響,截取到的圖片往往不是很符合預期,一直與會出現純黑的圖片,透明圖片,白色圖片等等無效圖片。因此,我們需要進行一下圖片有效性的辨識。 那麼,怎麼去辨識圖片的有效性呢?

這時候,你就需要認識一個新屬性了:Uint8ClampedArray

Uint8ClampedArray(8位元無符號整數固定數組) 類型化數組表示一個由值固定在0-255區間的8位無符號整數組成的數組;如果你指定一個在[0,255] 區間外的值,它將被替換為0或255;如果你指定一個非整數,那麼它將被設定為最接近它的整數。 (數組)內容被初始化為0。一旦(數組)被創建,你可以使用物件的方法來引用數組裡的元素,或使用標準的數組索引語法(即使用方括號標記)。

如果對 Uint8ClampedArray 感興趣,可以非同步這裡進一步研究 Uint8ClampedArray。

你是不是發現了什麼? 0~255這個是不是常見的數值,顏色的十六進位對應的數值。好,那麼,接下來就是按照我們所思考好的去實現,看看是不是這麼一個原理。 學javascript如何截取影片第一幀

程式碼是實現了,那麼結果呢,我這裡分別使用白色圖片,透明圖片,黑色圖片來對照一下,拿到的結果究竟是不是和我們所想像的一直的: 首先我們來看一下透明圖片:

學javascript如何截取影片第一幀

可以看到,結果陣列裡面,全部是0;

白色圖片:

學javascript如何截取影片第一幀

哎呦,全是255,那麼黑色就應該全是0了,別急,讓我們看一下

黑色圖片:

學javascript如何截取影片第一幀

出現了意想不到的數字,238,這是偏向255白色的色值,為什麼會這樣呢?其實是因為白色和透明色沒有過度,而黑色是過度的,就是在canvas繪製的時候會出現這種問題,但是可以忽略的。

知道了這三者的色值,那麼接下來的判斷也就好辦了,直接在加一個條件就好了

學javascript如何截取影片第一幀
##為什麼是200 和0 呢?其實這兩個值你們可以根據實際情況去判斷合理範圍,200 對應的色值是#c8c8c8,是灰色,0是透明色,所以在這裡就判斷是無效圖片了。只要brr數組裡面沒有值,就表示是無效圖片。

那麼實際情況如何呢?再來一張實際的對比圖:

學javascript如何截取影片第一幀
可以看到,brr裡面是有值的,而且還是大量的,所以這正圖片就是有效圖片。

4. 最後

JavaScript截取影片第一幀就已經完畢了,如果還想優化就是針對無效圖片的時候,使用預設圖片展示即可。

四、總結

JavaScript截取影片第一幀,過程比較繁雜,而且涉及到很大量的資料循環,會造成一定的記憶體成長,但是確確實實能解決這個問題,並且已經用到了企業資料中,其中使用了一個取巧優化的辦法,只有brr數組有一個值被push進去,就直接break,這樣可以極大的優化性能。

如果大家還有更好的解決辦法,可以多多交流!

想了解更多程式設計學習,請關注

php培訓欄位!

#

以上是學javascript如何截取影片第一幀的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:juejin.im。如有侵權,請聯絡admin@php.cn刪除