bloub导出完全指南:SVG、PNG、GIF、MP4四种格式的实现原理与手写LZW编码器
前端图形学【免费下载链接】bloubSVG recreation of the x.ai bot avatar. One shape morphing through 14 states, measured off the reference video frame by frame.项目地址https://gitcode.com/gh_mirrors/bl/bloub点击查看免费下载bloub 是一个用纯 SVG 复刻 x.ai 机器人头像的开源项目一个黑色填充形状在 14 种状态之间平滑变形双眼独立运动。它把导出做到了极致——头像可导出为SVG、PNG、动画 SVG 和 GIF整条时间轴可导出为GIF 或 MP4其中静态格式完全零依赖唯一的视频编码器也在首次请求时才按需加载。本文将带你逐层拆解 bloub 导出功能的实现原理包括那个堪称全项目最精妙的手写 LZW 编码器。一张表看懂四种格式各有什么定位 格式导出对象帧率/尺寸依赖适合场景PNG静态头像1024×1024无canvas所有平台头像Discord 128、X 400、GitHub 500、Slack 512SVG静态头像矢量无级无XMLSerializer要放大、要编辑、要贴进 Figma 的场合动画 SVG静态头像 眼神动画30 关键帧/秒无通用比 GIF 更小更顺GIF头像 / 整个周期20 fps / 320px无手写 LZWDiscord / Slack 动态头像它们拒收 SVGMP4整个周期30 fps / 1024pxmediabunny按需加载展示完整时间轴的场合完整的格式目录定义在 src/ui/export.ts 的ACTIONS常量中官方设计说明见 docs/export.md。SVG 与 PNG序列化活的 SVG而不是重画一遍bloub 导出静态图的第一原则是导出屏幕上的那个 SVG而不是在旁边再造一个。为什么敢这么做因为机器人组件 BloubBot.vue 输出的 SVG 天生自包含没有var(--...)CSS 变量、没有 Tailwind 类名每个形状的fill都是写死的十六进制色值。于是导出只需要三步见 src/ui/capture.tscloneNode克隆屏幕上正在显示的 SVG 节点去掉页面专属的class补上xmlns、viewBox和显式的width/heightFirefox 对没有固有尺寸的 SVG 拒绝栅格化会输出空白画布用XMLSerializer序列化、剥掉 XML 注释就是一份干净的 SVG 文件。PNG 则走 canvas 栅格化把 SVG 包装成 Blob 创建对象 URL而不是data:URL——btoa会被aria-label里的法语重音搞崩解码后drawImage最后canvas.toBlob(image/png)。两个安全前提也值得一提SVG 里没有foreignObject和image元素这是仅有的两种会污染 canvas 导致toBlob失败的东西。另外注意两个刻意的产品决策见 src/ui/export.tsPNG 只给 1024 一种尺寸——要不要更大尺寸不是用户该做的主想要无级放大请拿 SVG不提供静态 GIF——它的透明度只有 1 bitPNG 那里 8 bit alpha 的平滑边缘在 GIF 里会变成锯齿台阶。动画 SVG为什么它比 GIF 更小、还更丝滑在 bloub 里静止时身体几乎是纹丝不动的——实测 3 秒内轮廓只移动 1.17 个单位半径为 100按导出尺寸算约 1.5 个像素。所以活全部来自眼睛目光漂移 眨眼。基于这个测量src/ui/anime.ts 的svgAnime不重建任何图形只把首帧 SVG 中每个眼睛的transform属性替换成一段 CSS 关键帧动画。于是关键帧按 30/s 输出——一个关键帧只是一串矩阵文本密度几乎免费浏览器负责插值——动画按屏幕刷新率平滑播放而 GIF 这类翻页书格式 20 fps 下眨眼0.18 秒只能分到 3~4 帧肉眼可见地卡顿最终成品约16 kB而最早做过的动画 WebP 方案又卡又重167 kB直接淘汰。还有两个不能少的细节transform-box: view-box; transform-origin: 0 0否则 SVG 上的 CSS 变换会绕包围盒中心转眼睛直接飞到球的另一边以及animation-direction: alternate——目光漂移的周期刻意取互质数、永不重复普通循环会在接缝处跳变而往返播放能严丝合缝地闭合成环反转的眨眼依然是眨眼。GIF唯一会提问的导出和它的手写 LZW 编码器GIF 存在的全部理由是平台可达性Discord 和 Slack 接受 GIF 做动态头像但任何地方都不接受 SVG。而它 1 bit 的透明度逼出了唯一的一个交互——GifDialog.vue 会问你要透明底还是白色底透明底的抗锯齿边缘被 50% 阈值切断呈台阶状实心底色则能让边缘有东西可融入而重新变滑。选白底时眼睛本质是填充了paper色的洞必须被替换成背景色否则会留一圈暗环。GIF 的容器在 src/ui/anime.ts 的gifIndexe里逐字节手拼GIF89a头、Netscape 无限循环扩展、每帧的 Graphic Control Extension透明帧用清除至背景消除模式防止拖影实心帧用保持原样防止闪烁帧延迟以百分之一秒为单位、最低 20 和 1 在不同阅读器里行为不一致。手写 LZW 编码器一个 bit 都不能错真正的精华是 anime.ts 中的lzw函数。GIF 用 LZW 压缩bloub 没有引入任何压缩库而是从零实现变长编码、从最低有效位开始逐位写入、超过 255 字节切子块。它藏着一个整个格式唯一的深坑编码器在发出一个代码之后立刻把自己的字典条目写进去而解码器要等到读到下一个代码才写入自己的条目。解码器因此永远落后一个条目编码器扩展码宽的动作也必须相应地晚一步——判断条件必须是suivant (1 taille)绝不能写成。写错这一个比较符两边就会失同步所有阅读器都会拒绝这个文件而文件结构上看不出任何破绽。所以测试 anime.test.ts 干脆内置了一个完整的 GIF 解码器做往返测试把编码流解码回像素逐位比对——结构断言抓不住这种错误只有像素能。调色板按频率选渲染走两遍一个 30 秒的周期有 624 帧、颜色远超 255 种调色板必须取舍。bloub 的做法anime.ts第一遍只统计每种颜色的像素数不保留像素否则会占 255 MB 内存定板取出现最多的255 种颜色index 0 留给透明没被选中的颜色归并到最近邻带缓存每种颜色只找一次第二遍重新渲染渲染是确定性的重放得到一模一样的帧逐帧索引化后编码。实测输出60 帧 320² 的动画 GIF 仅 147 kBChrome 解码回来透明角完好、帧间 2033 个像素在变化。MP4质量旋钮是量化器不是码率导出完整周期是另一道题帧数、码流、内存全都要重新算详见 docs/export.md。帧永远不累积src/ui/video.ts 逐帧渲染、逐帧await source.add(...)——正是这个await把编码器的背压传回来把内存锁死在一帧的规模视频永远不透明VideoEncoder对 H.264 和 VP9 都拒绝alpha: keep所以对话框对 MP4 直接隐藏背景选项组编码器按需加载mediabunny 高达 43 kB gzip静态引入比被否掉的 vue-i18n 还大所以只在导出 MP4 的那一刻动态 import平时网站只多付 0.7 kB 的代价分辨率与帧率按格式分离GIF 受文件体积约束320px/20fps视频压缩的是运动而非逐帧存储理直气壮用 1024px/30fps。混用过的版本测出 93 kbps画质只有缩略图——这正是它看着像 GIF 的根源最反直觉的一点质量旋钮是QUANTIZER量化器 QP不是码率。Chrome 117 支持固定量化器编码时mediabunny 的QUALITY_HIGH等命名档位根本不设码率调高码率什么都改变不了。实测边缘误差QP 22 → 3.06QP 16 → 1.75QP 10 → 0.58。最终 video.ts 显式传new Quality({ quantizer: 12, bitrate })码率只作为不支持固定量化器的浏览器的回退。实测默认周期31.2 秒MP4 936 帧 1024² 仅 5.48 MB、约 4 秒完成如果用MediaRecorder实时录制得干等整整 31.2 秒——编码器胜出。怎么选三句话决策指南 要头像→ 拿 PNG1024 够用一切平台要进 Figma / Illustrator 可编辑 → 复制SVG 文本bloub 特意用writeText而非图片粘贴粘回去才是可编辑矢量要动态头像Discord / Slack→ GIF白底最稳妥要展示整条动画时间轴→ MP41024/30fps需要往群里甩小文件时再考虑 GIF。核心文件速查文件职责src/ui/export.ts纯逻辑层导出画框、文件名规则、各格式参数目录可 node 环境测试src/ui/capture.tsDOM 层SVG 序列化、canvas 栅格化、剪贴板、离屏序列渲染src/ui/anime.ts动画 SVG 组装 GIF 容器拼装 手写 LZW 编码器 频率调色板src/ui/video.tsMP4 编码mediabunny 动态加载、量化器 QP12src/components/GifDialog.vueGIF 背景选择对话框唯一会提问的导出docs/export.md官方导出设计文档含全部实测数据从 XMLSerializer 到手写 LZWbloub 的导出系统证明了一个像素级的复刻项目其输出管线可以和绘制管线一样讲究——每个参数都是测量出来的每个看似多余的测试都在守护一个真实的坑。赞分享前端图形学【免费下载链接】bloubSVG recreation of the x.ai bot avatar. One shape morphing through 14 states, measured off the reference video frame by frame.项目地址https://gitcode.com/gh_mirrors/bl/bloub点击查看免费下载相关推荐Mermaid.js数据导出PNG、SVG、PDF等多种格式的导出方案Mermaid.js数据导出PNG、SVG、PDF等多种格式的导出方案 引言为什么需要图表导出功能 在日常开发和技术文档编写中Mermaid.js已经成图表库前端数据可视化X6 画布导出插件 Export 完全指南SVG / PNG / JPEG 导出 API 与源码级原理X6 画布导出插件 Export 完全指南SVG / PNG / JPEG 导出 API 与源码级原理 X6 是使用 SVG 与 HTML 进行渲染的 Jav前端图形学Gephi导出功能完全指南PNG、SVG、PDF格式的最佳实践Gephi导出功能完全指南PNG、SVG、PDF格式的最佳实践 Gephi作为专业的开源网络可视化平台提供了强大的导出功能让用户能够将精心设计的网络图保存数据可视化数据分析桌面应用创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

