防挡脸弹幕,即大量弹幕飘过,但不会遮挡视频画面中的人物,看起来像是从人物背后飘过去的。
机器学习已经火了好几年了,但很多人都不知道浏览器中也能运行这些能力;
本文介绍在视频弹幕方面的实践优化过程,文末列举了一些本方案可适用的场景,期望能开启一些脑洞。
mediapipe Demo(https://google.github.io/mediapipe/)展示
☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜
up 上传视频
服务器后台计算提取视频画面中的人像区域,转换成 svg 存储
客户端播放视频的同时,从服务器下载 svg 与弹幕合成,人像区域不显示弹幕
客户端播放视频同时,实时从画面提取人像区域信息,将人像区域信息导出成图片与弹幕合成,人像区域不显示弹幕。
对比传统(|直播|SEI实时)方案
优点:
缺点:
众所周知,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
分析源码,结合打印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/do
cs/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,提升页面加载性能。
这个两步前端工程已经非常成熟了,略过细节。
注意事项
本期作者
刘俊
哔哩哔哩资深开发工程师
# 异步
# 重写
# 加载
# 客户端
# 设为
# 点位
# 开源
# 人时
# 的是
# 弹幕
# 性能优化
# 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
南京市珐之弘网络技术有限公司专注海外推广十年,是谷歌推广.Facebook广告全球合作伙伴,我们精英化的技术团队为企业提供谷歌海外推广+外贸网站建设+网站维护运营+Google SEO优化+社交营销为您提供一站式海外营销服务。