玩转B站弹幕不遮挡人物实现
一、话题来源
疫情被封控居家办公了,摸鱼时间用手机逛下B站、无意间发现: 咦, B站的弹幕是不会遮挡人物的耶。
哦?跟平时看到的弹幕好像非常不一样、立马掏出某讯视频看看:果然,B站跟某讯在弹幕方面还是有区别的。
看到这里,觉着很神奇,故有了此篇文章研究下其实现原理。
二、实现探究
随便访问一个B站视频(笔者随便找的)、打开调试终端,你会发现:跟视频播放器同级别有一个特殊的属性叫做-webkit-mask-image,该属性返回的好像是一张人物轮廓图。
试试看把该属性隐藏掉,你会发现:
事实证明,确实是该属性起的作用,那具体怎么用呢?请听后续分解。
三、详细解析
单图遮罩
这项黑科技被B站称为蒙版弹窗: 通过计算机视觉技术、对视频内容进行分析,并将之前已经定义好的内容进行识别并分发该客户端、让客户端利用CSS3的特性进行渲染从而达到该效果.(该解释摘抄于网络)
编写index.html文件内容如下
<!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
验证效果如下:
你会发现视频未展示出现(视频是blob资源、没法直接下载、这里我们不纠结视频的问题)、倒是有个红色背景。
Error:Not allowed to load local resource: blob:https://www.bilibili.com/6c6cd172-471b-4a43-befa-dbe20b65d034
至此,我们就实现了B站弹幕不遮挡人物的功能。
视频播放
上面Demo演示的是单张轮廓图,那么视频在播放途中,是怎么确保这个轮廓图能实时替换成最新的呢?
视频播放过程中查看network,你会发现: 有不断去请求轮廓图片、这个是跟视频播放到哪一个画面或者哪一帧有关的(具体可能得后端人员比较清楚、这里不过多纠结)
总结: 整个视频播放区域由3个部分组成: 视频播放器 + 弹幕 + 遮罩图(人物轮廓图)。前端只需要按照一定的时间节点替换这个承载遮罩图的容器图片即可。
四、写在最后
至此、相信您已经了解了为什么B站的弹幕不遮挡人物 && 实现方案。若觉着此文章对您有帮助的话,点个赞再走呗!