多电缆组件:自动化设备线缆集成设计与工程实践

多电缆组件:自动化设备线缆集成设计与工程实践

自动化设备装到一半,柜子里的线还没走完,光动力线、编码器线、抱闸线就好几根,拖链里缠成一团,现场调试的人蹲在地上顺着线一根一根捋。这个场景干过现场的人应该都不陌生。多电缆组件就是为这种事准备的。说得直白一点&#xff0…

2026/10/11 12:04:24 阅读更多 →
基于SSM的物资管理系统开发:从业务建模到库存并发的完整实战指南

基于SSM的物资管理系统开发:从业务建模到库存并发的完整实战指南

1. 从一次原型评审会说起:这类管理系统的第一道坎在哪里 几年前我参加过一个内部项目的原型评审会,做的是一个面向社区基层的物资管理后台。需求文档写得不算薄,流程图、用例图、状态表都齐全,但一进评审环节,业务方和…

2026/10/11 12:03:24 阅读更多 →
V1.0.3读卡服务完全指南:解决Chrome读身份证卡死与兼容问题

V1.0.3读卡服务完全指南:解决Chrome读身份证卡死与兼容问题

简介:神思SS628100型读卡服务安装包V1.0.3,是一款面向神思100型读卡设备使用者的配套安装程序,主要解决读卡控件在谷歌、火狐、360等主流浏览器中无法正常加载或调用的问题。该版本兼顾了门禁控制、考勤管理、支付验证等典型身份识别场景&…

