24a's blog
0x24a's personal blog.
首页
友情链接
联系我
文章分类
常用标签
友情链接
您正在查看:2025年5月

最近在研究 YAMAHA Vocaloid5 的项目文件(.vpr格式)。

按照对大厂套路的深入理解,后缀名改 zip 零帧起手,果然是个 ZIP 压缩包,里面包含了一个sequence.json,存储了所有的工程数据(音轨、音符、参数等)。

于是写了一个 Python 解析库,把它的结构逆向出来了。

内容分析

解压后主要文件是Project/sequence.json,包含项目的元信息、音轨(tracks)、音符(notes)、效果器等。
命名规则是驼峰命名法,按照 PEP8 要转换一下。

开始逆向!

用 Python 写了一个解析库,主要功能:

  • 读取 VPR 文件 → 转成 Pydantic 模型(带类型检查)。
  • 修改数据(比如改 BPM、音符参数)→ 重新打包成.vpr
  • 性能分析:内置Timer util 类,可以看各部分解析耗时。

示例用法:

from vpr_parser import VPRParser

parser = VPRParser()
project = parser.parse("song.vpr")  # 读取文件
project.title = "New Song Name"    # 改标题
parser.dump(project, "modified.vpr")  # 保存

踩坑记录

奇怪的命名法

YAMAHA 命名规则太奇怪,本来用驼峰命名法,pydantic alias_generator 转换一下的事,结果comp_id这个字段不是compId,而是compID😅
另、有的字段,比如global,是 Python 保留字,需要替换(处理代码如下):

class AliasedBaseModel(BaseModel):
    model_config = ConfigDict(
        alias_generator=lambda x: (
            to_camel(x).replace("Id", "ID")  # this shit is so ass i hate you yamaha 😭
            if x != "global_config"
            else "global"
        ),  # i love pyright randomly giving me 1mil errors ❤️
        populate_by_name=True,
        extra="forbid",
    )

后续计划

  • 给每个字段加入解释文档
  • 有的类型还不是很完善,比如 ControllerEvent 只有几种类型(应该使用 Literal[...]),我却直接用了 str

GitHub 项目vpr-parser(欢迎 Star/PR!)