JSON 结构与字段规范
1. 顶层结构
完整 JSON 顶层:
{
"meta": {},
"assets": {},
"tracks": []
}说明:
meta必填tracks必填,且至少包含 1 个 trackassets可选
2. meta
interface Meta {
version: string;
title?: string;
description?: string;
author?: string;
createdAt?: string;
tags?: string[];
width: number;
height: number;
fps: number;
background?: string | "transparent" | Gradient;
}字段说明:
version
- 类型:
string - 必填:是
- 用途:标识 schema 版本
- 建议值:
"2.0.0"
title
- 类型:
string - 必填:否
- 用途:视频标题元数据
description
- 类型:
string - 必填:否
- 用途:视频描述元数据
author
- 类型:
string - 必填:否
- 用途:作者元数据
createdAt
- 类型:
string - 必填:否
- 用途:创建时间元数据
tags
- 类型:
string[] - 必填:否
- 用途:标签元数据
width
- 类型:
number - 必填:是
- 限制:必须是正整数
- 用途:画布宽度
height
- 类型:
number - 必填:是
- 限制:必须是正整数
- 用途:画布高度
fps
- 类型:
number - 必填:是
- 限制:必须是正整数
- 用途:播放帧率
background
- 类型:
string | "transparent" | Gradient - 必填:否
- 默认值:
"#000000" - 用途:全局背景
渐变对象:
interface Gradient {
type: "linear" | "radial" | "conic";
angle?: number;
stops: Array<{
offset: number;
color: string;
}>;
}3. assets
interface Assets {
fonts?: FontAsset[];
images?: ImageAsset[];
videos?: VideoAsset[];
audios?: AudioAsset[];
subtitles?: SubtitleAsset[];
}fonts
interface FontAsset {
id: string;
src: string;
family: string;
}当前状态:
- 可以出现在 JSON 里
- 当前运行时不会自动下载或注册字体
- 不要把它当成完整字体加载系统
images
interface ImageAsset {
id: string;
src: string;
}videos
interface VideoAsset {
id: string;
src: string;
}audios
interface AudioAsset {
id: string;
src: string;
}subtitles
interface SubtitleAsset {
id: string;
words: SubtitleWord[];
}$ref 用法
支持 $ref 的资源池:
imagesvideosaudiossubtitles
格式:
{
"src": { "$ref": "video-hero" }
}或:
{
"words": { "$ref": "subtitle-main" }
}4. tracks
interface Track {
id?: string;
clips: Clip[];
}字段说明:
id
- 类型:
string - 必填:否
- 用途:track 标识
clips
- 类型:
Clip[] - 必填:是
- 限制:至少 1 个
5. Clip 总体结构
interface BaseClip {
id?: string;
type: ClipType;
start: number;
duration: number;
transform?: Transform;
zIndex?: number;
opacity?: number;
style?: Style;
animations?: Animation[];
keyframes?: Keyframe[];
transition?: Transition;
}所有 clip 共有的核心字段:
id
- 类型:
string - 必填:否
- 用途:标识 clip
type
- 类型:
ClipType - 必填:是
当前支持:
videoimagetextrectcirclepolygonaudiosubtitlelayouttemplate
start
- 类型:
number - 必填:是
- 单位:秒
- 用途:开始时间
duration
- 类型:
number - 必填:是
- 单位:秒
- 用途:持续时间
transform
- 类型:
Transform - 必填:否
zIndex
- 类型:
number - 必填:否
- 默认值:
0
opacity
- 类型:
number - 必填:否
- 默认值:
1 - 用途:所有可见元素的透明度快捷字段
- 兼容规则:
style.opacity优先级高于opacity
style
- 类型:
Style - 必填:否
animations
- 类型:
Animation[] - 必填:否
keyframes
- 类型:
Keyframe[] - 必填:否
transition
- 类型:
Transition - 必填:否
6. 坐标与百分比规则
百分比并不是 DOM 那种左上角原点,而是基于 Revideo 中心坐标系。
换算规则:
x: "50%"表示水平居中y: "50%"表示垂直居中x: "0%"表示最左侧x: "100%"表示最右侧y: "0%"表示最上侧y: "100%"表示最下侧
7. 顶层最小可用 JSON
{
"meta": {
"version": "2.0.0",
"width": 1920,
"height": 1080,
"fps": 30,
"background": "#000000"
},
"tracks": [
{
"clips": [
{
"type": "text",
"start": 0,
"duration": 3,
"text": "Hello, world",
"transform": {
"x": "50%",
"y": "50%"
},
"style": {
"fontSize": 72,
"fill": "#ffffff",
"textAlign": "center"
}
}
]
}
]
}8. 已知验证边界
POST /api/json 对顶层结构的校验是严格的,但对每个 clip 的字段不是深度 zod 校验。
这意味着:
- 顶层缺
meta或tracks会报错 - 但 clip 内部写错字段名,不一定会在 API 校验阶段报错
- 某些错误会在播放或渲染阶段才体现出来
所以写 JSON 时仍然应该以本文档和运行时实现为准。