使用社交账号登录
最近在继续做 @dan-uni/dan-any 的弹幕解析支持,发现网上没什么人对爱奇艺的弹幕格式有详细研究,故将研究过程公开,方便后人查阅资料。
关于爱奇艺的弹幕获取可以自行网络搜索,这个的文章还是挺多的。
请参考对话记录
基于该仓库提供的大量弹幕数据
得到以下总结文档:
统计范围:jxnd_XML/*/*.xml
bulletInfo 总数:139,463showTime 范围:1 - 2,735 秒,符合约 43-46 分钟剧集长度contentId 唯一率:100%,前 13 位可解释为毫秒时间戳,范围约为 2021-02-01 到 2021-06-16每条均出现的字段:
contentId, content, parentId, showTime, font, color, opacity, position, background, isReply, likeCount, plusCount, dissCount, isShowLike, userInfo, contentType, subType, src, spoiler, halfScreenShow, scoreLevel
几乎每条均出现:
emotionType:139,453 / 139,463,缺失 10 条稀有额外字段:
minVersion:1,018 条,含 iPhone/iPad/GPhone/GPad,值均为 9.6.0songId:43 条mentionedTitle / mentionedTvid:6 条未在样本中出现的接口字段:
variableEffectIdisShowLikeTestisShowReplyFlagreplyCntimageEmotionType| 字段 | 取值/范围 | 数据规律 | 含义推断 |
|---|---|---|---|
contentId | 139,463 个唯一 bigint | 前 13 位落在 2021-02-01 到 2021-06-16 的毫秒时间戳范围 | 弹幕唯一 ID,包含或派生自创建时间 |
content | 98,355 个唯一文本 | 长度 1-50,均值 8.34,中位数 7;高频为“哈哈哈哈”“泪目”等 | 弹幕正文 |
parentId | 0 为 138,468 条,非 0 为 995 条 | 非 0 的 parentId 中 976 条能在本数据集 contentId 中找到 | 回复目标弹幕 ID;0 表示普通弹幕 |
showTime | 1-2735 | 各集最大值约 2590-2735 秒 | 弹幕出现时间,单位秒 |
font | 0,1,2,3,4,14,20,30,99999,100001,100002,100003,100007 | 和 opacity、color 强相关;14/20 常配小写色值,0/1/2/3/4 常配大写色值 | 字体/字号/样式编码,不只是字号 |
color | 15 种字符串 | 白色最多:ffffff 82,797,FFFFFF 47,642;还有 d8b67e, 20fff3, ff3e3e 等 | RGB 十六进制颜色;大小写可能来自不同客户端/样式体系 |
opacity | 0-10 | 常见值:5、1、8、0;和 font 强相关 | 透明度或样式透明度等级,但不是简单百分比;可能是客户端预设档位 |
position | 0,1,2,3,4,100,200 | 0 占 99.51%;100 有 617 条、200 有 54 条;1-4 极少且都配 font=30 | 位置/展示类型编码。0 普通滚动;100/200 更像特殊高亮/半屏外展示;1-4 可能是固定/特殊轨道 |
background | 全为 0 | 无变化 | 背景样式开关/背景色,当前数据未使用 |
isReply | 全为 null | 与 parentId 不同步 | 该接口未填充的回复标记;判断回复应看 parentId |
likeCount | 0-7742 | 均值 79.55,中位数 6,P90 218,P99 1121 | 点赞数 |
plusCount | 0-5 | 97.84% 为 0 | 额外正向计数,可能是“加一/附加赞”,但证据弱 |
dissCount | 0-950 | 82.95% 为 0,P99 14 | 点踩/负反馈数 |
isShowLike | false 103,540;true 35,923 | true 的 likeCount 最小为 20;false 的 P99 为 19 | 是否在前端显示点赞/热度样式;基本由点赞数阈值触发 |
contentType | 0,100,200 | 0 为普通;100 有 1,017 条;200 有 68 条 | 内容类型。100/200 为特殊弹幕类型,但仅凭本数据不能精确定义名称 |
subType | 0,20,25 | 20 共 6 条且均带 mentionedTitle/Tvid;25 共 43 条且均带 songId | 子类型。20=提及/关联剧集;25=音乐/BGM 识别关联 |
src | 0,7,10 | 0 占 99.85%;7 有 176 条,10 有 40 条 | 来源渠道/客户端来源编码,数据中无法精确映射到平台名称 |
spoiler | 全为 false | 无变化 | 剧透标记,当前数据无剧透弹幕 |
halfScreenShow | 1: 138,372;0: 1,091 | 0 与 position=100/200、contentType=100/200、subType=20 明显相关 | 是否允许半屏/普通弹幕区域展示。0 多为特殊展示弹幕 |
scoreLevel | 1,2,3 | 3: 81,730;2: 34,763;1: 22,970 | 内容质量/审核/推荐等级;3 更像正常或高等级,1 较低 |
emotionType | 0,1 | 0: 135,608;1: 3,845;缺失 10 | 情绪/表情相关标记,但样本中 1 内容多为普通文本,具体语义不确定 |
| 字段 | 统计 | 含义推断 |
|---|---|---|
userInfo.uid | 52,314 个唯一值 | 用户 ID |
userInfo.name | 52,289 个唯一值 | 用户昵称 |
userInfo.senderAvatar | 38,936 个唯一值;默认头像占比较高 | 头像 URL |
userInfo.udid | 40,524 个唯一值;null 32,631 条;空字符串 277 条 | 设备标识,部分客户端不提供 |
| 字段 | 统计 | 含义推断 |
|---|---|---|
songId | 43 条,常见 netease-*, kuwo-*, 数字 ID | 音乐平台歌曲 ID;全部对应 subType=25,内容常含 BGM/音乐相关文本 |
mentionedTitle | 6 条,值为 瞄准、赘婿、绝命后卫师 | 弹幕中被识别/关联的其他剧集标题 |
mentionedTvid | 6 条,与 mentionedTitle 一一对应 | 被提及剧集的爱奇艺 TVID |
minVersion.* | 1,018 条,四端均为 9.6.0 | 该弹幕或样式所需最低客户端版本 |
原接口注释里有几处可以按数据修正:
parentId 不是恒为 0;约 0.71% 是回复,值指向父弹幕 contentId。position 不只有 0/1/2;本数据出现 0/1/2/3/4/100/200。100/200 比 1/2 更常见,且与特殊展示相关。opacity 虽为 0-10,但与 font 强相关,不宜直接写死为“百分比透明度”。contentType 不只有 0;出现 100、200。subType 不只有 0;20 明确对应提及剧集,25 明确对应音乐/BGM。src 不只有 0;出现 7、10。spoiler 在本数据中全为 false,只能说明当前样本无剧透弹幕,不能证明字段恒 false。imageEmotionType、variableEffectId、replyCnt 等在当前 XML 样本中未出现,建议接口类型中标为可选字段。说明:未找到可验证的爱奇艺公开字段枚举文档,因此下面把“数据事实”和“含义判断”分开。能由字段共现稳定确认的标为高置信;样本过少或只可推断的标为低置信。
font 在本数据中不是单纯字号。它与 opacity、color 大小写体系、position 强绑定,更像“客户端弹幕样式/字号档位编码”。
| font | 数量 | 占比 | 共现规律 | 含义判断 |
|---|---|---|---|---|
14 | 54,850 | 39.329% | 永远 opacity=5;可配小写颜色;可出现在 position=0/100/200 | 高置信:普通样式 A,可能是新版/默认常规字号 |
20 | 34,251 | 24.559% | 34,245 条为 opacity=1;全部 position=0;可配小写颜色 | 高置信:普通样式 B,可能是另一档字号/透明度样式 |
2 | 26,932 | 19.311% | 主要 opacity=8;几乎全是 color=FFFFFF;全部 position=0 | 高置信:旧版/另一客户端普通样式档位 |
0 | 19,437 | 13.937% | 永远 opacity=0;全部 position=0;颜色多为大写 FFFFFF | 高置信:旧版/默认样式档位,不代表字号为 0 |
30 | 1,988 | 1.425% | 多为 opacity=1;少数 position=1/2/3/4 全是该 font | 中置信:大字号或特殊样式档位;position=1-4 的特殊弹幕都用它 |
1 | 1,492 | 1.070% | 颜色固定 FFFFFF;opacity 可为 1-10 多档;全部 position=0 | 中置信:旧版/用户自定义样式档位 |
3 | 357 | 0.256% | 颜色固定 FFFFFF;opacity 多档;全部 position=0 | 中置信:旧版/用户自定义样式档位 |
4 | 142 | 0.102% | 颜色固定 FFFFFF;opacity 多档;全部 position=0 | 中置信:旧版/用户自定义样式档位 |
99999 | 6 | 0.004% | 永远 opacity=1、color=d8b67e、position=0 | 低置信:特殊高亮/会员/模板样式 |
100001 | 1 | 0.001% | opacity=1、color=ff3e3e | 低置信:特殊颜色/模板样式 |
100002 | 1 | 0.001% | opacity=1、color=fef102 | 低置信:特殊颜色/模板样式 |
100003 | 2 | 0.001% | opacity=1、color=00ff10 | 低置信:特殊颜色/模板样式 |
100007 | 4 | 0.003% | opacity=1、color=ff3e3e,点赞较高 | 低置信:特殊高亮/模板样式 |
结论:如果要建类型,建议不要把 font 注释成字号。更合适的是:
opacity 取值为 0-10,但它不适合直接理解为百分比透明度。原因是它与 font 高度绑定:font=14 永远是 5,font=20 几乎永远是 1,font=0 永远是 0。
| opacity | 数量 | 占比 | 主要共现 font | 含义判断 |
|---|---|---|---|---|
5 | 55,252 | 39.618% | font=14 为主 | 高置信:font=14 对应的默认透明度/样式档位 |
1 | 36,078 | 25.869% | font=20/30 为主,特殊 10000x 也为 1 | 高置信:font=20/30 对应的默认透明度/样式档位 |
8 | 26,122 | 18.730% | font=2 为主,少量 1/3/4/30 | 高置信:旧版/自定义样式常见透明度档位 |
0 | 19,437 | 13.937% | 只出现在 font=0 | 高置信:font=0 对应的默认透明度/样式档位 |
10 | 815 | 0.584% | font=2/1/3/4 | 中置信:用户自定义透明度档位 |
6 | 583 | 0.418% | font=2/1/3/30 | 中置信:用户自定义透明度档位 |
7 | 387 | 0.277% | font=2/1/3 | 中置信:用户自定义透明度档位 |
3 | 232 | 0.166% | font=2/1 | 中置信:用户自定义透明度档位 |
4 | 228 | 0.163% | font=2/1 | 中置信:用户自定义透明度档位 |
9 | 165 | 0.118% | font=2/1/3/4 | 中置信:用户自定义透明度档位 |
2 | 164 | 0.118% | font=2/1 | 中置信:用户自定义透明度档位 |
结论:可以说它是“透明度等级/样式透明度档位”,但不能写成 0-10 对应 0%-100%,当前数据不支持这个线性解释。
position 是位置或展示类型编码。它确实包含常见弹幕协议里的 0/1/2,但爱奇艺样本中还出现 3/4/100/200。
| position | 数量 | 占比 | 共现规律 | 含义判断 |
|---|---|---|---|---|
0 | 138,779 | 99.510% | 几乎所有 font 都可出现;大多数 halfScreenShow=1 | 高置信:普通滚动弹幕/默认轨道 |
100 | 617 | 0.442% | 永远 font=14、opacity=5;576 条 contentType=100 且 halfScreenShow=0 | 中高置信:特殊位置/特殊展示弹幕,不是普通顶部弹幕 |
200 | 54 | 0.039% | 永远 font=14、opacity=5、contentType=200、halfScreenShow=0 | 中高置信:另一类特殊位置/特殊展示弹幕 |
1 | 3 | 0.002% | 全部 font=30、opacity=1、contentType=0 | 低置信:固定位置之一;样本太少,不能确认是否“顶部” |
2 | 2 | 0.001% | 全部 font=30、opacity=1、contentType=0 | 低置信:固定位置之一;样本太少,不能确认是否“底部” |
3 | 2 | 0.001% | 全部 font=30、opacity=1、contentType=0 | 低置信:固定/特殊轨道位置 |
4 | 6 | 0.004% | 全部来自同一用户,font=30、opacity=1 | 低置信:固定/特殊轨道位置 |
关键判断:
position=0 可确认是默认普通弹幕。position=100/200 与 contentType=100/200、halfScreenShow=0 强绑定,更像爱奇艺客户端特殊展示类型,不应映射为“顶部/底部”。position=1/2/3/4 样本只有 13 条,且都绑定 font=30。虽然常见弹幕协议里 1=顶部、2=底部,但当前爱奇艺数据不足以实证确认。建议类型注释:
scoreLevel 只出现 1/2/3。它不像样式字段,因为各类 font/position/color 中都分布。它和点赞数有明显关系:scoreLevel=1 的点赞中位数显著高于 2/3。
| scoreLevel | 数量 | 占比 | likeCount 中位数 / P90 / 最大值 | isShowLike=true 占比 | 含义判断 |
|---|---|---|---|---|---|
3 | 81,730 | 58.603% | 4 / 88 / 7243 | 16.86% | 中高置信:普通/默认评分等级 |
2 | 34,763 | 24.926% | 6 / 136 / 3220 | 23.91% | 中高置信:中间等级 |
1 | 22,970 | 16.470% | 72 / 685 / 7742 | 60.20% | 中高置信:高热度/高推荐或高权重等级 |
注意:这里的数字方向和直觉可能相反。按样本统计,scoreLevel=1 更常见于高赞弹幕,scoreLevel=3 更常见于普通低赞弹幕。因此如果把它理解成“评分等级”,更像是:
1:高权重/优先展示/精选倾向2:中间等级3:普通默认等级但它也可能是服务端排序或审核打分等级,不一定直接展示给用户。建议注释为:
渲染管线
基于 2026-06-29 抓取的页面和静态资源,页面版本是 17.063.25642,核心入口为:
https://www.iqiyi.com/v_19rrntxeew.html?...https://static.iqiyi.com/js/player_v3/pcweb.wonder.17.063.online.jshttps://www.iqiyi.com/static/js/common-pcwPlayer_d91a9049.39e537cd.jshttps://www.iqiyi.com/static/js/common-pcwPlayer_7bd12dde.7156f81c.jshttps://www.iqiyi.com/static/js/common-pcwPlayer_9f650d08.98931572.js管线大致是:
pcweb.wonder 和 pcwPlayer 相关 chunk。#pcaBarrageContainer。Barrage XPlayer 构建 barrageBridge,把 tvid / vid / cid / aid / duration / paused / currentTime / videoAreaWidth / videoAreaHeight 传给弹幕层。Barrage Player 根据 bridge 参数实例化真实弹幕 SDK:new BarrageClass(params)。play / pause / timeUpdate / switch / switchQuality / show / hide / clear / close。JSBarrageAdapter 负责把 SDK 的设置、屏蔽词、发送结果、模式切换接到播放器 UI。56418 的 SDK 模块里;当前抓到的页面公开 chunk 里只看到引用,没定位到该模块定义,所以单条 font/position/scoreLevel 的官方枚举还不能 100% 反编译确认。关键反推
网页 UI 的“字号设置”不是 XML 里的 font。播放器设置面板中有独立的 fontSize 档位:
这说明 XML 的 font=14/20/30/0/1/2/3/4/99999/10000x 不是简单字号,而是弹幕内容自身的样式编码。网页全局设置只是在 SDK 层整体缩放/覆盖显示字号。
字段结论
font:样式/字号档位编码,不建议注释为纯字号。统计中常见值为 14,20,2,0,30,1,3,4,另有少量 99999/10000x 特殊样式。14、20、2、0 分别和固定 opacity 强绑定,说明它们是不同客户端或不同样式体系的编码。
opacity:取值 0-10,但不是可直接线性换算的百分比。比如 font=14 永远配 opacity=5,font=20 几乎永远配 1,font=0 永远配 0。更准确是“透明度/样式透明度档位”。
position:0 高置信是普通滚动弹幕。100/200 和 contentType=100/200、halfScreenShow=0 强绑定,更像爱奇艺特殊展示弹幕,不应映射成顶部/底部。1/2/3/4 样本极少,且全配 font=30,只能判断为固定/特殊轨道,无法可靠确认每个值的真实 UI 位置。
scoreLevel:不是样式字段,更像服务端权重/质量/排序等级。样本中方向是反直觉的:scoreLevel=1 的点赞和展示倾向最高,3 最普通。所以建议理解为 1=高权重/精选倾向,2=中间,3=普通默认。
建议把接口注释改成:
可以。逆向到当前爱奇艺 PC 网页播放器后,font 和 position 的结论比单纯统计 XML 更明确:
结论
font 在当前 PC 网页播放器里基本不是“单条弹幕实际字号”。播放器会把拉取到的弹幕统一覆盖成全局字号设置。
实际渲染管线里,弹幕进入轨道前会被设置为:
然后 DOM 样式使用:
也就是说,XML 里的:
更像是服务端/历史客户端/样式来源字段,而不是当前 PC 网页逐条弹幕的最终字号。
当前 PC 网页端可确认的实际字号来源是播放器设置:
默认长视频字号约为 24px,迷你/悬浮场景可见默认 14px。所以更准确地说:
XML font | 当前 PC 网页实际意义 |
|---|---|
14 | 不是强制 14px;当前 PC 会用全局 forcedFontSize 覆盖。统计上常和 opacity=5、position=100/200 同现,像顶部/底部类弹幕的来源样式值 |
20 | 不是强制 20px;统计上常见于普通滚动弹幕,可能是旧端/服务端记录的默认字号 |
30 | 不是强制 30px;统计上覆盖少量 position=1/2/3/4,像特殊历史样式来源 |
0/1/2/3/4 | 当前 PC 渲染代码里没有找到它们到实际 px 的枚举映射,更像历史样式码 |
99999/100001/... | 当前 PC 普通渲染路径没有按这些值决定字号;更像特殊主题/模板 ID |
所以如果你的目标是“复刻当前网页版播放器显示”,不要按 bulletInfo.font 逐条设字号,而应使用播放器全局字号档位。
position 的精确对应 这里可以确认得更准。当前 PC bundle 里定义了弹幕类型枚举:
| 值 | 名称 | 实际含义 |
|---|---|---|
0 | NORMAL | 普通滚动弹幕,右向左滚动 |
100 | TOP_NORMAL | 顶部固定普通弹幕 |
200 | BOTTOM_NORMAL | 底部固定普通弹幕 |
108 | TOP_ROLE | 顶部角色弹幕 |
208 | BOTTOM_ROLE | 底部角色弹幕 |
8 | ROLE | 角色弹幕 |
2 | STAR | 明星弹幕 |
10 | STAR_TOPIC | 明星话题弹幕 |
9 | VR | VR 弹幕 |
305 | SURROUND_PORTRAIT | 环绕/画像类弹幕 |
你的 XML 里 position=100/200 基本也同时出现 contentType=100/200,这和播放器枚举完全吻合。因此可以把它们解释为:
但要注意一个关键点:当前 PC 网页渲染主要按 contentType 选择弹幕类型,position 更像随数据一起保留的并行字段。XML 里二者一致时可以放心使用;如果冲突,复刻 PC 网页时应优先信 contentType。
至于你数据里的:
当前 PC 网页播放器没有找到这些数字的现代枚举定义。结合统计,它们数量极少、全部集中在 font=30、contentType=0,更像旧客户端遗留的位置/模板编号。按当前 PC 网页逻辑,它们大概率不会被当作顶部/底部枚举处理,而是落回普通弹幕路径。
参考逆向来源:
https://www.iqiyi.com/static/js/iqiyi-pcw-ui.aee16f12.jshttps://www.iqiyi.com/static/js/common-pcwPlayer_7bd12dde.7156f81c.jshttps://www.iqiyi.com/static/js/common-pcwPlayer_d91a9049.39e537cd.js最终建议的接口解释可以改成:
font: string; // 爱奇艺弹幕样式/字号档位编码;常见 0/1/2/3/4/14/20/30,少量 99999/10000x 特殊样式
opacity: string; // 0-10 的透明度/样式档位;与 font 强绑定,不建议直接按百分比换算
position: string; // 位置/展示类型编码。0=普通滚动;100/200=特殊展示;1/2/3/4 样本极少,疑似固定/特殊轨道
scoreLevel: string; // 服务端弹幕权重/质量/排序等级。样本中 1 更高权重,3 更普通
1 -> 14
2 -> 18
3 -> 26
4 -> 38
font: string; // 爱奇艺弹幕样式/字号档位编码,不是纯字号
opacity: string; // 0-10 的透明度/样式档位,和 font 强绑定
position: string; // 0=普通滚动;100/200=特殊展示;1/2/3/4 疑似固定/特殊轨道
scoreLevel: string; // 服务端弹幕权重/质量/排序等级;样本中 1 权重更高,3 更普通
item.fontSize = setting.config.forcedFontSize
font-size: ${fontSize}px
height / line-height: trackHeight
font: "14" | "20" | "30" | "0" | "2" | ...
danmuFontSize: [14, 20, 24, 30, 42, 50]
position = 0 // 滚动
position = 100 // 顶部固定
position = 200 // 底部固定
position = 1 | 2 | 3 | 4
font: string;
// 历史/来源样式字段。当前 PC 网页实际字号由全局 forcedFontSize 控制,
// 常见档位为 14/20/24/30/42/50px,不应直接把 XML font 当作最终字号。
position: string;
// 0 = 普通滚动
// 100 = 顶部固定
// 200 = 底部固定
// 1/2/3/4 = 历史遗留/特殊模板值,当前 PC 网页未确认有独立显示语义