GraphicSpec 规范文档 — 自定义"背景特效"
本文档译自日语原版。日语版为正式版本,如有出入以日语版为准。
本文档是 movlyric 背景特效(在歌词背后绘制图形、线条)定义“GraphicSpec”的完整规范。 在应用的“样式编辑器 →“背景”标签 → 背景特效 →“自定义”→ 用 AI 生成…”中使用(让歌词文字本身运动的“文字动作”是另一套体系, 其规范请见 ANIMATION_SPEC(文字动作))。 本文档的目标是:只读过此文档的 AI(或人类)也能写出可以直接粘贴到应用中并被接受的 JSON。 文档末尾附有可交给 AI 使用的提示词模板。将本文档整体作为提示词的一部分贴入同样可以正常使用。
1. 概述
背景特效是在歌词背后运动的动态图形(歌词本身的动作由另一套规范 AnimationSpec 处理)。
GraphicSpec 以"排列 N 个相同形状的图形并使其运动"的形式书写。图形共有圆形、矩形、线条、多边形四种。
每个图形的位置、大小、颜色、不透明度,可以用两种写法来决定。
- 定型合成(
基准值 + 随机数 + 正弦波 + 漂移 + 音频)— 写法简短 - 数学表达式 — 可以像
0.5 + sin(t * 2 + i) * 0.2这样自由计算,也能写条件分支,以及引用前一个图形位置的链式排布
数学表达式并不是 JavaScript。不能写赋值、循环、函数定义,只能是一个表达式返回一个数值(与电子表格公式的思路相同)。可使用的名称仅限 §2.6 列出的范围。
2. JSON 格式完整规范
2.1 根节点:GraphicSpec
{ "layers": [ <Layer>, ... ] }
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
layers |
Layer[] | 必需 | 1~4 个。先写的图层在最里侧,后写的画在更靠前的位置 |
根节点下能写的键只有这一个。
2.2 Layer
| 字段 | 类型 | 必需 | 取值范围 | 说明 |
|---|---|---|---|---|
shape |
字符串 | 必需 | "circle" / "rect" / "line" / "polygon" |
图形种类 |
count |
整数 | 必需 | 1~200 | 图形数量 |
sides |
整数 | 可选 | 3~24 | polygon 的顶点数(省略时为 5)。其他 shape 会忽略此项 |
star |
数值 | 可选 | 0~1 | polygon 的星形程度。0=正多边形,0.5 为标准星形。其他 shape 会忽略此项 |
when |
字符串 | 可选 | 数学表达式 | 绘制条件。求值为 0 的实例不会被绘制(§2.6) |
spread |
字符串 | 可选 | §2.4 | 各图形的初始排布方式。省略时全部重叠在同一位置 |
x |
Value | 必需 | — | 横向位置。相对画面宽度的比例(0=左端,0.5=居中,1=右端) |
y |
Value | 必需 | — | 纵向位置。相对画面高度的比例(0=上端,1=下端) |
size |
Value | 必需 | — | 大小。相对画面高度的比例。circle=半径 / rect=高度 / line=长度 |
aspect |
数值 | 可选 | 0.01~100 | rect 的宽度 = size × aspect。对 line 影响的是粗细。circle 会忽略此项 |
rotation |
Value | 可选 | — | 旋转(度)。circle 会忽略此项 |
color |
字符串或整数 | 必需 | §2.5 | 颜色 |
alpha |
Value | 必需 | — | 不透明度,会被截断到 0~1 |
wrap |
布尔值 | 可选 | — | 为 true 时,移出画面的图形会从对侧重新出现(用于持续流动的效果) |
2.3 Value(值的写法)
有三种写法。
| 写法 | 示例 | 用途 |
|---|---|---|
| 数值 | "x": 0.5 |
常量 |
| 数学表达式(字符串) | "x": "0.5 + sin(t) * 0.2" |
自由计算、条件分支、依赖前一个图形(§2.6) |
| 对象 | 见下方 | "基准值+随机数+波动+漂移+音频"的定型合成 |
拿不定主意时,用数学表达式更容易写。 对象形式是为了把常见组合写得更简短。
直接写数值即为常量("x": 0.5)。对象形式如下。
{
"base": 0.5,
"random": [-0.2, 0.2],
"wave": { "amplitude": 0.05, "periodMs": 3000, "phaseByIndex": 0.7 },
"drift": -0.1,
"audio": { "band": 2, "scale": 0.3 }
}
| 字段 | 类型 | 必需 | 取值范围 | 说明 |
|---|---|---|---|---|
base |
数值 | 必需 | — | 基准值 |
random |
[数值, 数值] | 可选 | — | 在此范围内取随机数加到 base 上。每个图形取值都不同(每次都生成相同画面的确定性随机数) |
wave |
对象 | 可选 | — | 用正弦波使其摆动(见下) |
drift |
数值 | 可选 | — | 随时间线性变化的量(每秒)。负值表示反方向 |
audio |
对象 | 可选 | — | 使其对音频作出反应(见下) |
wave
| 字段 | 类型 | 必需 | 取值范围 | 说明 |
|---|---|---|---|---|
amplitude |
数值 | 必需 | — | 摆动幅度 |
periodMs |
整数 | 必需 | 50~60000 | 一次往返所需时间(毫秒)。不可为小数 |
phaseByIndex |
数值 | 可选 | — | 按图形错开相位的量。省略时所有图形会一齐做相同运动,想让它们错落有致时可填入 0.3~1.0 左右的值 |
audio
| 字段 | 类型 | 必需 | 取值范围 | 说明 |
|---|---|---|---|---|
band |
整数 | 必需 | 0~63 | 频段。0 为最低音(底鼓),数字越大音调越高 |
scale |
数值 | 必需 | — | 乘以频段电平(0~1)后加到 base 上的量 |
若想对低音作出反应,band 建议取 0~3;中音约 8~16;高音约 24 以上。
2.4 spread(初始排布)
会叠加到 x/y 的值上。
| 值 | 排布方式 |
|---|---|
"none"(省略时) |
全部位于同一位置。用于打算配合 random 打散的场景 |
"random" |
在整个画面内随机散布(每次都生成相同排布的确定性随机数) |
"row" |
横向一列等间距排列 |
"column" |
纵向一列等间距排列 |
"ring" |
沿圆周等间距排列 |
"spiral" |
从中心向外画出螺旋(按黄金角分布,不易重叠) |
"grid" |
接近正方形的网格 |
2.5 color(颜色)
推荐引用调色板。 这样用户更改配色时,特效也会随之联动变化。
| 值 | 含义 |
|---|---|
"text" |
文字颜色 |
"accent" |
强调色(副歌颜色) |
"stroke" |
描边颜色 |
| 整数 | 0xRRGGBB 的直接数值(例如:红色 = 16711680)。不可使用字符串 "#ff0000" |
2.6 数学表达式
在值的位置写字符串即视为数学表达式。最多 200 个字符。
{ "x": "0.5 + sin(t * 2 + i * 0.5) * 0.2" }
可用变量
| 名称 | 含义 |
|---|---|
t |
经过的秒数 |
at |
音频的经过秒数(想让效果对音频响应时使用这个) |
i |
当前图形的编号(从 0 开始) |
n |
图形总数 |
p |
i/(n-1)(归一化到 0~1 的位置;n=1 时为 0) |
beat |
节拍进度 0~1(0 为拍点起始) |
energy |
该段落的能量值 0~1 |
chorus |
处于副歌时为 1,否则为 0 |
aspect |
画面的宽高比(宽/高) |
px py psize prot |
前一个图形的位置、大小、旋转(§2.7) |
PI TAU |
圆周率及其 2 倍 |
可用函数
sin cos tan asin acos atan atan2 abs sqrt exp log sign floor ceil round min max pow hypot mod clamp lerp step smoothstep rand band
mod(a, b)— 结果恒为正的取模(mod(-1, 3)= 2)clamp(v, min, max)/lerp(a, b, t)/step(edge, v)/smoothstep(e0, e1, v)rand(k)— 该图形专属的随机数 0~1(改变k会得到不同的数列;每次都生成相同值的确定性随机数)band(k)— 频段k的电平 0~1(0 为最低音)
运算符
+ - * / % ^(乘方),比较运算符 < <= > >= == !=,逻辑运算符 && || !,以及三元运算符 条件 ? A : B。
条件分支用三元运算符书写。
{ "size": "chorus ? 0.15 : 0.05" }
不能写的内容
不能写变量赋值、循环、函数定义、字符串。只能用一个表达式得出一个数值。写上表之外的名称(如 Math、Date、random 等)会报错。
2.7 依赖前一个图形的计算
px / py / psize / prot 是前一个图形(i-1)的确定值,借此可以写出链式、堆叠的排布。这些值会保持画面比例原样传入。
{ "x": "px + 0.15", "y": "py + sin(i) * 0.05" }
在开头(i = 0)时从 0 开始。想让"第一个特殊处理"时,请用 i 做分支。
{ "size": "i == 0 ? 0.1 : psize * 0.8" }
3. 常见错误(禁止事项)
- 超出取值范围:
count: 0、300,periodMs: 10或100000,band: 64,layers达 5 个以上,均不允许 - 不存在的属性:Layer 中只能写 §2.2 列出的项目,Value 的对象形式只能写 §2.3 的这 5 个。不存在
speed、opacity、radius、points等属性 - 在表达式中写不存在的名称:
Math.sin(t)不可用(应写作sin(t))。Date、random、window等均不可用 - 在表达式中写循环或赋值:不能写
for、=、let。一个表达式只能得出一个数值 - 用字符串写颜色:
"#ff0066"、"red"均不可,只能用调色板名称或整数 - 禁止使用小数的位置:
count/periodMs/band只能是整数 - 单位搞混:x/y/size 是相对画面的比例,而不是像素。
"size": 40会变成"画面高度的 40 倍",从而铺满整个画面。大小通常在 0.01~0.2 左右 - 忘记设置
phaseByIndex:不设置的话所有图形会一齐做相同运动,显得机械、不自然 - 混入非 JSON 内容:不可写注释、末尾逗号(数学表达式可以作为字符串书写 — §2.6)
4. 示例
以下均为可以直接粘贴到应用中并通过校验的完整 JSON。
4.1 飘浮的光粒
随机散布的圆形缓缓向上漂移,同时左右摆动并明灭。移出画面上端后会从下方重新出现。
{
"layers": [
{
"shape": "circle",
"count": 24,
"spread": "random",
"x": { "base": 0, "wave": { "amplitude": 0.02, "periodMs": 7000, "phaseByIndex": 0.9 } },
"y": { "base": 0, "drift": -0.05 },
"size": { "base": 0.03, "random": [0, 0.03] },
"color": "accent",
"alpha": { "base": 0.18, "wave": { "amplitude": 0.1, "periodMs": 4000, "phaseByIndex": 0.6 } },
"wrap": true
}
]
}
4.2 音频响应的均衡器
排列在画面下部的竖条,会随着从低音到高音各频段的电平伸缩。
{
"layers": [
{
"shape": "rect",
"count": 32,
"spread": "row",
"x": 0.5,
"y": 0.95,
"size": { "base": 0.02, "audio": { "band": 4, "scale": 0.5 } },
"aspect": 0.4,
"color": "accent",
"alpha": 0.75
}
]
}
4.3 斜向流动的线条
斜向的线条在背景中缓缓持续横穿。通过叠加一层较淡的远景和一层较浓的近景来营造纵深感。
{
"layers": [
{
"shape": "line",
"count": 14,
"spread": "random",
"x": { "base": 0, "drift": 0.06 },
"y": 0,
"size": { "base": 0.5, "random": [0, 0.4] },
"aspect": 0.03,
"rotation": -24,
"color": "text",
"alpha": 0.06,
"wrap": true
},
{
"shape": "line",
"count": 5,
"spread": "random",
"x": { "base": 0, "drift": 0.11 },
"y": 0,
"size": { "base": 0.7, "random": [0, 0.3] },
"aspect": 0.05,
"rotation": -24,
"color": "accent",
"alpha": 0.14,
"wrap": true
}
]
}
4.4 随底鼓脉动的圆环
排列在圆周上的点,会随低音(底鼓)向外扩张。
{
"layers": [
{
"shape": "circle",
"count": 24,
"spread": "ring",
"x": { "base": 0.5, "audio": { "band": 0, "scale": 0.06 } },
"y": { "base": 0.5, "audio": { "band": 0, "scale": 0.06 } },
"size": { "base": 0.012, "audio": { "band": 0, "scale": 0.02 } },
"color": "accent",
"alpha": 0.5
}
]
}
4.5 仅副歌时飞舞的星星(条件分支 + 多边形)
只有在副歌期间星形才会出现并旋转。用 when 按图层控制出现/消失,大小随节拍脉动。
{
"layers": [
{
"shape": "polygon",
"sides": 5,
"star": 0.55,
"count": 18,
"spread": "random",
"when": "chorus",
"x": 0,
"y": { "base": 0, "drift": -0.03 },
"size": "0.02 + (1 - beat) * 0.015 + rand(0) * 0.02",
"rotation": "t * 40 + i * 20",
"color": "accent",
"alpha": 0.5,
"wrap": true
}
]
}
4.6 连绵延伸的线条(依赖前一个图形)
从第一条线开始,依次把下一条线放在前一条线终点附近,形成链式排布。这是使用 px / py 的示例。
{
"layers": [
{
"shape": "line",
"count": 40,
"x": "i == 0 ? 0.05 : px + 0.022",
"y": "i == 0 ? 0.5 : py + sin(t + i * 0.4) * 0.012",
"size": 0.04,
"aspect": 0.06,
"rotation": "sin(t + i * 0.4) * 40",
"color": "accent",
"alpha": "0.15 + p * 0.5"
}
]
}
5. 供 AI 使用的提示词模板
请复制以下框内内容交给 AI。推荐的用法是:先贴上本规范文档全文,紧接着再贴这份模板(如果不附带规范文档、只把模板单独交给 AI,AI 容易在取值范围或单位上出错)。
以下为复制起点
你是 movlyric 的背景特效设计师。请严格遵循上面贴出的“GraphicSpec 规范文档”,创建一个 GraphicSpec 的 JSON。
输出规则:
- 只输出 JSON(不要写说明、前言或结语;可以用代码围栏包裹 JSON)
- 根节点为 {"layers": [...]},layers 为 1~4 个
- Layer 中只能写 shape, count, sides, star, when, spread, x, y, size, aspect, rotation, color, alpha, wrap
- shape 为 "circle" / "rect" / "line" / "polygon" 之一。polygon 可以带 sides(3..24) 和 star(0..1)
- count 为 1~200 的整数
- x, y, size, alpha 为必需项,可用以下三种方式书写:
(a) 直接写数值(常量)
(b) **数学表达式字符串**(最多 200 字符)
(c) {"base":..., "random":[min,max], "wave":{"amplitude":...,"periodMs":整数50..60000,"phaseByIndex":...}, "drift":..., "audio":{"band":整数0..63,"scale":...}}
- 数学表达式中只能使用变量 t, at, i, n, p, beat, energy, chorus, aspect, px, py, psize, prot, PI, TAU
- 数学表达式中只能使用函数 sin cos tan asin acos atan atan2 abs sqrt exp log sign floor ceil round min max pow hypot mod clamp lerp step smoothstep rand(k) band(k)
- 数学表达式中不能写赋值、循环、函数定义、字符串。条件分支请用三元运算符 `条件 ? A : B` 书写
- **不可写成 Math.sin(t) 这样的形式**(应写作 sin(t))。不能使用 Date / random / window 等名称
- 想依赖前一个图形时,使用 px / py / psize / prot(以画面比例原样传入;i=0 时为 0)
- 想按图层控制出现/消失时,在 when 中写数学表达式(求值为 0 则不绘制)
- **x/y/size 是相对画面的比例**(不是像素)。size 通常在 0.01~0.2 左右;x/y 在 0~1 范围内表示画面内部
- color 为 "text" / "accent" / "stroke" 之一,或 0xRRGGBB 形式的整数。不可使用字符串形式的颜色代码
- 想让多个图形错开运动时,在 wave 中加入 phaseByIndex 来错开相位(不设置的话全部会一齐运动,显得不自然)
- 想让效果对音频响应时使用 audio。band 为 0 表示最低音(底鼓),数字越大音调越高
- 想让图形持续流出画面外时,将 drift 与 wrap:true 组合使用
- 不要写不存在的属性、注释、末尾逗号、表达式
想要的特效:
{在此写下你想要的效果}
(仅在想修改已有特效时,请在下方粘贴当前的 JSON。若是新建,请删除这一整节)
当前 JSON:
{当前 JSON}
复制到此为止