玩轉(zhuǎn)B站彈幕不遮擋人物實現(xiàn)

一、話題來源
疫情被封控居家辦公了,摸魚時間用手機逛下B站、無意間發(fā)現(xiàn): 咦, B站的彈幕是不會遮擋人物的耶。

哦?跟平時看到的彈幕好像非常不一樣、立馬掏出某訊視頻看看:果然,B站跟某訊在彈幕方面還是有區(qū)別的。

看到這里,覺著很神奇,故有了此篇文章研究下其實現(xiàn)原理。
二、實現(xiàn)探究
隨便訪問一個B站視頻(筆者隨便找的)、打開調(diào)試終端,你會發(fā)現(xiàn):跟視頻播放器同級別有一個特殊的屬性叫做-webkit-mask-image,該屬性返回的好像是一張人物輪廓圖。

試試看把該屬性隱藏掉,你會發(fā)現(xiàn):

事實證明,確實是該屬性起的作用,那具體怎么用呢?請聽后續(xù)分解。
三、詳細解析
單圖遮罩
這項黑科技被B站稱為蒙版彈窗: 通過計算機視覺技術(shù)、對視頻內(nèi)容進行分析,并將之前已經(jīng)定義好的內(nèi)容進行識別并分發(fā)該客戶端、讓客戶端利用CSS3的特性進行渲染從而達到該效果.(該解釋摘抄于網(wǎng)絡(luò))
編寫index.html文件內(nèi)容如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.video-area {
width: 668px;
height: 376px;
position: relative;
mask-image: linear-gradient(rgb(0, 0, 0), rgb(0, 0, 0) 0.0332447%, rgba(0, 0, 0, 0) 0.0332447%), linear-gradient(rgba(0, 0, 0, 0) 99.9668%, rgb(0, 0, 0) 99.9668%, rgb(0, 0, 0)), url("data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKIHdpZHRoPSI2NjhweCIgc3R5bGU9InRyYW5zZm9ybTpzY2FsZSgxLDEuMDAxKTsiIGhlaWdodD0iMzc1Ljc1cHgiIHZpZXdCb3g9IjAgMCAzMjAuMDAwMDAwIDE4MC4wMDAwMDAiCiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCBtZWV0Ij4KPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC4wMDAwMDAsMTgwLjAwMDAwMCkgc2NhbGUoMC4xMDAwMDAsLTAuMTAwMDAwKSIKZmlsbD0iIzAwMDAwMCIgc3Ryb2tlPSJub25lIj4KPHBhdGggZD0iTTAgOTA1IGwwIC04OTUgMTYwMCAwIDE2MDAgMCAwIDg5NSAwIDg5NSAtMTYwMCAwIC0xNjAwIDAgMCAtODk1eiBtMTQ4OCA1MTMKYzcxIC0yNSAxMzcgLTg2IDE0OCAtMTM1IDMgLTE1IDE1IC01OSAyNiAtOTggMTcgLTU2IDIxIC05OSAyMiAtMjIwIGwxIC0xNTAKMzYgLTE3IGMxOSAtMTAgODIgLTIzIDE0MCAtMjggMjQ1IC0yNiAzOTkgLTEyMCA0NDMgLTI3NCAxMCAtMzIgMjMgLTY4IDMxCi04MCA3IC0xMiAxNiAtMzIgMjAgLTQ2IDQgLTE0IDE1IC0zNCAyNSAtNDUgOSAtMTEgMjcgLTQ4IDQwIC04MiAyMSAtNjAgMjIKLTY0IDYgLTg4IC0xMCAtMTQgLTI5IC0zMCAtNDMgLTM2IC0xNCAtNSAtMTA0IC04IC0yMDEgLTggLTk4IDEgLTIyOSAtMiAtMjkyCi04IC03NiAtNyAtMTQ0IC03IC0yMDAgMCAtNTggNyAtMTM4IDYgLTI1NSAtMiAtOTMgLTYgLTIzMSAtMTQgLTMwNiAtMTcKbC0xMzcgLTcgLTE3IDI2IGMtMTQgMjEgLTE3IDUzIC0xOCAxNjkgLTEgMTY0IDcgMTkwIDczIDIzNCAyMSAxNCA0MyAzOCA0OAo1MiAxMSAzNCAtMiAxMDUgLTI3IDE0NiAtMTAgMTcgLTIyIDU1IC0yNiA4NSAtNCAyOSAtMjAgNzcgLTM1IDEwNiAtNDkgOTQKLTQ5IDI1NiAyIDMwMSAxMSAxMSAyOSAzNyA0MCA1OCAzMCA1OSAxMjMgMTQzIDE2NyAxNTEgMjAgMyA0NyAxMyA2MSAyMCA0MAoyMyAxNTQgMTkgMjI4IC03eiIvPgo8L2c+Cjwvc3ZnPgo=");
-webkit-mask-image: linear-gradient(rgb(0, 0, 0), rgb(0, 0, 0) 0.0332447%, rgba(0, 0, 0, 0) 0.0332447%), linear-gradient(rgba(0, 0, 0, 0) 99.9668%, rgb(0, 0, 0) 99.9668%, rgb(0, 0, 0)), url("data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKIHdpZHRoPSI2NjhweCIgc3R5bGU9InRyYW5zZm9ybTpzY2FsZSgxLDEuMDAxKTsiIGhlaWdodD0iMzc1Ljc1cHgiIHZpZXdCb3g9IjAgMCAzMjAuMDAwMDAwIDE4MC4wMDAwMDAiCiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCBtZWV0Ij4KPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC4wMDAwMDAsMTgwLjAwMDAwMCkgc2NhbGUoMC4xMDAwMDAsLTAuMTAwMDAwKSIKZmlsbD0iIzAwMDAwMCIgc3Ryb2tlPSJub25lIj4KPHBhdGggZD0iTTAgOTA1IGwwIC04OTUgMTYwMCAwIDE2MDAgMCAwIDg5NSAwIDg5NSAtMTYwMCAwIC0xNjAwIDAgMCAtODk1eiBtMTQ4OCA1MTMKYzcxIC0yNSAxMzcgLTg2IDE0OCAtMTM1IDMgLTE1IDE1IC01OSAyNiAtOTggMTcgLTU2IDIxIC05OSAyMiAtMjIwIGwxIC0xNTAKMzYgLTE3IGMxOSAtMTAgODIgLTIzIDE0MCAtMjggMjQ1IC0yNiAzOTkgLTEyMCA0NDMgLTI3NCAxMCAtMzIgMjMgLTY4IDMxCi04MCA3IC0xMiAxNiAtMzIgMjAgLTQ2IDQgLTE0IDE1IC0zNCAyNSAtNDUgOSAtMTEgMjcgLTQ4IDQwIC04MiAyMSAtNjAgMjIKLTY0IDYgLTg4IC0xMCAtMTQgLTI5IC0zMCAtNDMgLTM2IC0xNCAtNSAtMTA0IC04IC0yMDEgLTggLTk4IDEgLTIyOSAtMiAtMjkyCi04IC03NiAtNyAtMTQ0IC03IC0yMDAgMCAtNTggNyAtMTM4IDYgLTI1NSAtMiAtOTMgLTYgLTIzMSAtMTQgLTMwNiAtMTcKbC0xMzcgLTcgLTE3IDI2IGMtMTQgMjEgLTE3IDUzIC0xOCAxNjkgLTEgMTY0IDcgMTkwIDczIDIzNCAyMSAxNCA0MyAzOCA0OAo1MiAxMSAzNCAtMiAxMDUgLTI3IDE0NiAtMTAgMTcgLTIyIDU1IC0yNiA4NSAtNCAyOSAtMjAgNzcgLTM1IDEwNiAtNDkgOTQKLTQ5IDI1NiAyIDMwMSAxMSAxMSAyOSAzNyA0MCA1OCAzMCA1OSAxMjMgMTQzIDE2NyAxNTEgMjAgMyA0NyAxMyA2MSAyMCA0MAoyMyAxNTQgMTkgMjI4IC03eiIvPgo8L2c+Cjwvc3ZnPgo=");
mask-size: 668px 376px;
}
video {
width: 100%;
height: 100%;
content-visibility: visible;
background: red;
}
.bullet-item {
position: absolute;
}
</style>
</head>
<body>
<div class="video-area">
<video crossorigin="anonymous" preload="auto" src="blob:https://www.bilibili.com/6c6cd172-471b-4a43-befa-dbe20b65d034"></video>
<div class="bullet-item" style="top: 4px;left: 270px;">看了不下十遍</div>
<div class="bullet-item" style="top: 54px;left: 200px;">看十次笑十次</div>
<div class="bullet-item" style="top: 79px;left: 210px;">我已迷上門口的老頭</div>
<div class="bullet-item" style="top: 54px;left: 300px;">門口的老頭哈哈哈哈</div>
</div>
</body>
</html
驗證效果如下:

