最近在研究 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!)