hihkm / DanmakuFactory

支持特殊弹幕的xml转ass格式转换工具
MIT License
577 stars 32 forks source link

如果设计一个新的弹幕文件格式,里面含有什么数据、用什么格式比较合理? #70

Closed Genteure closed 1 year ago

Genteure commented 1 year ago

目前在用python重写,也可以等我的python版本。

Originally posted by @hihkm in https://github.com/hihkm/DanmakuFactory/issues/64#issuecomment-1664284048


我一直想给录播姬设计一个新的弹幕文件格式,主要想解决现有格式的一些问题:

现在格式的优点:

一直以来录播姬输出的弹幕文件很大一部分用户都是直接喂给 DanmakuFactory 转成 .ass 文件了,所以我在考虑现在格式的优点并不是特别重要。并且之后如果设计了一个新的文件格式,可以写个工具转换成原来的 XML 格式。

问题/讨论点:

如果设计一个新的弹幕文件格式,里面保存哪些数据?具体使用什么格式比较好?

我自己目前的考虑:

sieveLau commented 1 year ago

关于存储的数据,根据目前各个处理弹幕文件的repo的issue来看

  1. uid和用户名似乎是多数用户想要的
  2. 弹幕的类型也是常用的字段,特别是直播类弹幕非常需要区别普通、SC和礼物
  3. 对于2,衍生出来的要求就是持续时间,毕竟immersive观看录播通常也会要求SC到期消失

以上三个是当前录播姬会输出的内容。剩下的就是(嘴炮)想法了,毕竟没有认真了解:弹幕的位置,就比如说是上下固定,还是左右移动的。

对于格式……其实我对于xml了解不多。现在貌似,比如说vscode,是喜欢用json来存数据的(为什么说这个呢,因为repo主说在用python重构,而python解析json那是相当的爽),存储各种数据都方便,而且增减字段影响不大……不过要考虑到文件大小的话,这个我没有把握说它就一定会比xml好多少。

lengyanyu258 commented 1 year ago

感谢 Genteure 大大无比优秀的软件给大家带来了诸多便利!(手动打call)

在我看来,既然都录了几个 GiB 的视频文件了,还需要在乎几十上百 MiB 的弹幕数据大小吗?

当然目前的 XML 格式保存弹幕原始数据确实有一点不妥之处。

个人认为,兼容 B 站的弹幕就是 XML 格式存在的唯一优点。有人说,文件格式要么被设计成对机器友好、要么被设计成对人类友好,而 XML 格式两者都不占。那么用 XML 格式应该怎么存储弹幕数据呢?B 站已经给出了答案——

<d p="29.922,1,25,16777215,1595726203,0,a39f0744,36441903090630661">啊这。。。</d>

Danmaku 简化为 d,其他字段的值全部放进 property 简化后的 p 属性中——这样通过去掉所有的语义信息及空格做到了极致的压缩,使得 XML 格式弹幕文件为最小。也许这才是 XML 文件存储弹幕数据的正确方式。

目前通过 DanmakuFactory 转换生成的 ASS 文件大小大约是记录了原始数据的 XML 文件大小的 20%。对于开发者来说文件大小是无所谓,但对于使用者可能就比较敏感,毕竟自己只想要要 p 属性中的数据,又何必拖家带口地背负 raw 属性的累赘呢?如此想来,如果是导出为 XML 格式,那么数据内容必然只与 B 站主站的弹幕数据一致。

如果想用新的文件格式保存弹幕数据,为满足不同的要求,个人认为不至于造个新的格式(增加使用者的负担),在已有的格式中按用途选取即可。比如原始数据保留为 JSON,有 XML 使用需求的再自动导出大幅缩减的 XML 格式,若不想占用太大空间,那么可以将原始数据保存为 SQLite(当然也不至于为节省汉字存储空间而将 UTF-8 编码改为 GB18030 编码),它既方便数据字段的扩展也方便导出为 JSON、XML 等其他格式的文件。

