LayoutSpec 规范文档 — 自定义"歌词布局"

本文档译自日语原版。日语版为正式版本,如有出入以日语版为准。

本文档是 movlyric 歌词布局定义“LayoutSpec”的完整规范。 在应用的“样式编辑器 →“布局”标签 → 布局预设 →“自定义”→ 用 AI 生成…”中使用。

有两个名称相近但完全不同的东西,请不要混淆。

决定的内容 规范文档
歌词放在画面的什么位置(本文档) LAYOUT_SPEC(歌词布局)
歌词文字如何运动(登场、退场、明灭) ANIMATION_SPEC(文字动作)
在歌词背后绘制的图形、线条 GRAPHIC_SPEC(背景特效)

本文档的目标是:只读过此文档的 AI(或人类)也能写出可以直接粘贴到应用中并被接受的 JSON。 文档末尾附有可交给 AI 使用的提示词模板。将本文档整体作为提示词的一部分贴入同样可以正常使用。


1. 概述

LayoutSpec 只决定"一句歌词放在画面何处、如何排列"这一件事。 其中不含任何随时间变化的要素(运动由 AnimationSpec 负责)。

由以下三项决定:

  1. 位置 — 以画面上的哪个点为基准来放置(anchors / placement)
  2. 排版方式 — 横排还是竖排、最多折成几行(writing / maxLines / lineGap / scaleMode)
  3. 错落 — 是否不排成直线而做出错落感(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}

复制到此为止