news 2026/9/19 17:19:08

Bilibili-Evolved 弹幕下载功能深度解析:XML / JSON / ASS 三种格式的获取原理与播放器设置联动

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Bilibili-Evolved 弹幕下载功能深度解析:XML / JSON / ASS 三种格式的获取原理与播放器设置联动

Bilibili-Evolved 弹幕下载功能深度解析:XML / JSON / ASS 三种格式的获取原理与播放器设置联动

【免费下载链接】Bilibili-Evolved强大的哔哩哔哩增强脚本项目地址: https://gitcode.com/gh_mirrors/bi/Bilibili-Evolved

导读

本文基于 Bilibili-Evolved 仓库中registry/lib/components/video/danmaku/download组件的实现,完整解析"下载弹幕"功能的三种输出格式(XML、JSON、ASS)、基于 protobuf 的分段拉取流程,以及 ASS 转换如何自动继承哔哩哔哩播放器内的屏蔽与显示设置。读完本文,你将掌握该功能从功能面板点击到文件落盘的全链路原理,并能在此基础上自行扩展弹幕导出能力。

功能定位与使用入口

在视频(含番剧)页面中,启用该功能后即可从功能面板下载当前视频的弹幕。组件元数据定义在 index.ts,其关键字段如下:

  • name: 'downloadDanmaku'displayName: '下载弹幕',标签为componentsTags.video,属于视频类组件;
  • urlInclude: videoAndBangumiUrls,即仅在视频与番剧页面生效;
  • widget.condition: hasVideo,功能面板图标仅在检测到视频时显示;
  • 组件无独立入口(entry: none),下载能力完全通过功能面板按钮与"下载视频"插槽两种途径暴露。

功能面板:三种格式一键下载

功能面板组件 DownloadDanmaku.vue 渲染了三个并列的DefaultWidget按钮,分别对应:

按钮名称触发类型
下载弹幕 (XML)download('xml')
下载弹幕 (JSON)download('json')
下载弹幕 (ASS)download('ass')

点击后,组件通过getFriendlyTitle()取得页面友好标题,调用getBlobByType(type)生成 Blob,再交给DownloadPackage.single直接下载,文件名形如视频标题.xml。下载过程中按钮会置灰(disabled)以防止重复触发,异常则通过logError记录。

与"下载视频"功能的集成

