{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://tunx.ai/guides/video-prompt-engineering/shotspec.schema.json",
  "title": "Tunx Video ShotSpec",
  "description": "面向多模型视频生产的供应商中立镜头规范。org_id 为组织级数据的强制隔离键。",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "schema_version",
    "org_id",
    "project_id",
    "shot_id",
    "mode",
    "intent",
    "visual",
    "motion",
    "camera",
    "timeline",
    "audio",
    "model",
    "references",
    "constraints",
    "provenance"
  ],
  "properties": {
    "schema_version": {
      "const": "1.0.0"
    },
    "org_id": {
      "type": "string",
      "minLength": 1,
      "description": "强制组织隔离键；查询、导出、评测与资产关联均不得跨 org_id。"
    },
    "project_id": {
      "type": "string",
      "minLength": 1
    },
    "sequence_id": {
      "type": "string"
    },
    "shot_id": {
      "type": "string",
      "minLength": 1
    },
    "prompt_version": {
      "type": "integer",
      "minimum": 1,
      "default": 1
    },
    "mode": {
      "type": "string",
      "enum": [
        "text_to_video",
        "image_to_video",
        "first_last_frame",
        "reference_to_video",
        "video_to_video",
        "edit_video",
        "extend_video",
        "performance_transfer",
        "avatar_presenter",
        "interactive_avatar"
      ]
    },
    "intent": {
      "type": "object",
      "additionalProperties": false,
      "required": ["objective", "audience", "channel", "duration_seconds", "aspect_ratio"],
      "properties": {
        "objective": {"type": "string", "minLength": 1},
        "audience": {"type": "string", "minLength": 1},
        "channel": {
          "type": "string",
          "examples": ["TikTok", "Reels", "YouTube", "TV", "landing_page", "internal_training"]
        },
        "message": {"type": "string"},
        "call_to_action": {"type": "string"},
        "duration_seconds": {"type": "number", "exclusiveMinimum": 0},
        "aspect_ratio": {
          "type": "string",
          "pattern": "^[0-9]+:[0-9]+$",
          "examples": ["16:9", "9:16", "1:1"]
        },
        "delivery_resolution": {"type": "string", "examples": ["1080p", "4K"]},
        "single_take": {"type": "boolean", "default": true}
      }
    },
    "continuity": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "character_bible": {"type": "string"},
        "wardrobe_bible": {"type": "string"},
        "product_bible": {"type": "string"},
        "scene_geography": {"type": "string"},
        "palette_bible": {"type": "string"},
        "voice_bible": {"type": "string"},
        "must_not_drift": {"type": "array", "items": {"type": "string"}, "uniqueItems": true}
      }
    },
    "visual": {
      "type": "object",
      "additionalProperties": false,
      "required": ["subject", "scene"],
      "properties": {
        "subject": {"type": "string", "minLength": 1},
        "attributes": {"type": "string"},
        "wardrobe_materials": {"type": "string"},
        "props": {"type": "string"},
        "scene": {"type": "string", "minLength": 1},
        "time_weather": {"type": "string"},
        "lighting": {"type": "string"},
        "palette": {"type": "string"},
        "style_medium": {"type": "string"},
        "texture_finish": {"type": "string"}
      }
    },
    "motion": {
      "type": "object",
      "additionalProperties": false,
      "required": ["subject_action"],
      "properties": {
        "subject_action": {"type": "string", "minLength": 1},
        "object_action": {"type": "string"},
        "environment_action": {"type": "string"},
        "direction": {"type": "string"},
        "speed_rhythm": {"type": "string"},
        "trajectory_amplitude": {"type": "string"},
        "physics": {"type": "string", "description": "质量、惯性、摩擦、碰撞、反弹、布料与流体等。"},
        "causality": {"type": "string"},
        "spatial_binding": {"type": "string", "description": "明确谁在何处对什么做什么，避免动作串角色。"}
      }
    },
    "camera": {
      "type": "object",
      "additionalProperties": false,
      "required": ["shot_size", "movement"],
      "properties": {
        "shot_size": {"type": "string"},
        "angle": {"type": "string"},
        "point_of_view": {"type": "string"},
        "height_distance": {"type": "string"},
        "lens_focal_length": {"type": "string"},
        "aperture_depth_of_field": {"type": "string"},
        "focus_behavior": {"type": "string"},
        "composition": {"type": "string"},
        "movement": {"type": "string", "minLength": 1},
        "stabilization": {"type": "string"}
      }
    },
    "timeline": {
      "type": "object",
      "additionalProperties": false,
      "required": ["beats"],
      "properties": {
        "beats": {
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": ["start_seconds", "end_seconds", "action"],
            "properties": {
              "start_seconds": {"type": "number", "minimum": 0},
              "end_seconds": {"type": "number", "exclusiveMinimum": 0},
              "action": {"type": "string", "minLength": 1},
              "camera": {"type": "string"},
              "audio_cue": {"type": "string"},
              "transition": {"type": "string"}
            }
          }
        },
        "pacing": {"type": "string"},
        "hold_last_frame_seconds": {"type": "number", "minimum": 0},
        "loop_seam": {"type": "boolean", "default": false}
      }
    },
    "audio": {
      "type": "object",
      "additionalProperties": false,
      "required": ["enabled"],
      "properties": {
        "enabled": {"type": "boolean"},
        "dialogue": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": ["speaker", "line"],
            "properties": {
              "speaker": {"type": "string"},
              "line": {"type": "string"},
              "language": {"type": "string"},
              "accent": {"type": "string"},
              "delivery": {"type": "string"},
              "timecode": {"type": "string"}
            }
          }
        },
        "narration": {"type": "string"},
        "voice": {"type": "string"},
        "sound_effects": {"type": "array", "items": {"type": "string"}},
        "ambience": {"type": "string"},
        "music": {"type": "string"},
        "silence_cues": {"type": "string"},
        "sync_cues": {"type": "string"}
      }
    },
    "references": {
      "type": "array",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": ["asset_id", "role", "rights_status"],
        "properties": {
          "asset_id": {"type": "string", "minLength": 1},
          "sha256": {"type": "string", "pattern": "^[a-fA-F0-9]{64}$"},
          "kind": {"type": "string", "enum": ["image", "video", "audio", "document", "url"]},
          "role": {
            "type": "string",
            "enum": ["identity", "wardrobe", "product", "prop", "scene", "composition", "style", "motion", "pose", "first_frame", "last_frame", "voice", "music", "dialogue", "background"]
          },
          "use_only": {"type": "string", "description": "只借用什么。"},
          "preserve": {"type": "string", "description": "必须保持什么。"},
          "rights_status": {"type": "string", "enum": ["owned", "licensed", "consented", "public_domain", "pending_review"]},
          "consent_record_id": {"type": "string"},
          "source_url": {"type": "string", "format": "uri"}
        }
      }
    },
    "constraints": {
      "type": "object",
      "additionalProperties": false,
      "required": ["must_keep", "must_avoid"],
      "properties": {
        "must_keep": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
        "must_avoid": {"type": "array", "items": {"type": "string"}, "uniqueItems": true},
        "negative_prompt": {"type": "string", "description": "仅当目标模型明确支持独立负向字段时使用。"},
        "safety": {"type": "array", "items": {"type": "string"}},
        "legal_text_in_post": {"type": "boolean", "default": true}
      }
    },
    "model": {
      "type": "object",
      "additionalProperties": false,
      "required": ["provider", "model_id", "model_version", "settings"],
      "properties": {
        "provider": {"type": "string", "minLength": 1},
        "platform": {"type": "string"},
        "model_id": {"type": "string", "minLength": 1},
        "model_version": {"type": "string", "minLength": 1},
        "endpoint_or_ui": {"type": "string"},
        "settings": {
          "type": "object",
          "additionalProperties": true,
          "properties": {
            "duration_seconds": {"type": "number", "exclusiveMinimum": 0},
            "aspect_ratio": {"type": "string"},
            "resolution": {"type": "string"},
            "fps": {"type": "number", "exclusiveMinimum": 0},
            "seed": {"type": ["integer", "string", "null"]},
            "motion_strength": {"type": ["number", "string", "null"]},
            "reference_strength": {"type": ["number", "string", "null"]},
            "native_audio": {"type": "boolean"},
            "prompt_enhancer": {"type": "boolean"}
          }
        }
      }
    },
    "prompts": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "raw_prompt": {"type": "string"},
        "effective_prompt": {"type": "string", "description": "经平台增强器或适配器改写后实际送入模型的提示词。"},
        "adapter_id": {"type": "string"},
        "adapter_version": {"type": "string"}
      }
    },
    "provenance": {
      "type": "object",
      "additionalProperties": false,
      "required": ["created_by", "created_at", "source_policy"],
      "properties": {
        "created_by": {"type": "string", "minLength": 1},
        "reviewed_by": {"type": "string"},
        "created_at": {"type": "string", "format": "date-time"},
        "updated_at": {"type": "string", "format": "date-time"},
        "source_policy": {"type": "string", "minLength": 1},
        "change_note": {"type": "string"}
      }
    },
    "render": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "job_id": {"type": "string"},
        "output_asset_id": {"type": "string"},
        "status": {"type": "string", "enum": ["draft", "queued", "rendering", "completed", "rejected", "failed"]},
        "cost": {"type": "number", "minimum": 0},
        "currency": {"type": "string"},
        "latency_seconds": {"type": "number", "minimum": 0}
      }
    },
    "evaluation": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "hard_rejects": {"type": "array", "items": {"type": "string"}},
        "scores": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "prompt_adherence": {"$ref": "#/$defs/score"},
            "temporal_action": {"$ref": "#/$defs/score"},
            "spatial_binding": {"$ref": "#/$defs/score"},
            "identity_continuity": {"$ref": "#/$defs/score"},
            "camera_execution": {"$ref": "#/$defs/score"},
            "physics": {"$ref": "#/$defs/score"},
            "visual_quality": {"$ref": "#/$defs/score"},
            "audio_sync_quality": {"$ref": "#/$defs/score"},
            "editorial_utility": {"$ref": "#/$defs/score"}
          }
        },
        "reject_reason": {"type": "string"},
        "review_notes": {"type": "string"}
      }
    }
  },
  "$defs": {
    "score": {
      "type": "number",
      "minimum": 0,
      "maximum": 5
    }
  }
}