2026/10/11 12:03:24 阅读更多 →

最新新闻

新能源充电站负荷预测数据集构建:从数据对齐到LSTM建模

新能源充电站负荷预测数据集构建:从数据对齐到LSTM建模

简介:新能源充电站负荷预测数据集面向电力系统、智能交通与机器学习领域的研究者与开发者,整合时间序列用电记录、充电行为特征与外部环境参数,可支撑充电负荷预测建模、站点效能评估及电网协同优化研究。整套资源共32个文件,压缩…

2026/10/11 12:53:39 阅读更多 →
2G树莓派5打造完全离线AI语音助手实战

2G树莓派5打造完全离线AI语音助手实战

1. 项目概述:为什么2G树莓派5能撑起一个“完全离线”的AI语音助手?最近刷到不少标题党视频,说什么“8G版树莓派5才配跑AI”,点进去一看,全是调用云端API、依赖网络唤醒词检测、语音转文字扔给OpenAI再回传——这哪是离…

2026/10/11 12:53:39 阅读更多 →
RK3588嵌入式AI手写板全链路实战:从模型训练到NPU部署

RK3588嵌入式AI手写板全链路实战:从模型训练到NPU部署

做嵌入式AI开发这么久,手写板这个项目算是我在RK3588上折腾得最尽兴的一次。很多人觉得手写板不就是一块电磁感应板加个USB线,顶多再配个压感协议,能有什么AI含量?但加上RK3588这块自带6TOPS NPU的算力板子之后,整个玩…

2026/10/11 12:53:39 阅读更多 →
GFPGAN老照片修复Python实战:从源码环境到参数调优

GFPGAN老照片修复Python实战:从源码环境到参数调优

简介:面向图像处理学习者和开发者的GFPGAN老照片修复Python源码工程,以泛用性人脸先验引导修复网络为核心,结合GAN生成对抗机制增强人脸细节,可用于老照片人像修复、画面清晰度恢复等场景。压缩包共51个文件、约6.09MB&#xff0c…

2026/10/11 12:53:39 阅读更多 →
汽车传感器与执行器实战解析:从信号链路到故障排查

汽车传感器与执行器实战解析:从信号链路到故障排查

作为一个常年泡在汽车电子电气系统里的人,我对“Automotive Sensors and Actuators”这个名字再熟悉不过。它既是车辆工程和汽车电子相关专业的一门核心课程,也是电控开发、标定、诊断人员绕不开的基本功。说白了,传感器就是电控系统的“五官…

2026/10/11 12:53:39 阅读更多 →
SL3170 降压恒压150V耐压 内置MOS管 支持输出12V1A

SL3170 降压恒压150V耐压 内置MOS管 支持输出12V1A

在非隔离辅助电源、电动工具、电动自行车和以太网供电等场景中,输入电压往往覆盖十几伏到上百伏,而控制板又常需要稳定的 12V/1A 级供电。森利威尔 SL3170 正是一款面向此类需求的高压 DC-DC 控制器:内置 150V 功率 MOSFET,支持 1…

2026/10/11 12:52:38 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 10:38:42 阅读更多 →