综上所述,个人愚见:

  1. 保存所有数据;
  2. 如果采用 XML 格式,则将所有数据字段展开存储,比如
    {
        "background_bottom_color": "#E2B52B",
        "background_color": "#FFF1C5",
        "gift": {
            "gift_name": "醒目留言",
            "num": 1
        },
        "message": "统一冰红茶,真柠檬,真青春!",
        "message_font_color": "#72110E",
        "price": 100,
        "rate": 1000,
        "time": 300,
        "ts": 1690032220,
        "uid": 99452737,
        "user_info": {
            "uname": "miaomiaomiao来啦",
            "user_level": 10
        }
    }

    展开存储为

    <sc uid="99452737" ts="1690032220" time="300" rate="1000", price="100" message_font_color="#72110E" message="统一冰红茶,真柠檬,真青春!" background_color="#FFF1C5" background_bottom_color="#E2B52B">
      <user_info user_level="10" uname="miaomiaomiao来啦" />
      <gift num="1" gift_name="醒目留言" />
    </sc>

    (改得我有点恶心)由于数据格式进行了修改,许多依照以前格式解析的工具可能也要进行相应的改动。

  3. 如果是 JSON 储存,则直接原样保存即可。
    • 当然为了与之前的生态进行兼容,可能需要提供自动导出 XML 格式的功能(XML 格式的存在仍是刚需);
    • 十多年前 B 站选择了主流的 XML 格式作为数据交换的媒介,这有着当年的时代特征。假如 B 站今年才成立,在新时代下它会选择什么格式呢?我想应该会是 JSON。
  4. 如果采用 SQLite 存储,则需要提供相关的工具:
    • 自动导出生成与 B 站主站弹幕一致的 XML 格式文件的开关选项;
    • 自动导出保存着原始 JSON 格式文件的开关选项;
    • 软件内提供方便扩展数据字段的工具,比如给所有弹幕添加某个属性,或给某个 UID 所发送弹幕的某个属性设置为某个值(也许不能指望大伙儿再自行下载 SQLite 数据库软件学习 SQL 相关知识进行读写操作?);
    • sqlite-wasm 确实不错,但需要做到开箱即用可能比之前的 XML 直接打开要麻烦一点:
      • 将相关库文件保存在软件源目录中;
      • 每个录制的目录下生成 index.html 文件读取当前录制的弹幕数据库?
      • 通过软件打开前端界面,拖动弹幕数据库文件以读取显示相关文档数据?
      • 优点是界面可以变得更华丽好看,还能添加直播流水统计等功能。
    • 怎么处理视频文件的分段?
      • XML 与 JSON 格式可以很直观且方便地进行分段与合并,danmaku_tools 是一个很方便对 XML 数据格式进行处理的工具。
      • SQLite 有必要随着视频分段吗?
      • 分段后再进行合并又会比前两者稍麻烦一点。

暂时考虑这么多,非常感谢 Genteure 大大在软件功能上的开发工作!

hihkm commented 1 year ago

大大好,上面两位大佬的方案我觉得已经是很完美了~

Genteure commented 1 year ago

最近也和其他人在各种群里有一些讨论,暂定的是用 JSONL 作为文件格式,即每行一个 JSON 文本。可能会选一个自定义的文件后缀(而不是直接 .jsonl)。 也有人提出用 CBOR,如果后续觉得有需要的话也可以作为另外一个选项,数据结构和 JSONL 的保持一致即可。

讨论后感觉使用文本格式、保持“记事本可读性”还是挺重要的一个点。要数据密度的话可能流式 gzip 输出成 弹幕.xxx.gz 文件更合理一些。不过之前录播姬导出的 FLV 数据文件出现过 gz 文件无法正常解压的情况,等实际实现的时候还需要多测试测试。

我目前考虑的是每个弹幕都记录发送的绝对时间,比如 unix 时间戳。在文件最后记录参照时间点,弹幕的时间减去参照时间点就是弹幕在视频中应该出现的时间。主要是方便对齐弹幕和视频内容,因为弹幕写入到文件的时候可能还不能确定与视频的时间关系,需要事后再计算。如果在内存中缓存弹幕数据等到得出结论再写入,又有可能使用过多的内存。

Genteure commented 12 months ago

更新:现在B站直播的弹幕连接加了风控,弹幕数据不全也不可靠了,设计新格式这个事应该就不做了。。