你會發(fā)現(xiàn)視頻未展示出現(xiàn)(視頻是blob資源、沒法直接下載、這里我們不糾結(jié)視頻的問題)、倒是有個紅色背景。
Error:Not allowed to load local resource: blob:https://www.bilibili.com/6c6cd172-471b-4a43-befa-dbe20b65d034
至此,我們就實現(xiàn)了B站彈幕不遮擋人物的功能。
視頻播放
上面Demo演示的是單張輪廓圖,那么視頻在播放途中,是怎么確保這個輪廓圖能實時替換成最新的呢?
視頻播放過程中查看network,你會發(fā)現(xiàn): 有不斷去請求輪廓圖片、這個是跟視頻播放到哪一個畫面或者哪一幀有關(guān)的(具體可能得后端人員比較清楚、這里不過多糾結(jié))

總結(jié): 整個視頻播放區(qū)域由3個部分組成: 視頻播放器 + 彈幕 + 遮罩圖(人物輪廓圖)。前端只需要按照一定的時間節(jié)點替換這個承載遮罩圖的容器圖片即可。
四、寫在最后
至此、相信您已經(jīng)了解了為什么B站的彈幕不遮擋人物 && 實現(xiàn)方案。若覺著此文章對您有幫助的話,點個贊再走唄!
