javascript
js截取视频第一帧_学学javascript如何截取视频第一帧
JavaScript截取視頻第一幀
一、背景
在企業(yè)資料的開(kāi)發(fā)中,除了涉及到視頻上傳之外,還需要使用視頻中的第一幀或者或許幾幀作為視頻封面展示。
產(chǎn)生的問(wèn)題:
因此,JS截取視頻第一幀的難點(diǎn)就此誕生,但是查閱了資料發(fā)現(xiàn),網(wǎng)上提供的資料無(wú)外乎倆種,第一種是 wasm + ffmpeg 配合后端去截取,第二種是JS自行截取。優(yōu)缺點(diǎn)也是顯而易見(jiàn)的,第一種,配合成本比較高,而且不是很靈活;第二種可以滿足一般條件下的使用,但是會(huì)有兼容問(wèn)題(IE再見(jiàn))以及截取黑屏的問(wèn)題。
二、wasm + ffmpeg
這種方式優(yōu)缺點(diǎn)也是顯而易見(jiàn)的,配合成本比較高,而且會(huì)造成web內(nèi)存的急劇飆升,但是支持的視頻種類(lèi)已經(jīng)截取的幀數(shù)是很靈活的;由于涉及到服務(wù)端,具體可以參考 wasm + ffmpeg 截取視頻。
三、JavaScript 前端截取
這里前端截取的話就需要了解 video、canvas 標(biāo)簽的兼容性和響應(yīng)事件了。而且對(duì)IE可能不是那么友好。
1. canvas的知識(shí)這里不做過(guò)多補(bǔ)充,下面主要看一下video標(biāo)簽的響應(yīng)事件有哪些:
執(zhí)行結(jié)果
根據(jù)順序,第一個(gè)被觸發(fā)的竟然是 timeupdate 事件,按設(shè)想來(lái)說(shuō),最先執(zhí)行的應(yīng)該是 loadedmetadata,元數(shù)據(jù)加載完畢。關(guān)于這一點(diǎn),在MDN上沒(méi)有明確的說(shuō)明,但是可以推理一下:當(dāng) currentTime 更新時(shí)會(huì)觸發(fā) timeupdate 事件
結(jié)論:雖然最先觸發(fā),但是此時(shí)視頻文件尚未加載,截取的是 canvas 的無(wú)內(nèi)容本身。注:timeupdate 事件根據(jù)使用的系統(tǒng)不同,每秒觸發(fā)4-66次,且由于觸發(fā)頻率高,單位過(guò)小(毫秒級(jí)別),事件響應(yīng)需要延遲等原因,無(wú)法完全精準(zhǔn)的控制。loadedmetadata 上文提到,元數(shù)據(jù)加載完畢之后即觸發(fā),但數(shù)據(jù)中并不包括視頻文件本身。結(jié)論:如果視頻文件較大,加載時(shí)間較長(zhǎng),仍然無(wú)法截取到已加載的第一幀。補(bǔ)充:通過(guò) URL.createObjectURL()方法能夠基本做到無(wú)察覺(jué),但并不保險(xiǎn)。
loadeddata 當(dāng)前幀數(shù)(第一幀)加載完畢觸發(fā),沒(méi)毛病。結(jié)論:可用。補(bǔ)充:萬(wàn)一第一幀是黑屏想用下一幀怎么辦,對(duì)不起,余下幀數(shù)加沒(méi)加載完不在它的考慮范圍之類(lèi),這個(gè)事件不管。
canplay 視頻能夠開(kāi)始播放時(shí)觸發(fā),也就是根據(jù)上傳的視頻幀數(shù)決定加載多少幀(24/25/30/60等等)后滿足播放畫(huà)面后觸發(fā)。總結(jié):因?yàn)榧虞d相對(duì)于 loadeddata的事件來(lái)說(shuō)更多(多一丟丟),總體可行。補(bǔ)充:通過(guò)控制 currentTime可以滿足(但不可能是第二幀那么準(zhǔn)確),可以看做“當(dāng)前播放幀”。
play 開(kāi)始播放時(shí)才會(huì)觸發(fā),和上傳快速截取的需求不是很符合。
waiting 已播放但下一畫(huà)面沒(méi)緩沖好時(shí)觸發(fā),適合插播小廣告。
2. 了解上面的響應(yīng)事件之后,讓我們來(lái)看一下接下來(lái)截取操作:
上面的的結(jié)果是什么呢?
可以看到已經(jīng)很成功的截取到了視頻的第一幀,那么到此階段,其實(shí)已經(jīng)基本實(shí)現(xiàn)了需求,但是圖片是否是有效的,這個(gè)還未可知,所以需要我們進(jìn)一步去判斷。
3. 第一幀是否有效
其實(shí),截取到的第一幀圖片,有些時(shí)候由于視頻的質(zhì)量不佳或者一些其他因素影響,截取到的圖片往往不是很符合預(yù)期,一直與會(huì)出現(xiàn)純黑的圖片,透明圖片,白色圖片等等無(wú)效圖片。因此,我們需要進(jìn)行一下圖片有效性的識(shí)別。
那么,怎么去識(shí)別圖片的有效性呢?
這時(shí)候,你就需要認(rèn)識(shí)一個(gè)新屬性了:Uint8ClampedArrayUint8ClampedArray(8位無(wú)符號(hào)整型固定數(shù)組) 類(lèi)型化數(shù)組表示一個(gè)由值固定在0-255區(qū)間的8位無(wú)符號(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ù)組索引語(yǔ)法(即使用方括號(hào)標(biāo)記)。
如果對(duì) Uint8ClampedArray 感興趣,可以異步這里進(jìn)一步研究 Uint8ClampedArray。
你是不是發(fā)現(xiàn)了什么?0~255這個(gè)是不是常見(jiàn)的數(shù)值,顏色的十六進(jìn)制對(duì)應(yīng)的數(shù)值。好,那么,接下來(lái)就是按照我們所思考好的去實(shí)現(xiàn),看看是不是這么一個(gè)原理。
代碼是實(shí)現(xiàn)了,那么結(jié)果呢,我這里分別使用白色圖片,透明圖片,黑色圖片來(lái)對(duì)照一下,拿到的結(jié)果究竟是不是和我們所想象的一直的:
首先我們來(lái)看一下透明圖片:
可以看到,結(jié)果數(shù)組里面,全部是 0;
白色圖片:
哎呦,全是255,那么黑色就應(yīng)該全是0了,別急,讓我們看一下
黑色圖片:
出現(xiàn)了意想不到的數(shù)字,238,這是偏向255白色的色值,為什么會(huì)這樣呢?其實(shí)是因?yàn)榘咨屯该魃珱](méi)有過(guò)度,而黑色是過(guò)度的,就是在canvas繪制的時(shí)候會(huì)出現(xiàn)這種問(wèn)題,但是是可以忽略不計(jì)的。
知道了這三者的色值,那么接下來(lái)的判斷也就好辦了,直接在加一個(gè)條件就好了
為什么是200 和 0 呢?其實(shí)這倆個(gè)值你們可以根據(jù)實(shí)際情況去判斷合理范圍,200 對(duì)應(yīng)的色值是#c8c8c8,是灰色,0是透明色,所以在這里就判斷是無(wú)效圖片了。只要brr數(shù)組里面沒(méi)有值,就說(shuō)明是無(wú)效圖片。
那么實(shí)際情況如何呢?再來(lái)一張實(shí)際的對(duì)比圖:
可以看到,brr里面是有值的,而且還是大量的,所以這正圖片就是有效圖片。
4. 最后
JavaScript截取視頻第一幀就已經(jīng)完畢了,如果還想優(yōu)化就是針對(duì)無(wú)效圖片的時(shí)候,使用默認(rèn)圖片展示即可。
四、總結(jié)
JavaScript截取視頻第一幀,過(guò)程比較繁雜,而且涉及到很大量的數(shù)據(jù)循環(huán),會(huì)造成一定的內(nèi)存增長(zhǎng),但是確確實(shí)實(shí)能解決這個(gè)問(wèn)題,并且已經(jīng)已用到了企業(yè)資料中,其中使用了一個(gè)取巧優(yōu)化的辦法,只有brr數(shù)組有一個(gè)值被push進(jìn)去,就直接break,這樣可以極大的優(yōu)化性能。如果大家還有更好的解決辦法,可以多多交流!想了解更多編程學(xué)習(xí),敬請(qǐng)關(guān)注php培訓(xùn)欄目!
總結(jié)
以上是生活随笔為你收集整理的js截取视频第一帧_学学javascript如何截取视频第一帧的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 火箭军下连学计算机专业好吗,火箭军招收定
- 下一篇: 利用 JS 脚本实现网页全自动秒杀抢购