Web 端实时防挡脸弹幕(基于机器学习)


防挡脸弹幕,即大量弹幕飘过,但不会遮挡视频画面中的人物,看起来像是从人物背后飘过去的。

机器学习已经火了好几年了,但很多人都不知道浏览器中也能运行这些能力;

本文介绍在视频弹幕方面的实践优化过程,文末列举了一些本方案可适用的场景,期望能开启一些脑洞。

mediapipe Demo(https://google.github.io/mediapipe/)展示

☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜

主流防挡脸弹幕实现原理

点播

up 上传视频

服务器后台计算提取视频画面中的人像区域,转换成 svg 存储

客户端播放视频的同时,从服务器下载 svg 与弹幕合成,人像区域不显示弹幕

 |直播|

  1. 主播推流时,实时(主播设备)从画面提取人像区域,转换成 svg
  2. 将 svg 数据合并到视频流中(SEI),推流至服务器
  3. 客户端播放视频同时,从视频流中(SEI)解析出 svg
  4. 将 svg 与弹幕合成,人像区域不显示弹幕

本文实现方案

客户端播放视频同时,实时从画面提取人像区域信息,将人像区域信息导出成图片与弹幕合成,人像区域不显示弹幕。

实现原理

  1. 采用机器学习开源库从视频画面实时提取人像轮廓,如Body Segmentation(https://github.com/tensorflow/tfjs-models/blob/master/body-segmentation/README.md)
  2. 将人像轮廓转导出为图片,设置弹幕层的 mask-image(https://developer.mozilla.org/zh-CN/docs/Web/CSS/mask-image)

 对比传统(|直播|SEI实时)方案

优点:

  • 易于实现;只需要Video标签一个参数,无需多端协同配合
  • 无网络带宽消耗

缺点:

  • 理论性能极限劣于传统方案;相当于性能资源换网络资源

面临的问题

众所周知,JavaScript 的性能较差,因此不适合用于处理 CPU 密集型任务。由官方demo变成工程实践,最大的挑战就是——性能。

本次实践最终将 CPU 占用优化到 5% 左右(2025 M1 Macbook),达到生产可用状态。

实践调优过程

选择机器学习模型

BodyPix (https://github.com/tensorflow/tfjs-models/blob/master/body-segmentation/src/body_pix/README.md)

精确度太差,面部偏窄,有很明显的弹幕与人物面部边缘重叠现象

BlazePose(https://github.com/tensorflow/tfjs-models/blob/master/pose-detection/src/blazepose_mediapipe/README.md)

精确度优秀,且提供了肢体点位信息,但性能较差

返回数据结构示例

[{score: 0.8,keypoints: [{x: 230, y: 220, score: 0.9, score: 0.99, name: "nose"},{x: 212, y: 190, score: 0.8, score: 0.91, name: "left_eye"},...],keypoints3D: [{x: 0.65, y: 0.11, z: 0.05, score: 0.99, name: "nose"},...],segmentation: {maskValueToLabel: (maskValue: number) => { return 'person' },mask: {toCanvasImageSource(): ...toImageData(): ...toTensor(): ...getUnderlyingType(): ...}}}]

MediaPipe SelfieSegmentation (https://github.com/tensorflow/tfjs-models/blob/master/body-segmentation/src/selfie_segmentation_mediapipe/README.md)

精确度优秀(跟 BlazePose 模型效果一致),CPU 占用相对 BlazePose 模型降低 15% 左右,性能取胜,但返回数据中不提供肢体点位信息

返回数据结构示例

{maskValueToLabel: (maskValue: number) => { return 'person' },mask: {toCanvasImageSource(): ...toImageData(): ...toTensor(): ...getUnderlyingType(): ...}}

初版实现

参考 MediaPipe SelfieSegmentation 模型 官方实现(https://github.com/tensorflow/tfjs-models/blob/master/body-segmentation/README.md#bodysegmentationdrawmask),未做优化的情况下 CPU 占用 70% 左右

const canvas = document.createElement('canvas')canvas.width = videoEl.videoWidthcanvas.height = videoEl.videoHeightasync function detect (): Promise {const segmentation = await segmenter.segmentPeople(videoEl)const foregroundColor = { r: 0, g: 0, b: 0, a: 0 }const backgroundColor = { r: 0, g: 0, b: 0, a: 255 } const mask = await toBinaryMask(segmentation, foregroundColor, backgroundColor) await drawMask(canvas, canvas, mask, 1, 9)// 导出Mask图片,需要的是轮廓,图片质量设为最低handler(canvas.toDataURL('image/png', 0)) window.setTimeout(detect, 33)} detect().catch(console.error)

降低提取频率,平衡 性能-体验

一般视频 30FPS,尝试弹幕遮罩(后称 Mask)刷新频率降为 15FPS,体验上还能接受

window.setTimeout(detect, 66) // 33 => 66

此时,CPU 占用 50% 左右

解决性能瓶颈

分析火焰图可发现,性能瓶颈在 toBinaryMask 和 toDataURL

重写toBinaryMask

分析源码,结合打印segmentation的信息,发现segmentation.mask.toCanvasImageSource可获取原始ImageBitmap对象,即是模型提取出来的信息。尝试自己编写代码,将ImageBitmap转换为遮罩(Mask),以代替使用开源库所提供的默认实现。

实现原理

async function detect (): Promise {const segmentation = await segmenter.segmentPeople(videoEl) context.clearRect(0, 0, canvas.width, canvas.height)// 1. 将`ImageBitmap`绘制到 Canvas 上context.drawImage(// 经验证 即使出现多人,也只有一个 segmentationawait segmentation[0].mask.toCanvasImageSource(),0, 0,canvas.width, canvas.height)// 2. 设置混合模式context.globalCompositeOperation = 'source-out'// 3. 反向填充黑色context.fillRect(0, 0, canvas.width, canvas.height)// 导出Mask图片,需要的是轮廓,图片质量设为最低handler(canvas.toDataURL('image/png', 0)) window.setTimeout(detect, 66)}

第 2、3 步相当于给人像区域外的内容填充黑色(反向填充ImageBitmap),是为了配合css(mask-image), 不然只有当弹幕飘到人像区域才可见(与目标效果正好相反)。

globalCompositeOperation MDN(https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation)

此时,CPU 占用 33% 左右

多线程优化

我原先认为toDataURL是由浏览器内部实现的,无法再进行优化,现在只有优化toDataURL这个耗时操作了。

虽没有替换实现,但可使用 OffscreenCanvas (https://developer.mozilla.org/zh-CN/docs/Web/API/OffscreenCanvas)+ Worker,将耗时任务转移到 Worker 中去, 避免占用主线程,就不会影响用户体验了。

并且ImageBitmap实现了Transferable接口,可被转移所有权,跨 Worker 传递也没有性能损耗(https://hughfenghen.github.io/fe-basic-course/js-concurrent.html#%E4%B8%A4%E4%B8%AA%E6%96%B9%E6%B3%95%E5%AF%B9%E6%AF%94)。

// 前文 detect 的反向填充 ImageBitmap 也可以转移到 Worker 中// 用 OffscreenCanvas 实现, 此处略过 const reader = new FileReaderSync()// OffscreenCanvas 不支持 toDataURL,使用 convertToBlob 代替offsecreenCvsEl.convertToBlob({type: 'image/png',quality: 0}).then((blob) => {const dataURL = reader.readAsDataURL(blob)self.postMessage({msgType: 'mask',val: dataURL})}).catch(console.error)

可以看到两个耗时的操作消失了

此时,CPU 占用 15% 左右

降低分辨率

继续分析,上图重新计算样式(紫色部分)耗时约 3ms

Demo 足够简单很容易推测到是这行代码导致的,发现 imgStr 大概 100kb 左右(视频分辨率 1280x720)。

danmakuContainer.style.webkitMaskImage = `url(${imgStr})

通过canvas缩小图片尺寸(360P甚至更低),再进行推理。

优化后,导出的 imgStr 大概 12kb,重新计算样式耗时约 0.5ms。

此时,CPU 占用 5% 左右

启动条件优化

虽然提取 Mask 整个过程的 CPU 占用已优化到可喜程度。

当在画面没人的时候,或没有弹幕时候,可以停止计算,实现 0 CPU 占用。

无弹幕判断比较简单(比如 10s 内收超过两条弹幕则启动计算),也不在该 SDK 实现范围,略过

 判定画面是否有人

第一步中为了高性能,选择的模型只有ImageBitmap,并没有提供肢体点位信息,所以只能使用getImageData返回的像素点值来判断画面是否有人。

画面无人时,CPU 占用接近 0%

发布构建优化

依赖包的提交较大,构建出的 bundle 体积:684.75 KiB / gzip: 125.83 KiB

所以,可以进行异步加载SDK,提升页面加载性能。

  1. 分别打包一个 loader,一个主体
  2. 由业务方 import loader,首次启用时异步加载主体

这个两步前端工程已经非常成熟了,略过细节。

运行效果

总结

过程

  • 选择高性能模型后,初始状态 CPU 70%
  • 降低 Mask 刷新频率(15FPS),CPU 50%
  • 重写开源库实现(toBinaryMask),CPU 33%
  • 多线程优化,CPU 15%
  • 降低分辨率,CPU 5%
  • 判断画面是否有人,无人时 CPU 接近 0%

CPU 数值指主线程占用

注意事项

  • 兼容性:Chrome 79及以上,不支持 Firefox、Safari。因为使用了OffscreenCanvas
  • 不应创建多个或多次创建segmenter实例(bodySegmentation.createSegmenter),如需复用请保存实例引用,因为:
  • 创建实例时低性能设备会有明显的卡顿现象
  • 会内存泄露;如果无法避免,这是mediapipe 内存泄露 解决方法(https://github.com/google/mediapipe/issues/2819#issuecomment-1160335349)

经验

  • 优化完成之后,提取并应用 Mask 关键计算量在 GPU (30%左右),而不是 CPU
  • 性能优化需要业务场景分析,防挡弹幕场景可以使用低分辨率、低刷新率的 mask-image,能大幅减少计算量
  • 该方案其他应用场景:
  • 替换/模糊人物背景
  • 人像马赛克
  • 人像抠图
  • 卡通头套,虚拟饰品,如猫耳朵、兔耳朵、带花、戴眼镜什么的(换一个模型,略改)
  • 关注Web 神经网络 API (https://mp.weixin.qq.com/s/v7-xwYJqOfFDIAvwIVZVdg)进展,以后实现相关功能也许会更简单

本期作者

                                                                               刘俊   

哔哩哔哩资深开发工程师


# 异步  # 重写  # 加载  # 客户端  # 设为  # 点位  # 开源  # 人时  # 的是  # 弹幕  # 性能优化  # https  # tensorflow  # github  # canvas  # 浏览器  # 对象  # JS  # 主线程  # 多线程  # 线程  # 接口  # 数据结构  # html  # safari  # chrome  # css  # firefox  # JavaScript  # canva 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 网络优化91478 】 【 技术知识72672 】 【 云计算0 】 【 GEO优化84317 】 【 优选文章0 】 【 营销推广36048 】 【 网络运营41350 】 【 案例网站102563 】 【 AI智能45237


相关推荐: 如何用AI帮你把小说改编成电影剧本?3步掌握核心技巧  音乐天赋自测:你天生拥有绝对音感吗?15个问题揭晓  探索占星术:揭秘 कुंडली 中的 शुक्र,财富与运势的钥匙  动漫肌肉美学:盘点最佳动漫肌肉男体格  Midjourney怎样加参数调细节_Midjourney参数调整技巧【指南】  文心一言辅助学习方法 解决难题与知识点梳理使用指南  Django与React构建AI音乐推荐:数据库集成实战指南  美图秀秀AI抠图如何换背景_美图秀秀AI背景替换与贴纸添加【攻略】  批改网AI检测工具怎样开启实时检测_批改网AI检测工具实时检测开启与延迟设置【指南】  AI周报生成工具有哪些_一键生成工作总结的AI工具推荐  n8n:零代码AI自动化平台的终极指南和免费VPS设置  批改网AI检测工具怎么关联班级学生_批改网AI检测工具班级绑定与学生管理【步骤】  Google Gemini 辅助进行 Android Studio 代码开发  百度ai助手通知栏怎么关 百度ai助手通知消息屏蔽  Tune AI: 革新音乐创作,AI音乐平台深度测评  利用 Google AI 进行图像元数据分析与整理  System of a Down:深度剖析《Hypnotize》歌词  EdrawMax全面评测:使用AI轻松绘制流程图和思维导图  AI广告全面解析:免费教程、JSON提示与营销策略  标准渣打银行电子账单下载完全指南:轻松管理财务  kimi生成ppt怎么编辑文字_kimi编辑文字后怎么保存  PandaDoc vs. SignEasy: 2025 eSignature 平台终极对比  AI在软件测试中的应用:提升效率与质量的关键策略  文心一言辅助进行中文播客脚本起草教程  Midjourney怎样用参数调分辨率_Midjourney分辨率调整技巧【教程】  利用 DeepSeek 辅助进行编译器原理课程学习  Gemini怎样用快捷指令_Gemini快捷指令使用教程【步骤】  TopMedi AI:AI语音克隆和文本转语音终极指南  Ocfotech AI 房地产工具:提升房地产投资效率的终极指南  宠物翻译App评测:与猫狗交流的未来科技?  AI写作工具检测:学生如何避免学术不端行为  豆包AI的发现页面有什么功能_探索热门智能体与话题  AI人像摄影新纪元:Gemini AI助力照片编辑  Notion AI整理笔记怎么用_Notion AI整理笔记使用方法详细指南【教程】  TechInternPath.ai:AI驱动的实习之路,助你梦想成真  tofai怎么调整层级顺序 tofai图层上下移动方法【步骤】  Fotor懒设计AI排版怎么调整配色方案_Fotor懒设计AI排版配色优化方法【指南】  AI数字人教程:轻松打造专属YouTube虚拟形象  AI猴子视频制作终极指南:从入门到网红,轻松上手!  找不到百度AI助手入口 最新官网登录入口  AI面试助手:提升招聘效率的终极工具  千问怎样用提示词获取健康建议_千问健康类提示词注意事项【指南】  CharSnap AI:终极角色扮演与群聊平台指南  动态规划解题:攀登楼梯的独特方法与技巧  如何用AI设计一个Logo?5个步骤教你打造专属品牌标志  免费高效获客!ChatGPT助你快速生成潜在客户名单  飞猪旅行AI如何预约抢票_飞猪AI抢票预约与加速包使用【攻略】  Wix AI:无需代码免费创建专业网站完整指南  雷小兔ai智能写作如何生成日记_雷小兔ai智能写作日记模板调用【步骤】  feelin聊天官方网站入口 feelinAl官方网站 

 2023-06-10

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

南京市珐之弘网络技术有限公司


南京市珐之弘网络技术有限公司

南京市珐之弘网络技术有限公司专注海外推广十年,是谷歌推广.Facebook广告全球合作伙伴,我们精英化的技术团队为企业提供谷歌海外推广+外贸网站建设+网站维护运营+Google SEO优化+社交营销为您提供一站式海外营销服务。

 87067657

 13565296790

 87067657@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.