{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "video.dsl/v1alpha1",
  "title": "Video DSL v1alpha1",
  "description": "声明式视频描述语言，描述最终视频应该长什么样，而非如何调用每个技能。",
  "type": "object",
  "required": ["version", "meta", "global", "scenes"],
  "properties": {
    "version": {
      "type": "string",
      "const": "v1alpha1"
    },
    "meta": {
      "$ref": "#/definitions/Meta"
    },
    "global": {
      "$ref": "#/definitions/GlobalConfig"
    },
    "assets": {
      "type": "array",
      "items": { "$ref": "#/definitions/AssetRef" },
      "description": "顶层素材声明池，可被 scene 级 assetBindings 引用"
    },
    "scenes": {
      "type": "array",
      "items": { "$ref": "#/definitions/Scene" },
      "minItems": 1,
      "maxItems": 20
    },
    "transitions": {
      "$ref": "#/definitions/TransitionConfig"
    },
    "renderHints": {
      "$ref": "#/definitions/RenderHints"
    },
    "outputs": {
      "$ref": "#/definitions/OutputConfig"
    }
  },
  "definitions": {
    "Meta": {
      "type": "object",
      "required": ["title"],
      "properties": {
        "title": { "type": "string" },
        "topic": { "type": "string" },
        "targetDuration": {
          "type": "number",
          "description": "目标总时长（秒）"
        },
        "language": { "type": "string", "default": "zh-CN" },
        "style": {
          "type": "string",
          "description": "整体风格标签，如 科技感、清新、商务、卡通"
        },
        "audience": { "type": "string" },
        "description": { "type": "string" }
      }
    },
    "GlobalConfig": {
      "type": "object",
      "properties": {
        "aspectRatio": {
          "type": "string",
          "enum": ["16:9", "9:16", "1:1", "4:3", "3:4", "21:9"],
          "default": "16:9"
        },
        "resolution": {
          "type": "string",
          "enum": ["480p", "720p", "1080p", "4k"],
          "default": "1080p"
        },
        "fps": {
          "type": "integer",
          "enum": [24, 25, 30, 60],
          "default": 30
        },
        "subtitle": {
          "type": "object",
          "properties": {
            "enabled": { "type": "boolean", "default": true },
            "style": { "type": "string", "enum": ["bottom", "center", "karaoke"], "default": "bottom" },
            "fontSize": { "type": "integer" },
            "fontFamily": { "type": "string" },
            "color": { "type": "string" }
          }
        },
        "narration": {
          "type": "object",
          "properties": {
            "voiceId": { "type": "string", "description": "Minimax 音色 ID" },
            "voiceName": { "type": "string" },
            "speed": { "type": "number", "default": 1.0 },
            "languageBoost": { "type": "string", "description": "TTS 语种提示（auto / Chinese / English …）。中英混排的旁白不给提示时，英文词容易被按中文音系读出来；留空由服务端取默认值。" }
          }
        },
        "bgm": {
          "type": "object",
          "properties": {
            "enabled": { "type": "boolean", "default": false },
            "url": { "type": "string" },
            "volume": { "type": "number", "default": 0.15, "minimum": 0, "maximum": 1 }
          }
        },
        "font": {
          "type": "object",
          "description": "全局字体选择。省略 = 跟随模板自带的字体搭配。match_template 会把它折进 binding 的 globalOverrides.typography。",
          "properties": {
            "fontId": {
              "type": "string",
              "description": "字体库的不透明 key（font.uniq_id）。**不要在这里写 CSS family 名**：family 名是渲染细节，由 ab-render 调 /font/resolve 解析；写成 family 名一旦拼错就静默退回默认字体，没有任何报错。见 ab-platform/docs/font-selection-design.md §8.1。"
            },
            "fontName": { "type": "string", "description": "展示名，仅供人读与日志，渲染不使用" }
          }
        }
      }
    },
    "AssetRef": {
      "type": "object",
      "required": ["assetId", "type"],
      "properties": {
        "assetId": {
          "type": "string",
          "description": "全局唯一素材 ID，scene 可通过此 ID 引用"
        },
        "type": {
          "type": "string",
          "enum": ["image", "video", "audio", "avatar", "subtitle", "bgm"]
        },
        "source": {
          "type": "string",
          "enum": ["existing", "gen-image", "gen-video", "gen-voice", "gen-digital-human"],
          "description": "素材来源"
        },
        "status": {
          "type": "string",
          "enum": ["missing", "planned", "generating", "generated", "approved", "failed"],
          "default": "planned"
        },
        "url": {
          "type": "string",
          "description": "已生成/已有素材的 URL"
        },
        "localPath": {
          "type": "string",
          "description": "本地缓存路径"
        },
        "payload": {
          "type": "object",
          "description": "素材生成参数，根据 source 不同内容不同",
          "properties": {
            "prompt": { "type": "string" },
            "negativePrompt": {
              "type": "string",
              "description": "负向提示词，描述不希望出现的元素"
            },
            "guidanceScale": {
              "type": "number",
              "description": "引导系数，控制生成图片对 prompt 的遵循程度"
            },
            "model": { "type": "string" },
            "text": { "type": "string" },
            "voiceId": { "type": "string" },
            "avatarId": { "type": ["string", "integer"] },
            "duration": { "type": "number" },
            "ratio": { "type": "string" },
            "resolution": { "type": "string" },
            "style": { "type": "string" }
          },
          "additionalProperties": true
        },
        "metadata": {
          "type": "object",
          "description": "生成后的元数据",
          "properties": {
            "duration": { "type": "number" },
            "width": { "type": "integer" },
            "height": { "type": "integer" },
            "fileSize": { "type": "integer" },
            "mimeType": { "type": "string" }
          },
          "additionalProperties": true
        }
      }
    },
    "Scene": {
      "type": "object",
      "required": ["id", "purpose"],
      "properties": {
        "id": { "type": "string" },
        "purpose": {
          "type": "string",
          "enum": ["opening", "intro", "point", "example", "explanation", "transition", "highlight", "cta", "ending"],
          "description": "场景在叙事中的角色"
        },
        "duration": {
          "type": "number",
          "description": "该场景时长（秒），可省略由模板决定"
        },
        "layout": {
          "type": "string",
          "enum": ["full-visual", "split-left-right", "split-top-bottom", "picture-in-picture", "text-overlay", "avatar-with-bg", "kenburns"],
          "default": "full-visual"
        },
        "visuals": {
          "type": "object",
          "properties": {
            "background": {
              "type": "object",
              "properties": {
                "assetRef": { "type": "string", "description": "引用 assets 池中的 assetId" },
                "color": { "type": "string" },
                "gradient": { "type": "string" }
              }
            },
            "foreground": {
              "type": "object",
              "properties": {
                "assetRef": { "type": "string" },
                "position": { "type": "string", "enum": ["center", "left", "right", "top", "bottom"] },
                "scale": { "type": "number", "default": 1.0 }
              }
            },
            "avatar": {
              "type": "object",
              "properties": {
                "assetRef": { "type": "string" },
                "position": { "type": "string", "enum": ["center", "left", "right", "bottom-left", "bottom-right"] },
                "scale": { "type": "number", "default": 1.0 }
              }
            }
          }
        },
        "audio": {
          "type": "object",
          "properties": {
            "narration": {
              "type": "object",
              "description": "场景旁白。两种写法：(A) 传统：提供 text；(B) 多项卡片场景推荐：提供 intro/items/outro，每个 item 对应一张卡片，编译期会按 \\n 切行送 TTS 并自动生成 highlightMap，避免高亮与音频错位。",
              "properties": {
                "text": { "type": "string", "description": "该场景的完整旁白文案（传统写法）" },
                "intro": { "type": "string", "description": "可选：开场铺垫句（此期间无卡片高亮）" },
                "items": {
                  "type": "array",
                  "items": { "type": "string" },
                  "description": "每行一个卡片的叙述句。长度必须等于 templateData 里对应数组（concepts/pillars/eras/items）的长度"
                },
                "outro": { "type": "string", "description": "可选：收尾句（此期间无卡片高亮）" },
                "assetRef": { "type": "string", "description": "旁白音频 assetId" },
                "languageBoost": { "type": "string", "description": "TTS 语种提示（auto / Chinese / English …）。中英混排的旁白不给提示时，英文词容易被按中文音系读出来；覆盖 global.narration 的同名字段；留空则跟随全局/服务端默认。" }
              }
            },
            "bgm": {
              "type": "object",
              "properties": {
                "assetRef": { "type": "string" },
                "volume": { "type": "number" }
              }
            },
            "soundEffect": {
              "type": "object",
              "properties": {
                "assetRef": { "type": "string" },
                "trigger": { "type": "string", "enum": ["scene-start", "scene-end", "midpoint"] }
              }
            }
          }
        },
        "textLayers": {
          "type": "array",
          "items": {
            "type": "object",
            "required": ["role", "content"],
            "properties": {
              "role": {
                "type": "string",
                "enum": ["headline", "subheadline", "caption", "badge", "callout"],
                "description": "文本图层的语义角色：headline=画面主标题（大字），subheadline=画面副标题/项目名/标语（小字，与 headline 配对），caption=注释/角标，badge=徽标，callout=指示/标注。注意 subtitle（CC 字幕，逐句出字）由 global.subtitle 与 render-plan.subtitleSegments 单独承载，不在 textLayers.role 这里。"
              },
              "content": { "type": "string" },
              "position": { "type": "string" },
              "animation": { "type": "string", "enum": ["fade-in", "slide-up", "typewriter", "none"], "default": "fade-in" }
            }
          }
        },
        "animationHints": {
          "type": "object",
          "properties": {
            "entrance": { "type": "string", "enum": ["fade", "slide-left", "slide-right", "slide-up", "zoom-in", "none"], "default": "fade" },
            "exit": { "type": "string", "enum": ["fade", "slide-left", "slide-right", "slide-down", "zoom-out", "none"], "default": "fade" },
            "motion": { "type": "string", "enum": ["static", "kenburns-in", "kenburns-out", "pan-left", "pan-right", "float"], "default": "static" }
          }
        },
        "assetBindings": {
          "type": "array",
          "items": { "type": "string" },
          "description": "该场景引用的 assetId 列表"
        },
        "templateData": {
          "type": "object",
          "additionalProperties": true,
          "description": "模板专属数据，结构由所绑定模板的 slotMapping 定义。如 knowledge-slides 的 slides 等"
        }
      }
    },
    "TransitionConfig": {
      "type": "object",
      "properties": {
        "default": {
          "type": "string",
          "enum": ["cut", "fade", "dissolve", "slide-left", "slide-right", "wipe", "zoom", "flip", "flip-corner"],
          "default": "fade"
        },
        "duration": {
          "type": "number",
          "default": 0.5,
          "description": "转场时长（秒）"
        },
        "overrides": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "from": { "type": "string" },
              "to": { "type": "string" },
              "type": { "type": "string" },
              "duration": { "type": "number" }
            }
          }
        }
      }
    },
    "RenderHints": {
      "type": "object",
      "properties": {
        "templatePreference": {
          "type": "array",
          "items": { "type": "string" },
          "description": "偏好的模板 ID 列表"
        },
        "brandColors": {
          "type": "array",
          "items": { "type": "string" },
          "description": "品牌色 HEX 值"
        },
        "pace": {
          "type": "string",
          "enum": ["slow", "normal", "fast"],
          "default": "normal"
        },
        "shotDensity": {
          "type": "string",
          "enum": ["sparse", "normal", "dense"],
          "default": "normal"
        }
      }
    },
    "OutputConfig": {
      "type": "object",
      "properties": {
        "remotion": {
          "type": "object",
          "properties": {
            "enabled": { "type": "boolean", "default": true },
            "codec": { "type": "string", "enum": ["h264", "h265", "vp8", "vp9"], "default": "h264" },
            "crf": { "type": "integer", "default": 18 }
          }
        },
        "jianyingDraft": {
          "type": "object",
          "description": "剪映草稿导出（预留）",
          "properties": {
            "enabled": { "type": "boolean", "default": false }
          }
        },
        "cloudEditingProject": {
          "type": "object",
          "description": "云剪辑工程导出（预留）",
          "properties": {
            "enabled": { "type": "boolean", "default": false }
          }
        }
      }
    }
  }
}
