LayoutSpec 规范文档 — 自定义"歌词布局"
本文档译自日语原版。日语版为正式版本,如有出入以日语版为准。
本文档是 movlyric 歌词布局定义“LayoutSpec”的完整规范。 在应用的“样式编辑器 →“布局”标签 → 布局预设 →“自定义”→ 用 AI 生成…”中使用。
有两个名称相近但完全不同的东西,请不要混淆。
| 决定的内容 | 规范文档 |
|---|---|
| 歌词放在画面的什么位置(本文档) | LAYOUT_SPEC(歌词布局) |
| 歌词文字如何运动(登场、退场、明灭) | ANIMATION_SPEC(文字动作) |
| 在歌词背后绘制的图形、线条 | GRAPHIC_SPEC(背景特效) |
本文档的目标是:只读过此文档的 AI(或人类)也能写出可以直接粘贴到应用中并被接受的 JSON。 文档末尾附有可交给 AI 使用的提示词模板。将本文档整体作为提示词的一部分贴入同样可以正常使用。
1. 概述
LayoutSpec 只决定"一句歌词放在画面何处、如何排列"这一件事。 其中不含任何随时间变化的要素(运动由 AnimationSpec 负责)。
由以下三项决定:
- 位置 — 以画面上的哪个点为基准来放置(
anchors/placement) - 排版方式 — 横排还是竖排、最多折成几行(
writing/maxLines/lineGap/scaleMode) - 错落 — 是否不排成直线而做出错落感(
scatter/baselineRotateDeg/path/charScaleRange/focusWord)
所有用到随机数的项目,在同一首曲子内都是固定的。 只要曲子和样式相同,每次结果都一致,
预览与导出也会一致(placement: "random" / scatter / charScaleRange /
focusWord.pick: "random" 全部由样式的 seed 决定)。
2. JSON 格式完整规范
2.1 根节点:LayoutSpec
{
"writing": "horizontal",
"anchors": [{ "x": 0.5, "y": 0.5, "align": "center" }],
"placement": "fixed"
}
| 键 | 必需 | 类型 | 含义 |
|---|---|---|---|
writing |
✅ | "horizontal" | "vertical" |
横排 / 竖排(从上到下,列从右到左) |
anchors |
✅ | Anchor 数组(1 个以上) | 放置候选点 |
placement |
✅ | "fixed" | "cycle" | "random" |
如何把乐句分配到候选点 |
maxLines |
整数,1 以上 | 折行数(竖排时为列数)。默认 1 = 不折行 | |
lineGap |
数值,0 以上 | 行间距(列间距),相对字号的比例。默认 0.15 | |
scaleMode |
"fixed" | "fill" |
fill = 排满画面宽度(竖排时为高度)的大字排版。默认 fixed |
|
scatter |
Scatter | 逐字的散落效果 | |
baselineRotateDeg |
数值 | 整句的倾斜角度(度)。默认 0 | |
path |
Path | 非直线的排列方式(仅横排) | |
charScaleRange |
[最小值, 最大值] |
逐字大小的浮动范围(仅横排) | |
focusWord |
FocusWord | 放大其中一个单词(仅横排) |
取值与默认值相同的键请不要写。 例如 maxLines: 1 或 scaleMode: "fixed"
应当省略不写(写与不写含义相同,写出来只会让保存内容徒增无用信息)。
2.2 Anchor(放置候选点)
{ "x": 0.5, "y": 0.88, "align": "center" }
| 键 | 必需 | 类型 | 含义 |
|---|---|---|---|
x |
✅ | 0..1 | 画面左端为 0 ~ 右端为 1 |
y |
✅ | 0..1 | 画面上端为 0 ~ 下端为 1 |
align |
✅ | "start" | "center" | "end" |
以锚点为基准,歌词向哪一侧延伸 |
align 在横排时表示左对齐/居中对齐/右对齐,竖排时表示上对齐/居中对齐/下对齐。
放在画面边缘时,请配合调整 align。 例如给 x: 0.08 指定 align: "center",
较长的乐句会溢出画面左侧。想贴靠左端的话应使用 align: "start"。
2.3 placement(乐句的分配方式)
| 值 | 含义 |
|---|---|
"fixed" |
始终使用第 1 个候选点(候选点只有 1 个时用这个) |
"cycle" |
按乐句顺序依次轮流候选点 |
"random" |
从候选点中随机选取(同一首曲子内固定) |
候选点只有 1 个时,这三种取值结果都相同。 只有写了 2 个以上候选点时才有实际意义。
2.4 Scatter(逐字散落)
{ "offsetRatio": 0.25, "rotateDeg": 8 }
| 键 | 必需 | 类型 | 含义 |
|---|---|---|---|
offsetRatio |
✅ | 数值,0 以上 | 位置偏移幅度,相对字号的比例 |
rotateDeg |
✅ | 数值,0 以上 | 旋转摆动幅度(度) |
两者都在同一首曲子内固定。取 0.3 / 12 左右会呈现相当散乱的效果。
2.5 Path(非直线的排列方式,仅横排)
{ "kind": "wave", "amplitude": 0.3, "period": 8 }
| 键 | 必需 | 类型 | 含义 |
|---|---|---|---|
kind |
✅ | "wave" | "arc" | "steps" |
波浪 / 圆弧 / 阶梯 |
amplitude |
✅ | 数值 | 摆动幅度,相对字号的比例 |
period |
数值,大于 0 | 多少个字符一个周期。省略时 wave 为 8,steps 为 3 |
wave 和 arc 会让文字的旋转跟随曲线的切线方向(沿排列方向倾斜)。
arc 不使用 period(整句歌词共同构成一条弧线)。
有多行时,各行会独立应用此效果。
2.6 charScaleRange(文字大小的浮动,仅横排)
[0.85, 1.3]
由 [最小值, 最大值] 两个元素构成。会为每个字符确定一个在该曲子内固定的倍率。
该倍率同时作用于字号与字符间距,因此行宽计算、折行、居中对齐都会一并将这种浮动纳入考虑,保持一致。
2.7 FocusWord(放大其中一个单词,仅横排)
{ "scale": 1.4, "pick": "longest" }
| 键 | 必需 | 类型 | 含义 |
|---|---|---|---|
scale |
✅ | 数值,大于 0 | 目标单词的放大倍率 |
pick |
✅ | "longest" | "random" |
字符数最多(相同则取最前面的)/随机(同一首曲子内固定) |
与 charScaleRange 同时使用时,倍率会相乘。
3. 常见错误(禁止事项)
- 不要在竖排中写
path/charScaleRange/focusWord。 引擎只在横排时解析这些字段, 写了也不会产生任何效果(也不会报错,因此很容易没有察觉)。 - 不要把
anchors设为空数组。 这样会没有放置位置,导致歌词不显示。 - 不要给
x/y写像素值。 它们是 0~1 的比例(应写0.5而不是960)。 - 不要写与默认值相同的键(如
maxLines: 1/lineGap: 0.15/scaleMode: "fixed",或候选点只有 1 个时实质无意义的placement: "cycle"等)。 - 不要写随时间或音频变化的值。 LayoutSpec 中没有数学表达式或动画。 想要运动效果,请交给 AnimationSpec(ANIMATION_SPEC(文字动作))负责。
- 不要写不存在的属性、注释、末尾逗号。
4. 示例
4.1 画面下部单行(卡拉OK经典样式)
{
"writing": "horizontal",
"anchors": [{ "x": 0.5, "y": 0.88, "align": "center" }],
"placement": "fixed"
}
4.2 上下分布,最多折成 2 行
{
"writing": "horizontal",
"anchors": [
{ "x": 0.5, "y": 0.3, "align": "center" },
{ "x": 0.5, "y": 0.7, "align": "center" }
],
"placement": "cycle",
"maxLines": 2,
"lineGap": 0.4
}
每句歌词会按"上→下→上…"依次轮流切换。
4.3 竖排,从右侧起 3 列
{
"writing": "vertical",
"anchors": [{ "x": 0.82, "y": 0.15, "align": "start" }],
"placement": "fixed",
"maxLines": 3,
"lineGap": 0.5
}
竖排文字从上到下书写,列从右向左依次增加。这里用 align: "start" 让文字顶部对齐。
4.4 铺满画面的大字排版并倾斜
{
"writing": "horizontal",
"anchors": [{ "x": 0.5, "y": 0.5, "align": "center" }],
"placement": "fixed",
"scaleMode": "fill",
"baselineRotateDeg": -6
}
scaleMode: "fill" 会把整句歌词放大到铺满画面宽度,因此文字大小会随字符数量变化。
4.5 散布在四角形成错落
{
"writing": "horizontal",
"anchors": [
{ "x": 0.2, "y": 0.25, "align": "start" },
{ "x": 0.8, "y": 0.4, "align": "end" },
{ "x": 0.25, "y": 0.62, "align": "start" },
{ "x": 0.75, "y": 0.8, "align": "end" }
],
"placement": "random",
"scatter": { "offsetRatio": 0.3, "rotateDeg": 12 },
"charScaleRange": [0.85, 1.3]
}
边缘的锚点分别用 align 的 start / end 来配合,避免歌词溢出画面。
4.6 波浪排列并突出一个单词
{
"writing": "horizontal",
"anchors": [{ "x": 0.5, "y": 0.5, "align": "center" }],
"placement": "fixed",
"path": { "kind": "wave", "amplitude": 0.35, "period": 6 },
"focusWord": { "scale": 1.5, "pick": "longest" }
}
5. 供 AI 使用的提示词模板
请先贴上本文档全文,然后继续贴上以下内容。
以下为复制起点
你是 movlyric 的歌词布局设计师。请严格遵循上面贴出的“LayoutSpec 规范文档”,创建一个 LayoutSpec 的 JSON。
输出规则:
- 只输出 JSON(不要写说明、前言或结语;可以用代码围栏包裹 JSON)
- 根节点只能写 writing, anchors, placement, maxLines, lineGap, scaleMode, scatter, baselineRotateDeg, path, charScaleRange, focusWord
- writing, anchors, placement 为必需项,其余只在需要时书写
- **不要写与默认值相同的键**(maxLines:1 / lineGap:0.15 / scaleMode:"fixed")
- writing 为 "horizontal" / "vertical" 之一
- anchors 为 1~8 个,每个元素为 {"x":0..1, "y":0..1, "align":"start"|"center"|"end"}
- x, y 是**相对画面的比例**(不是像素),0.5 为居中
- 想贴靠画面边缘时,将 align 设为 start / end(保持 center 会溢出)
- placement 为 "fixed" / "cycle" / "random"。anchors 只有 1 个时应设为 "fixed"
- scatter 为 {"offsetRatio":0以上, "rotateDeg":0以上}
- path 为 {"kind":"wave"|"arc"|"steps", "amplitude":数值, "period":大于0(可选)}
- charScaleRange 为 [最小值, 最大值] 两个元素
- focusWord 为 {"scale":大于0, "pick":"longest"|"random"}
- **writing 为 "vertical" 时不要写 path / charScaleRange / focusWord**(会被忽略)
- 不能写随时间、音频、随机数变化的值或数学表达式(运动由另一套规范 AnimationSpec 负责)
- 不要写不存在的属性、注释、末尾逗号
想要的歌词布局:
{在此写下你想要的布局}
(仅在想修改已有布局时,请在下方粘贴当前的 JSON。若是新建,请删除这一整节)
当前 JSON:
{当前 JSON}
复制到此为止