除独立下载外,该组件还以插件形式注册到视频下载流程中(index.ts 中的plugin.setup):

  1. 通过addData('downloadVideo.assets', ...)向下载视频功能注册一个"额外产物"(DownloadVideoAssets,其类型定义见 types.ts);
  2. 在批量下载视频时,对每个视频输入调用getBlobByType获取对应格式的弹幕 Blob,并返回{ name: \${title}.${type}`, data: blob }` 作为下载包条目;
  3. 使用Promise.allSettled并发处理多个视频,实时通过 Toast 显示进度(获取弹幕中... (n/m)),完成后提示成功与失败数量;
  4. 格式选择由 Plugin.vue 提供,下拉项为['无', 'ass', 'json', 'xml'],选择结果写入downloadVideo组件的options.danmakuType

三种下载格式及其数据来源

DanmakuDownloadType = 'json' | 'xml' | 'ass'(定义于 utils.ts)。所有格式都基于同一份内存数据模型JsonDanmaku,它保存了每条弹幕的id / progress / mode / fontsize / color / midHash / content / ctime / weight / pool / attr等字段——这与下文的 protobuf 响应字段一一对应。

getBlobByType(type, { aid, cid })的最终分发逻辑:

  • JSON:直接将jsonDanmakus数组序列化为缩进 2 空格的美化 JSON,MIME 类型text/json,保留弹幕最原始的结构化信息;
  • XML:通过convertToXmlFromJson重新生成符合哔哩哔哩标准的 XML 文档,MIME 类型text/xml
  • ASS:先经convertToAssFromJson调用DanmakuConverter做完整字幕转换,MIME 类型text/ass

JSON 格式

JSON 是最忠实的原始数据形态,每条弹幕包含progress(毫秒)、mode(弹幕类型)、fontsizecolor(十进制颜色值)、midHash(用户哈希)、ctime(发送时间戳)等全部字段,适合程序化二次处理,例如做弹幕统计、情感分析或自建弹幕库。

XML 格式

convertToXmlFromJson生成的 XML 文档结构如下(danmaku.cid作为chatidmaxlimit为弹幕总数):

<?xml version="1.0" encoding="UTF-8"?> <i> <chatserver>chat.bilibili.com</chatserver> <chatid>123456</chatid> <mission>0</mission> <maxlimit>2048</maxlimit> <state>0</state> <real_name>0</real_name> <source>k-v</source> <d p="10.60800,5,25,16724991,1544806627,0,6d16be9f,9261260365889536">biu</d> </i>

其中每条<d>标签的属性顺序由JsonDanmaku.xmlDanmakus映射而来:发送时间(秒) / 弹幕类型 / 字体相对大小 / 颜色 / Unix时间戳 / 弹幕池 / 用户Hash / 行序号,各字段含义可参考仓库内的格式设计笔记 danmaku-converter.md。生成的 XML 可直接被第三方播放器(如 PotPlayer、mpv 弹幕插件)加载。

ASS 格式与内置限制

ASS 是最适合直接作为字幕文件使用的格式,但需要注意组件说明中明确写出的限制:

请注意 ASS 弹幕下载不会包含高级弹幕, 字幕弹幕等。

该限制的实现依据在转换配置中:默认blockTypes: [7, 8],而 7~8 正是"高级弹幕"类型(见 danmaku-converter.md 的弹幕类型表:1~3 普通、4 底端、5 顶端、6 逆向、7~8 高级)。DanmakuConverter.xmlDanmakuToAssDocument(danmaku-converter.ts)在处理时会跳过这些类型,同时也会跳过命中用户屏蔽词/屏蔽用户的弹幕。

底层数据获取:基于 protobuf 的分段弹幕拉取

弹幕原始数据并非一次接口调用即可获取,而是先请求配置接口获知分段总数,再并发拉取各分段。这一流程封装在JsonDanmaku.fetchInfo()中,实际网络请求位于 danmaku-segment.ts:

  1. 获取弹幕配置getDanmakuView(aid, cid)请求https://api.bilibili.com/x/v2/dm/web/view?type=1&oid={cid}&pid={aid},得到DmWebViewReply,其中dmSge.total表示弹幕分段总数;
  2. 并发拉取分段getDanmakuSegment(aid, cid, index)请求https://api.bilibili.com/x/v2/dm/web/seg.so?type=1&oid={cid}&pid={aid}&segment_index={index+1},返回DmSegMobileReplyelems为该段弹幕列表;
  3. 解码与合并:响应为 protobuf 二进制,通过运行时加载的 protobuf 库(protobufLibrary)按proto中定义的消息结构解码,再flat()合并全部分段,按progress升序排序后存入jsonDanmakus

从源码结构可以推断,分段并发拉取的方式对大弹幕量的视频(如热门番剧、演唱会)能显著缩短等待时间;任何一段失败都会向上抛出,由调用方的Promise.allSettled汇总为"失败 n 个"的提示。

ASS 转换原理:自动继承播放器设置

ASS 下载的独特价值在于转换结果并非固定模板,而是自动继承用户当前播放器内的弹幕显示与屏蔽设置。这一逻辑集中在getUserDanmakuConfig()(utils.ts),其读取链路为:调用loadDanmakuSettingsPanel()确保设置就绪 → 读取localStorage中的bilibili_player_settings→ 通过playerAgent.getPlayerConfig逐项读取。

默认配置(无播放器设置时的兜底)

配置项默认值含义
font'微软雅黑'弹幕字体
alpha0.4弹幕透明度
duration顶部/底端 4 秒,其余 6 秒单条弹幕持续时长
blockTypes[7, 8]屏蔽的弹幕类型(高级弹幕)
resolution1920 × 1080字幕画布分辨率
bottomMarginPercent0.15底部留白比例(防挡字幕)
boldfalse是否加粗

与播放器设置的联动项

  • 屏蔽类型:读取block.type_scroll / type_top / type_bottom / type_color四项开关,分别映射为滚动(1,2,3)、顶端(5)、底端(4)、彩色弹幕,未屏蔽的类型才参与转换,并始终追加 7、8(高级弹幕不转换);
  • 加粗dmSetting.bold
  • 透明度alpha = 1 - dmSetting.opacity,经lodash.clamp(…, 0, 1)约束范围;
  • 分辨率:由dmSetting.fontsize计算缩放因子resolutionFactor = 1.4 - 0.4 × fontsize(默认 1),再乘以 1920×1080 得到画布尺寸——播放器字号越大,导出的 ASS 画布越大,以保持视觉比例一致;
  • 持续时长:滚动弹幕时长按18 - 3 × speed计算,speed取自dmSetting.speedplus(或组件隐藏选项downloadDanmakuOptions.speed手动指定,见 options.ts,默认'auto'),顶部/底端固定 4 秒;
  • 底部间距dmSetting.danmakuArea小于 100 时按百分比换算,等于 100(无区域限制)时归零;此时若开启防挡字幕dmSetting.preventshade,则回退为 0.15;
  • 用户屏蔽:读取block.list,逐条支持三种屏蔽类型——keyword(内容包含关键词)、regexp(正则匹配)、user(按userHash匹配),命中即从 ASS 中剔除,且只应用处于开启状态(s: true)的条目;
  • 字体:直接从页面 DOM 中读取播放器弹幕设置面板当前选中的字体文本(选择器为.bilibili-player-video-danmaku-setting-right-font或新版.bpx-player-dm-setting-right-content-fontfamily下的.bui-select-result),因为 localStorage 中保存的是更复杂的 font-family 解析串。

若读取失败或未找到播放器设置(bilibili_player_settings不存在),则整体回退到上表默认配置,保证任何环境下都能正常导出。

XML → ASS 的格式转换细节

转换器 DanmakuConverter 按 danmaku-converter.md 中记录的 ASS 规范生成字幕:

  • 按字体大小(18/25/30/36/45)映射为 Small/Medium/Large/Larger/ExtraLarge 五种样式,字号分别为 36/52/64/72/90,并通过alpha生成形如&H66FFFFFF的 ASS 颜色(&HAA为透明度十六进制);
  • 颜色以\c&H<bb><gg><rr>&形式输出(注意 BGR 字节序),边框色用\2c
  • 滚动弹幕使用\move(x1,y1,x2,y2)标签,固定弹幕使用\pos(X,Y),底部留白由DanmakuStack依据bottomMarginPercent计算纵向位置,避免弹幕堆叠重叠;
  • 弹幕内容经normalizeContent规范化处理,避免非法字符破坏字幕文件。

相关源码文件索引

  • 组件入口与插件注册
  • 下载逻辑与配置读取
  • 功能面板按钮
  • 下载视频集成面板
  • 组件隐藏选项
  • protobuf 弹幕接口与解码
  • ASS 转换器
  • XML / ASS 格式设计笔记
  • 视频下载额外产物类型定义

以上即可完整回答"下载弹幕"功能的三个核心问题:数据从哪来(protobuf 分段接口)、能导出成什么(JSON / XML / ASS)、导出时如何继承用户设置(播放器设置联动与 ASS 转换器)。

【免费下载链接】Bilibili-Evolved强大的哔哩哔哩增强脚本项目地址: https://gitcode.com/gh_mirrors/bi/Bilibili-Evolved

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/19 17:17:14

零成本双语字幕实战:PotPlayer AI字幕与实时翻译配置全攻略

如果你手头有大量外语视频、生肉剧集、海外公开课&#xff0c;或者经常需要把会议录音快速变成可读字幕&#xff0c;PotPlayer 的 AI生成字幕和实时翻译功能&#xff0c;绝对能直接改变你的观影和工作效率。这篇文章不是产品介绍&#xff0c;而是把我自己实际跑通的完整流程拆开…

作者头像 李华
网站建设 2026/9/19 17:16:03

SpringBoot+Vue3构建美食推荐商城系统实战

1. 项目概述这个Java Web美食推荐商城系统采用了当前主流的技术栈组合&#xff1a;SpringBoot2Vue3MyBatis-PlusMySQL8.0。作为一个全栈项目&#xff0c;它完美展现了前后端分离架构在现代电商系统中的典型应用。我去年在开发类似项目时&#xff0c;这套技术组合的稳定性和开发…

作者头像 李华
网站建设 2026/9/19 17:15:59

用python-pptx拆解工业机器视觉报告:数据口径与验证方法

简介&#xff1a;2024年工业机器视觉行业分析报告以PPT形式呈现&#xff0c;聚焦智能制造与工业自动化赛道&#xff0c;面向行业分析师、企业决策者及技术研发人员&#xff0c;帮助读者快速把握行业全貌与关键趋势。报告设置行业概况与趋势、政策与法规环境、市场需求与消费者行…

作者头像 李华
网站建设 2026/9/19 17:14:54

树的三种存储表示方法详解:双亲、孩子、孩子兄弟表示法

先说个现象。我见过不少同学&#xff0c;学树的时候能把定义背得滚瓜烂熟——节点、根、叶子、子树、深度、层次&#xff0c;说起来头头是道&#xff0c;真让写代码就卡住了。原因倒也不复杂&#xff1a;树在逻辑上非常直观&#xff0c;可一旦要落到内存里&#xff0c;立刻就会…

作者头像 李华
网站建设 2026/9/19 17:14:45

davinci-codex 身份验证失败?TaoToken 这样改 requests 的请求地址

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

作者头像 李华
网站建设 2026/9/19 17:13:03

RealSense D455 深度相机实战指南:从第一帧深度图到调参的完整上手

RealSense D455 深度相机实战指南&#xff1a;从第一帧深度图到调参的完整上手 【免费下载链接】librealsense RealSense SDK 项目地址: https://gitcode.com/GitHub_Trending/li/librealsense 机器人要在 0.8 米外判断有没有障碍物&#xff0c;靠普通彩色相机是做不到的…

作者头像 李华