目的
直接利用 VOICEVOX 编辑器的.vvproj,让 Laravel 能重新生成 Talk / Song。
顶层结构
.vvproj 是 UTF-8 JSON。Talk 与 Song 保存在同一个文件中。
| Key | 内容 |
|---|---|
appVersion | 保存时的编辑器版本 |
talk | Talk 用数据(audioKeys + audioItems) |
song | Song 用数据(速度、拍号、轨道群) |
talk 部分
talk.audioKeys 是有序数组,talk.audioItems 是以 ID 为键的 Record。
TalkAudioItem
| Key | 内容 |
|---|---|
text | 输入文本 |
voice.engineId | 引擎 ID(对应 /engine_manifest) |
voice.speakerId | 说话人 UUID |
voice.styleId | Style ID。可直接传给 /synthesis?speaker={styleId} |
query | 等同于 AudioQuery |
presetKey | 编辑器的预设 ID。Laravel 侧的预设请参见 预设 |
.vvproj 已保存有 query,则可以不再执行 /audio_query,直接进入合成。
accentPhrases
| Key | 内容 |
|---|---|
moras | mora 数组(consonant 类字段可能被省略) |
accent | 重音位置(从 1 开始) |
pauseMora | 在标点等处插入静音时可能会存在 |
isInterrogative | 疑问句标志 |
song 部分
| Key | 内容 |
|---|---|
tpqn | Ticks Per Quarter Note。标准为 480 |
tempos | 速度表(position 为 tick) |
timeSignatures | 拍号表(measureNumber 从 1 开始) |
tracks | 以 Track ID 为键的 Record |
trackOrder | 显示/播放顺序。需与 tracks 的键集合一致 |
Track
| Key | 内容 |
|---|---|
singer.styleId | 最终传给 /frame_synthesis?speaker={styleId} 的 ID |
notes | 音符数组 |
keyRangeAdjustment | 以半音为单位的调号调整 |
volumeRangeAdjustment | 音量调整 |
pitchEditData / volumeEditData | 按帧的编辑数据 |
phonemeTimingEditData | 每个 Note ID 的音素时长编辑 |
solo / mute | 用于判定播放对象轨道 |
Note
| Key | 内容 |
|---|---|
id | 音符 ID(唯一) |
position | 音符开始 tick |
duration | 音符长度 tick |
noteNumber | MIDI 音符编号 |
lyric | 歌词 |
tick、秒、帧的转换
在单一速度下按以下方式换算。tempos 按 position 升序累加各区间。
Note::len() helper 将 tick 转换为帧长的实现请参考 Score 与 Note 详解。
Song 音频生成流程
直接编辑时的注意事项
- 必须使
tracks的键集合与trackOrder一致 talk.audioKeys与talk.audioItems同样需要保持同步- 保持
position >= 0、duration >= 1、noteNumber处于0..127 tempos[0].position通常为0,timeSignatures[0].measureNumber通常为1- 未知的 key 尽可能保留并重新保存,以避免破坏与未来版本的兼容性
Laravel 代码示例
以下是读取.vvproj 并生成 Talk 与 Song 的最小示例。