您好,登錄后才能下訂單哦!
這篇文章將為大家詳細(xì)講解有關(guān)javascript實(shí)現(xiàn)截取視頻第一幀的方法,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
在企業(yè)資料的開發(fā)中,除了涉及到視頻上傳之外,還需要使用視頻中的第一幀或者或許幾幀作為視頻封面展示。
因此,JS截取視頻第一幀的難點(diǎn)就此誕生,但是查閱了資料發(fā)現(xiàn),網(wǎng)上提供的資料無外乎倆種,第一種是 wasm + ffmpeg 配合后端去截取,第二種是JS自行截取。優(yōu)缺點(diǎn)也是顯而易見的,第一種,配合成本比較高,而且不是很靈活;第二種可以滿足一般條件下的使用,但是會(huì)有兼容問題(IE再見)以及截取黑屏的問題。
這種方式優(yōu)缺點(diǎn)也是顯而易見的,配合成本比較高,而且會(huì)造成web內(nèi)存的急劇飆升,但是支持的視頻種類已經(jīng)截取的幀數(shù)是很靈活的;由于涉及到服務(wù)端,具體可以參考 wasm + ffmpeg 截取視頻。
這里前端截取的話就需要了解 video、canvas 標(biāo)簽的兼容性和響應(yīng)事件了。而且對(duì)IE可能不是那么友好。
執(zhí)行結(jié)果
根據(jù)順序,第一個(gè)被觸發(fā)的竟然是 timeupdate 事件,按設(shè)想來說,最先執(zhí)行的應(yīng)該是 loadedmetadata,元數(shù)據(jù)加載完畢。關(guān)于這一點(diǎn),在MDN上沒有明確的說明,但是可以推理一下:
當(dāng) currentTime 更新時(shí)會(huì)觸發(fā) timeupdate 事件
結(jié)論:雖然最先觸發(fā),但是此時(shí)視頻文件尚未加載,截取的是 canvas 的無內(nèi)容本身。注:timeupdate 事件根據(jù)使用的系統(tǒng)不同,每秒觸發(fā)4-66次,且由于觸發(fā)頻率高,單位過小(毫秒級(jí)別),事件響應(yīng)需要延遲等原因,無法完全精準(zhǔn)的控制。
loadedmetadata 上文提到,元數(shù)據(jù)加載完畢之后即觸發(fā),但數(shù)據(jù)中并不包括視頻文件本身。結(jié)論:如果視頻文件較大,加載時(shí)間較長,仍然無法截取到已加載的第一幀。補(bǔ)充:通過 URL.createObjectURL()方法能夠基本做到無察覺,但并不保險(xiǎn)。
loadeddata 當(dāng)前幀數(shù)(第一幀)加載完畢觸發(fā),沒毛病。結(jié)論:可用。補(bǔ)充:萬一第一幀是黑屏想用下一幀怎么辦,對(duì)不起,余下幀數(shù)加沒加載完不在它的考慮范圍之類,這個(gè)事件不管。
canplay 視頻能夠開始播放時(shí)觸發(fā),也就是根據(jù)上傳的視頻幀數(shù)決定加載多少幀(24/25/30/60等等)后滿足播放畫面后觸發(fā)??偨Y(jié):因?yàn)榧虞d相對(duì)于 loadeddata的事件來說更多(多一丟丟),總體可行。補(bǔ)充:通過控制 currentTime可以滿足(但不可能是第二幀那么準(zhǔn)確),可以看做“當(dāng)前播放幀”。
play 開始播放時(shí)才會(huì)觸發(fā),和上傳快速截取的需求不是很符合。
waiting 已播放但下一畫面沒緩沖好時(shí)觸發(fā),適合插播小廣告。
上面的的結(jié)果是什么呢?
可以看到已經(jīng)很成功的截取到了視頻的第一幀,那么到此階段,其實(shí)已經(jīng)基本實(shí)現(xiàn)了需求,但是圖片是否是有效的,這個(gè)還未可知,所以需要我們進(jìn)一步去判斷。
其實(shí),截取到的第一幀圖片,有些時(shí)候由于視頻的質(zhì)量不佳或者一些其他因素影響,截取到的圖片往往不是很符合預(yù)期,一直與會(huì)出現(xiàn)純黑的圖片,透明圖片,白色圖片等等無效圖片。因此,我們需要進(jìn)行一下圖片有效性的識(shí)別。 那么,怎么去識(shí)別圖片的有效性呢?
這時(shí)候,你就需要認(rèn)識(shí)一個(gè)新屬性了:Uint8ClampedArray
Uint8ClampedArray(8位無符號(hào)整型固定數(shù)組) 類型化數(shù)組表示一個(gè)由值固定在0-255區(qū)間的8位無符號(hào)整型組成的數(shù)組;如果你指定一個(gè)在 [0,255] 區(qū)間外的值,它將被替換為0或255;如果你指定一個(gè)非整數(shù),那么它將被設(shè)置為最接近它的整數(shù)。(數(shù)組)內(nèi)容被初始化為0。一旦(數(shù)組)被創(chuàng)建,你可以使用對(duì)象的方法引用數(shù)組里的元素,或使用標(biāo)準(zhǔn)的數(shù)組索引語法(即使用方括號(hào)標(biāo)記)。
如果對(duì) Uint8ClampedArray 感興趣,可以異步這里進(jìn)一步研究 Uint8ClampedArray。
你是不是發(fā)現(xiàn)了什么?0~255這個(gè)是不是常見的數(shù)值,顏色的十六進(jìn)制對(duì)應(yīng)的數(shù)值。好,那么,接下來就是按照我們所思考好的去實(shí)現(xiàn),看看是不是這么一個(gè)原理。
代碼是實(shí)現(xiàn)了,那么結(jié)果呢,我這里分別使用白色圖片,透明圖片,黑色圖片來對(duì)照一下,拿到的結(jié)果究竟是不是和我們所想象的一直的: 首先我們來看一下透明圖片:
可以看到,結(jié)果數(shù)組里面,全部是 0;
白色圖片:
哎呦,全是255,那么黑色就應(yīng)該全是0了,別急,讓我們看一下
黑色圖片:
出現(xiàn)了意想不到的數(shù)字,238,這是偏向255白色的色值,為什么會(huì)這樣呢?其實(shí)是因?yàn)榘咨屯该魃珱]有過度,而黑色是過度的,就是在canvas繪制的時(shí)候會(huì)出現(xiàn)這種問題,但是是可以忽略不計(jì)的。
知道了這三者的色值,那么接下來的判斷也就好辦了,直接在加一個(gè)條件就好了
為什么是200 和 0 呢?其實(shí)這倆個(gè)值你們可以根據(jù)實(shí)際情況去判斷合理范圍,200 對(duì)應(yīng)的色值是#c8c8c8,是灰色,0是透明色,所以在這里就判斷是無效圖片了。只要brr數(shù)組里面沒有值,就說明是無效圖片。
那么實(shí)際情況如何呢?再來一張實(shí)際的對(duì)比圖:
可以看到,brr里面是有值的,而且還是大量的,所以這正圖片就是有效圖片。
JavaScript截取視頻第一幀就已經(jīng)完畢了,如果還想優(yōu)化就是針對(duì)無效圖片的時(shí)候,使用默認(rèn)圖片展示即可。
JavaScript截取視頻第一幀,過程比較繁雜,而且涉及到很大量的數(shù)據(jù)循環(huán),會(huì)造成一定的內(nèi)存增長,但是確確實(shí)實(shí)能解決這個(gè)問題,并且已經(jīng)已用到了企業(yè)資料中,其中使用了一個(gè)取巧優(yōu)化的辦法,只有brr數(shù)組有一個(gè)值被push進(jìn)去,就直接break,這樣可以極大的優(yōu)化性能。
關(guān)于javascript實(shí)現(xiàn)截取視頻第一幀的方法就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。