{
  "format": "mosael-workflow",
  "version": 1,
  "workflow_revision": 1,
  "name": "Product into a presenter-led short",
  "description": "Everything in the narrated short, but a character from your asset library speaks the hook and the call to action on camera (with its own face and voice), while each beat in between stays a product shot voiced in the same voice, lined up with the beat and captioned, exported as a vertical short with an \"AI-generated\" label. Pick the character on “Pick the presenter” before running; it needs a front image and a voice in the asset library; real people need a consent declaration, and a cloned voice needs one too. Where a video model is available, the beats in between move, as in the narrated short (the hook and call to action are already presenter video): one more paid video generation per beat, with about (target length minus hook and call to action) ÷ the start node's beat_seconds beats. This copy includes “Put this beat in motion”: the start node's beat_seconds is every beat's length, and the video model you pick has to make that length. Without a video model, open the per-beat loop on the canvas after importing, delete “Put this beat in motion”, “File this beat's clip” and “Mute this beat's clip”, then wire the output of “Paint this beat” into the asset of “Lay it down for this beat's length” — every beat then lays a still for beat_seconds. Or add the template from the in-app gallery: without a video model it is built with stills.",
  "graph_hash": "1ea954da5a2d039e3509d31eca42f0104bb2ec1e57f517d9b6ff18ee54d40cf2",
  "graph": {
    "meta": {
      "template_id": "product_pitch_presenter",
      "template_version": 7,
      "source": "official"
    },
    "nodes": [
      {
        "id": "start",
        "type": "start",
        "name": "Product and selling points",
        "position": {
          "x": 40,
          "y": 260
        },
        "config": {
          "params": {
            "product_name": "",
            "selling_points": "",
            "audience": "刷竖屏短视频的年轻观众",
            "target_duration_seconds": 30,
            "beat_seconds": 5,
            "width": 1080,
            "height": 1920,
            "fps": 30
          },
          "required_params": [
            "product_name",
            "selling_points"
          ]
        }
      },
      {
        "id": "product_photo",
        "type": "asset",
        "name": "Pick the product photo",
        "position": {
          "x": 330,
          "y": 260
        },
        "config": {
          "asset_id": ""
        }
      },
      {
        "id": "pitch_script",
        "type": "llm",
        "name": "Write the beat-by-beat script",
        "position": {
          "x": 650,
          "y": 120
        },
        "config": {
          "profile_id": "",
          "model": "",
          "preset": "creative",
          "system": "你是带货短视频的编导。用户给你一件商品和几条卖点，你要写一条约 {{start.target_duration_seconds}} 秒、\n能直接拍的口播脚本，按\"拍\"拆开。\n\n硬性要求：\n- 前三秒必须给出观看理由，不要从\"大家好\"开始。\n- 每一拍正好 {{start.beat_seconds}} 秒（视频模型一段就出这么长），每一拍的 narration 念出来不能超过它：中文按每秒约 4 个字估，宁短勿长。\n- visual_prompt 用英文写这一拍的第一帧画面（这一拍的视频从它开始动），**商品必须出现在画面里**；不要写机位参数，不要在画面里\n  生成文字、logo 或水印；也不要把画面写成「手机屏幕里的画面」、不要加设备边框或 App 界面 ——\n  成片本来就在手机上看。\n- motion_prompt 用英文写这 {{start.beat_seconds}} 秒里画面怎么动：镜头缓慢推近、平移或环绕，光线在商品表面\n  流动，场景里轻微的动作；动作要小、在这几秒内完成，商品始终完整、清楚、不变形、不换样子。\n- 卖点只能来自用户给的那几条，不要编造功效、成分、资质或数据。\n- caption 是屏幕上的短句，不是把 narration 原样抄一遍。\n- 最多 12 拍：每一拍都要出一张画面、再出一段视频，是两次付费生成。\n\n只输出符合 JSON Schema 的对象。\n\n这一条由一位主播**出镜**说开场钩子(hook_line)和结尾号召(call_to_action):这两句是对着镜头说的话,\n口语、自然,各自念出来不超过 8 秒;它们**也算在成片时长里**。中间的每一拍是商品画面,narration 是画外音。",
          "prompt": "商品名称：{{start.product_name}}\n卖点（只能用这些）：\n{{start.selling_points}}\n目标观众：{{start.audience}}\n成片目标时长：{{start.target_duration_seconds}} 秒\n\n请写出分拍脚本。拍数 × 每拍 {{start.beat_seconds}} 秒，加上开场钩子和结尾号召念出来的时长（中文每秒约 4 个字），要接近目标时长。",
          "response_format": "json_schema",
          "json_schema_name": "product_pitch_script",
          "json_schema": {
            "type": "object",
            "properties": {
              "hook_line": {
                "type": "string",
                "description": "主播出镜说的开场钩子,中文,念出来不超过 8 秒"
              },
              "beats": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "narration": {
                      "type": "string",
                      "description": "这一拍要念的口播原文,中文;念出来不超过一拍的时长"
                    },
                    "visual_prompt": {
                      "type": "string",
                      "description": "这一拍的第一帧画面,英文;商品必须在画面里"
                    },
                    "motion_prompt": {
                      "type": "string",
                      "description": "这一拍的画面怎么动,英文:镜头的缓慢运动、光线在商品上的变化、轻微的动作"
                    },
                    "caption": {
                      "type": "string",
                      "description": "屏幕上的短句,不超过 14 字"
                    }
                  },
                  "required": [
                    "narration",
                    "visual_prompt",
                    "motion_prompt",
                    "caption"
                  ],
                  "additionalProperties": false
                },
                "minItems": 2,
                "maxItems": 12
              },
              "call_to_action": {
                "type": "string",
                "description": "主播出镜说的结尾行动号召,中文,念出来不超过 8 秒"
              }
            },
            "required": [
              "hook_line",
              "beats",
              "call_to_action"
            ],
            "additionalProperties": false
          },
          "json_schema_strict": "true",
          "temperature": 0.6,
          "max_tokens": 6000
        }
      },
      {
        "id": "fit_beats",
        "type": "fit_narration",
        "name": "Check each beat's narration fits",
        "position": {
          "x": 970,
          "y": 120
        },
        "config": {
          "items": "{{pitch_script.json.beats}}",
          "text_field": "narration",
          "seconds": "{{start.beat_seconds}}",
          "max_total_seconds": "{{start.target_duration_seconds}}",
          "reserved_text": "{{pitch_script.json.hook_line}}\n{{pitch_script.json.call_to_action}}",
          "profile_id": "",
          "model": ""
        }
      },
      {
        "id": "pitch_project",
        "type": "project_sequence_create",
        "name": "Create the vertical timeline",
        "position": {
          "x": 650,
          "y": 420
        },
        "config": {
          "name": "{{start.product_name}} · Product short",
          "width": "{{start.width}}",
          "height": "{{start.height}}",
          "fps": "{{start.fps}}"
        }
      },
      {
        "id": "presenter",
        "type": "entity_get",
        "name": "Pick the presenter (a character from the asset library)",
        "position": {
          "x": 330,
          "y": 520
        },
        "config": {
          "entity_id": "",
          "kind": "character"
        }
      },
      {
        "id": "has_hook",
        "type": "condition",
        "name": "Is there a hook line?",
        "position": {
          "x": 650,
          "y": 520
        },
        "config": {
          "left": "{{pitch_script.json.hook_line}}",
          "op": "not_empty"
        }
      },
      {
        "id": "hook_talk",
        "type": "entity_speak",
        "name": "Presenter speaks the hook",
        "position": {
          "x": 650,
          "y": 620
        },
        "config": {
          "entity_id": "",
          "text": "{{pitch_script.json.hook_line}}",
          "model": ""
        },
        "inputs": [
          "entity_id"
        ]
      },
      {
        "id": "hook_place",
        "type": "timeline_append",
        "name": "Put the hook first",
        "position": {
          "x": 970,
          "y": 620
        },
        "config": {
          "sequence_id": "",
          "asset_id": "",
          "track_id": ""
        },
        "inputs": [
          "sequence_id",
          "asset_id",
          "track_id"
        ]
      },
      {
        "id": "has_cta",
        "type": "condition",
        "name": "Is there a call to action?",
        "position": {
          "x": 650,
          "y": 720
        },
        "config": {
          "left": "{{pitch_script.json.call_to_action}}",
          "op": "not_empty"
        }
      },
      {
        "id": "cta_talk",
        "type": "entity_speak",
        "name": "Presenter speaks the call to action",
        "position": {
          "x": 650,
          "y": 800
        },
        "config": {
          "entity_id": "",
          "text": "{{pitch_script.json.call_to_action}}",
          "model": ""
        },
        "inputs": [
          "entity_id"
        ]
      },
      {
        "id": "presenter_has_voice",
        "type": "condition",
        "name": "Does the presenter have a voice?",
        "position": {
          "x": 330,
          "y": 700
        },
        "config": {
          "left": "",
          "op": "not_empty"
        },
        "inputs": [
          "left"
        ]
      },
      {
        "id": "presenter_has_face",
        "type": "condition",
        "name": "Does the presenter have an image?",
        "position": {
          "x": 330,
          "y": 860
        },
        "config": {
          "left": "",
          "op": "not_empty"
        },
        "inputs": [
          "left"
        ]
      },
      {
        "id": "presenter_voice_notice",
        "type": "notify",
        "name": "The presenter has no voice yet",
        "position": {
          "x": 40,
          "y": 860
        },
        "config": {
          "title": "Product short not started: the presenter has no voice",
          "body": "“{{presenter.name}}” has no voice yet. Give it one in the asset library (a cloned voice needs a consent declaration) and run again. Nothing has been spent."
        }
      },
      {
        "id": "presenter_face_notice",
        "type": "notify",
        "name": "The presenter has no image yet",
        "position": {
          "x": 40,
          "y": 1020
        },
        "config": {
          "title": "Product short not started: the presenter has no image",
          "body": "“{{presenter.name}}” has no front image yet. Add one in the asset library (or draw one first) and run again. Nothing has been spent."
        }
      },
      {
        "id": "cta_spoken",
        "type": "condition",
        "name": "Did the call to action come out?",
        "position": {
          "x": 970,
          "y": 800
        },
        "config": {
          "left": "",
          "op": "not_empty"
        },
        "inputs": [
          "left"
        ]
      },
      {
        "id": "cta_place",
        "type": "timeline_append",
        "name": "Put the call to action last",
        "position": {
          "x": 1290,
          "y": 800
        },
        "config": {
          "sequence_id": "",
          "asset_id": "",
          "track_id": ""
        },
        "inputs": [
          "sequence_id",
          "asset_id",
          "track_id"
        ]
      },
      {
        "id": "hook_captions",
        "type": "generate_subtitles",
        "name": "Caption the hook",
        "position": {
          "x": 1610,
          "y": 620
        },
        "config": {
          "sequence_id": "",
          "segments": "",
          "clip_id": "",
          "allow_empty": "yes"
        },
        "inputs": [
          "sequence_id",
          "segments",
          "clip_id"
        ]
      },
      {
        "id": "cta_captions",
        "type": "generate_subtitles",
        "name": "Caption the call to action",
        "position": {
          "x": 1610,
          "y": 800
        },
        "config": {
          "sequence_id": "",
          "segments": "",
          "clip_id": "",
          "allow_empty": "yes"
        },
        "inputs": [
          "sequence_id",
          "segments",
          "clip_id"
        ]
      },
      {
        "id": "shoot_beats",
        "type": "loop_foreach",
        "name": "Paint, animate, voice and place each beat",
        "position": {
          "x": 970,
          "y": 260
        },
        "config": {
          "items": "",
          "inputs": {
            "product_asset_id": "{{product_photo.asset_id}}",
            "product_name": "{{start.product_name}}",
            "project_id": "{{pitch_project.project_id}}",
            "sequence_id": "{{pitch_project.sequence_id}}",
            "video_track_id": "{{pitch_project.video_track_id}}",
            "audio_track_id": "{{pitch_project.audio_track_id}}",
            "beat_seconds": "{{start.beat_seconds}}",
            "aspect_ratio": "9:16",
            "resolution": "720p",
            "voice_engine": "{{presenter.voice_engine}}",
            "voice_id": "{{presenter.voice_id}}"
          },
          "body": {
            "nodes": [
              {
                "id": "beat_frame",
                "type": "ai_generate",
                "name": "Paint this beat",
                "position": {
                  "x": 80,
                  "y": 140
                },
                "config": {
                  "provider": "",
                  "provider_profile_id": "",
                  "model": "",
                  "kind": "image",
                  "prompt": "{{loop.item.visual_prompt}} The product in the reference image must be reproduced EXACTLY: identical cut, silhouette, colour, fabric texture, weave, print scale and placement, stitching, buttons, trims and any logo or label. Do not redesign, restyle, recolour, resize the print, add or remove details. Only the wearer, pose, setting and lighting may change. Vertical 9:16 portrait-orientation photograph, full-bleed: the scene fills the frame edge to edge. Photorealistic, no text, no logo overlay, no watermark.",
                  "negative_prompt": "different garment, altered pattern, changed colour, distorted print, redesigned collar or sleeves, extra logos, text, watermark, deformed hands, extra limbs, phone, smartphone, device frame, screen bezel, mockup, app interface",
                  "parameters": {},
                  "source_assets": [
                    "{{input.product_asset_id}}:reference_image"
                  ]
                }
              },
              {
                "id": "file_frame",
                "type": "asset_update",
                "name": "File this beat's frame",
                "position": {
                  "x": 400,
                  "y": 0
                },
                "config": {
                  "asset_ids": "",
                  "name": "{{input.product_name}} · {{loop.item.caption}}",
                  "project_id": "{{input.project_id}}"
                },
                "inputs": [
                  "asset_ids"
                ]
              },
              {
                "id": "beat_clip",
                "type": "ai_generate",
                "name": "Put this beat in motion",
                "position": {
                  "x": 400,
                  "y": 140
                },
                "config": {
                  "provider": "",
                  "provider_profile_id": "",
                  "model": "",
                  "kind": "video",
                  "prompt": "{{loop.item.motion_prompt}} The product in the reference image must be reproduced EXACTLY: identical cut, silhouette, colour, fabric texture, weave, print scale and placement, stitching, buttons, trims and any logo or label. Do not redesign, restyle, recolour, resize the print, add or remove details. Only the wearer, pose, setting and lighting may change. Subtle, natural motion only; the product stays whole, undistorted and readable throughout. No text, no logo overlay, no watermark.",
                  "negative_prompt": "different garment, altered pattern, changed colour, distorted print, redesigned collar or sleeves, extra logos, text, watermark, deformed hands, extra limbs, phone, smartphone, device frame, screen bezel, mockup, app interface",
                  "parameters": {
                    "duration_seconds": "{{input.beat_seconds}}",
                    "aspect_ratio": "{{input.aspect_ratio}}",
                    "resolution": "{{input.resolution}}",
                    "generate_audio": false
                  },
                  "source_assets": [
                    "{{beat_frame.asset_id}}:first_frame"
                  ]
                }
              },
              {
                "id": "file_clip",
                "type": "asset_update",
                "name": "File this beat's clip",
                "position": {
                  "x": 720,
                  "y": 0
                },
                "config": {
                  "asset_ids": "",
                  "name": "{{input.product_name}} · {{loop.item.caption}} · clip",
                  "project_id": "{{input.project_id}}"
                },
                "inputs": [
                  "asset_ids"
                ]
              },
              {
                "id": "mute_clip",
                "type": "edit_timeline",
                "name": "Mute this beat's clip",
                "position": {
                  "x": 1040,
                  "y": 140
                },
                "config": {
                  "sequence_id": "{{input.sequence_id}}",
                  "operations": "[{\"kind\": \"set_clip_gain\", \"clip_id\": \"{{beat_on_timeline.clip_id}}\", \"muted\": true}]"
                }
              },
              {
                "id": "beat_on_timeline",
                "type": "timeline_append",
                "name": "Lay it down for this beat's length",
                "position": {
                  "x": 720,
                  "y": 140
                },
                "config": {
                  "sequence_id": "{{input.sequence_id}}",
                  "asset_id": "",
                  "track_id": "{{input.video_track_id}}",
                  "start": 0,
                  "end": "{{input.beat_seconds}}"
                },
                "inputs": [
                  "asset_id"
                ]
              },
              {
                "id": "has_narration",
                "type": "condition",
                "name": "Does this beat have narration?",
                "position": {
                  "x": 80,
                  "y": 320
                },
                "config": {
                  "left": "{{loop.item.narration}}",
                  "op": "not_empty"
                }
              },
              {
                "id": "beat_voice",
                "type": "synthesize_speech",
                "name": "Voice this beat",
                "position": {
                  "x": 400,
                  "y": 320
                },
                "config": {
                  "text": "{{loop.item.narration}}",
                  "engine": "{{input.voice_engine}}",
                  "voice": "{{input.voice_id}}"
                }
              },
              {
                "id": "beat_voice_place",
                "type": "timeline_append",
                "name": "Line the voice up with the beat",
                "position": {
                  "x": 1040,
                  "y": 320
                },
                "config": {
                  "sequence_id": "{{input.sequence_id}}",
                  "asset_id": "",
                  "track_id": "{{input.audio_track_id}}",
                  "at": "",
                  "max_duration": "",
                  "trim_overflow": "yes"
                },
                "inputs": [
                  "asset_id",
                  "at",
                  "max_duration"
                ]
              },
              {
                "id": "voice_overflow",
                "type": "condition",
                "name": "Was the voice-over cut short?",
                "position": {
                  "x": 1360,
                  "y": 320
                },
                "config": {
                  "left": "",
                  "op": "gt",
                  "right": "0"
                },
                "inputs": [
                  "left"
                ]
              },
              {
                "id": "overflow_notice",
                "type": "notify",
                "name": "Say the voice-over was cut",
                "position": {
                  "x": 1680,
                  "y": 320
                },
                "config": {
                  "title": "Product short: a beat's voice-over didn't fit",
                  "body": "The voice-over for the “{{loop.item.caption}}” beat is still {{beat_voice_place.trimmed}} s longer than its picture at 1.5× speed, so the rest was cut. To keep the whole line, shorten that beat's narration or raise the start node's beat_seconds (to a length the video model can make) and run again."
                }
              }
            ],
            "edges": [
              {
                "id": "file_then_clip",
                "source": "file_frame",
                "target": "beat_clip"
              },
              {
                "id": "clip_file",
                "source": "beat_clip",
                "target": "file_clip"
              },
              {
                "id": "clip_place",
                "source": "beat_clip",
                "target": "beat_on_timeline"
              },
              {
                "id": "place_mute",
                "source": "beat_on_timeline",
                "target": "mute_clip"
              },
              {
                "id": "frame_file",
                "source": "beat_frame",
                "target": "file_frame"
              },
              {
                "id": "place_voice",
                "source": "beat_on_timeline",
                "target": "beat_voice_place"
              },
              {
                "id": "voice_voice_place",
                "source": "beat_voice",
                "target": "beat_voice_place"
              },
              {
                "id": "narration_voice",
                "source": "has_narration",
                "target": "beat_voice",
                "source_handle": "true"
              },
              {
                "id": "narration_voice_place",
                "source": "has_narration",
                "target": "beat_voice_place",
                "source_handle": "true"
              },
              {
                "id": "voice_overflow_check",
                "source": "beat_voice_place",
                "target": "voice_overflow"
              },
              {
                "id": "overflow_notify",
                "source": "voice_overflow",
                "target": "overflow_notice",
                "source_handle": "true"
              },
              {
                "id": "d-beat_frame-asset_id-file_frame-asset_ids",
                "source": "beat_frame",
                "target": "file_frame",
                "kind": "data",
                "source_output": "asset_id",
                "target_input": "asset_ids"
              },
              {
                "id": "d-beat_clip-asset_id-file_clip-asset_ids",
                "source": "beat_clip",
                "target": "file_clip",
                "kind": "data",
                "source_output": "asset_id",
                "target_input": "asset_ids"
              },
              {
                "id": "d-beat_clip-asset_id-beat_on_timeline-asset_id",
                "source": "beat_clip",
                "target": "beat_on_timeline",
                "kind": "data",
                "source_output": "asset_id",
                "target_input": "asset_id"
              },
              {
                "id": "d-beat_voice-asset_id-beat_voice_place-asset_id",
                "source": "beat_voice",
                "target": "beat_voice_place",
                "kind": "data",
                "source_output": "asset_id",
                "target_input": "asset_id"
              },
              {
                "id": "d-beat_on_timeline-timeline_start-beat_voice_place-at",
                "source": "beat_on_timeline",
                "target": "beat_voice_place",
                "kind": "data",
                "source_output": "timeline_start",
                "target_input": "at"
              },
              {
                "id": "d-beat_on_timeline-duration-beat_voice_place-max_duration",
                "source": "beat_on_timeline",
                "target": "beat_voice_place",
                "kind": "data",
                "source_output": "duration",
                "target_input": "max_duration"
              },
              {
                "id": "d-beat_voice_place-trimmed-voice_overflow-left",
                "source": "beat_voice_place",
                "target": "voice_overflow",
                "kind": "data",
                "source_output": "trimmed",
                "target_input": "left"
              }
            ]
          },
          "concurrency": 1,
          "output": ""
        },
        "inputs": [
          "items"
        ]
      },
      {
        "id": "beat_captions",
        "type": "generate_subtitles",
        "name": "Lay each beat's on-screen line",
        "position": {
          "x": 1290,
          "y": 260
        },
        "config": {
          "sequence_id": "",
          "segments": "",
          "start_field": "beat_on_timeline.timeline_start",
          "end_field": "beat_on_timeline.timeline_end",
          "text_field": "loop.item.caption"
        },
        "inputs": [
          "sequence_id",
          "segments"
        ]
      },
      {
        "id": "export_short",
        "type": "export_sequence",
        "name": "Export the short",
        "position": {
          "x": 1610,
          "y": 260
        },
        "config": {
          "sequence_id": ""
        },
        "inputs": [
          "sequence_id"
        ]
      },
      {
        "id": "done_notice",
        "type": "notify",
        "name": "Short is ready",
        "position": {
          "x": 1930,
          "y": 260
        },
        "config": {
          "title": "Product short exported",
          "body": "The narrated short for {{start.product_name}} is done: {{shoot_beats.count}} beats.\n{{fit_beats.note}}"
        }
      },
      {
        "id": "output",
        "type": "output",
        "name": "Hand over the short and the script",
        "position": {
          "x": 2250,
          "y": 260
        },
        "config": {
          "values": {
            "final_asset_id": "{{export_short.asset_id}}",
            "script": "{{pitch_script.json}}",
            "beat_count": "{{shoot_beats.count}}",
            "caption_count": "{{beat_captions.count}}",
            "sequence_id": "{{pitch_project.sequence_id}}",
            "hook_asset_id": "{{hook_talk.asset_id}}",
            "cta_asset_id": "{{cta_talk.asset_id}}"
          }
        }
      }
    ],
    "edges": [
      {
        "id": "start_photo",
        "source": "start",
        "target": "product_photo"
      },
      {
        "id": "start_presenter",
        "source": "start",
        "target": "presenter"
      },
      {
        "id": "presenter_voice_check",
        "source": "presenter",
        "target": "presenter_has_voice"
      },
      {
        "id": "presenter_voice_ok",
        "source": "presenter_has_voice",
        "target": "presenter_has_face",
        "source_handle": "true"
      },
      {
        "id": "presenter_voice_missing",
        "source": "presenter_has_voice",
        "target": "presenter_voice_notice",
        "source_handle": "false"
      },
      {
        "id": "presenter_face_missing",
        "source": "presenter_has_face",
        "target": "presenter_face_notice",
        "source_handle": "false"
      },
      {
        "id": "presenter_script",
        "source": "presenter_has_face",
        "target": "pitch_script",
        "source_handle": "true"
      },
      {
        "id": "script_project",
        "source": "pitch_script",
        "target": "pitch_project"
      },
      {
        "id": "presenter_hook",
        "source": "presenter",
        "target": "hook_talk"
      },
      {
        "id": "script_has_hook",
        "source": "pitch_script",
        "target": "has_hook"
      },
      {
        "id": "hook_said",
        "source": "has_hook",
        "target": "hook_talk",
        "source_handle": "true"
      },
      {
        "id": "presenter_cta",
        "source": "presenter",
        "target": "cta_talk"
      },
      {
        "id": "script_has_cta",
        "source": "pitch_script",
        "target": "has_cta"
      },
      {
        "id": "cta_said",
        "source": "has_cta",
        "target": "cta_talk",
        "source_handle": "true"
      },
      {
        "id": "hook_place_edge",
        "source": "hook_talk",
        "target": "hook_place"
      },
      {
        "id": "project_hook",
        "source": "pitch_project",
        "target": "hook_place"
      },
      {
        "id": "hook_place_gate",
        "source": "has_hook",
        "target": "hook_place",
        "source_handle": "true"
      },
      {
        "id": "hook_then_beats",
        "source": "hook_place",
        "target": "shoot_beats"
      },
      {
        "id": "script_fit",
        "source": "pitch_script",
        "target": "fit_beats"
      },
      {
        "id": "fit_shoot",
        "source": "fit_beats",
        "target": "shoot_beats"
      },
      {
        "id": "beats_then_cta",
        "source": "shoot_beats",
        "target": "cta_spoken"
      },
      {
        "id": "cta_place_edge",
        "source": "cta_talk",
        "target": "cta_place"
      },
      {
        "id": "cta_place_gate",
        "source": "cta_spoken",
        "target": "cta_place",
        "source_handle": "true"
      },
      {
        "id": "cta_then_captions",
        "source": "cta_place",
        "target": "beat_captions"
      },
      {
        "id": "shoot_captions",
        "source": "shoot_beats",
        "target": "beat_captions"
      },
      {
        "id": "beats_then_hook_captions",
        "source": "beat_captions",
        "target": "hook_captions"
      },
      {
        "id": "hook_then_cta_captions",
        "source": "hook_captions",
        "target": "cta_captions"
      },
      {
        "id": "captions_export",
        "source": "cta_captions",
        "target": "export_short"
      },
      {
        "id": "export_notice",
        "source": "export_short",
        "target": "done_notice"
      },
      {
        "id": "notice_output",
        "source": "done_notice",
        "target": "output"
      },
      {
        "id": "d-presenter-entity_id-hook_talk-entity_id",
        "source": "presenter",
        "target": "hook_talk",
        "kind": "data",
        "source_output": "entity_id",
        "target_input": "entity_id"
      },
      {
        "id": "d-pitch_project-sequence_id-hook_place-sequence_id",
        "source": "pitch_project",
        "target": "hook_place",
        "kind": "data",
        "source_output": "sequence_id",
        "target_input": "sequence_id"
      },
      {
        "id": "d-hook_talk-asset_id-hook_place-asset_id",
        "source": "hook_talk",
        "target": "hook_place",
        "kind": "data",
        "source_output": "asset_id",
        "target_input": "asset_id"
      },
      {
        "id": "d-pitch_project-video_track_id-hook_place-track_id",
        "source": "pitch_project",
        "target": "hook_place",
        "kind": "data",
        "source_output": "video_track_id",
        "target_input": "track_id"
      },
      {
        "id": "d-presenter-entity_id-cta_talk-entity_id",
        "source": "presenter",
        "target": "cta_talk",
        "kind": "data",
        "source_output": "entity_id",
        "target_input": "entity_id"
      },
      {
        "id": "d-presenter-voice_id-presenter_has_voice-left",
        "source": "presenter",
        "target": "presenter_has_voice",
        "kind": "data",
        "source_output": "voice_id",
        "target_input": "left"
      },
      {
        "id": "d-presenter-asset_ids-presenter_has_face-left",
        "source": "presenter",
        "target": "presenter_has_face",
        "kind": "data",
        "source_output": "asset_ids",
        "target_input": "left"
      },
      {
        "id": "d-cta_talk-asset_id-cta_spoken-left",
        "source": "cta_talk",
        "target": "cta_spoken",
        "kind": "data",
        "source_output": "asset_id",
        "target_input": "left"
      },
      {
        "id": "d-pitch_project-sequence_id-cta_place-sequence_id",
        "source": "pitch_project",
        "target": "cta_place",
        "kind": "data",
        "source_output": "sequence_id",
        "target_input": "sequence_id"
      },
      {
        "id": "d-cta_talk-asset_id-cta_place-asset_id",
        "source": "cta_talk",
        "target": "cta_place",
        "kind": "data",
        "source_output": "asset_id",
        "target_input": "asset_id"
      },
      {
        "id": "d-pitch_project-video_track_id-cta_place-track_id",
        "source": "pitch_project",
        "target": "cta_place",
        "kind": "data",
        "source_output": "video_track_id",
        "target_input": "track_id"
      },
      {
        "id": "d-pitch_project-sequence_id-hook_captions-sequence_id",
        "source": "pitch_project",
        "target": "hook_captions",
        "kind": "data",
        "source_output": "sequence_id",
        "target_input": "sequence_id"
      },
      {
        "id": "d-hook_talk-cues-hook_captions-segments",
        "source": "hook_talk",
        "target": "hook_captions",
        "kind": "data",
        "source_output": "cues",
        "target_input": "segments"
      },
      {
        "id": "d-hook_place-clip_id-hook_captions-clip_id",
        "source": "hook_place",
        "target": "hook_captions",
        "kind": "data",
        "source_output": "clip_id",
        "target_input": "clip_id"
      },
      {
        "id": "d-pitch_project-sequence_id-cta_captions-sequence_id",
        "source": "pitch_project",
        "target": "cta_captions",
        "kind": "data",
        "source_output": "sequence_id",
        "target_input": "sequence_id"
      },
      {
        "id": "d-cta_talk-cues-cta_captions-segments",
        "source": "cta_talk",
        "target": "cta_captions",
        "kind": "data",
        "source_output": "cues",
        "target_input": "segments"
      },
      {
        "id": "d-cta_place-clip_id-cta_captions-clip_id",
        "source": "cta_place",
        "target": "cta_captions",
        "kind": "data",
        "source_output": "clip_id",
        "target_input": "clip_id"
      },
      {
        "id": "d-fit_beats-items-shoot_beats-items",
        "source": "fit_beats",
        "target": "shoot_beats",
        "kind": "data",
        "source_output": "items",
        "target_input": "items"
      },
      {
        "id": "d-pitch_project-sequence_id-beat_captions-sequence_id",
        "source": "pitch_project",
        "target": "beat_captions",
        "kind": "data",
        "source_output": "sequence_id",
        "target_input": "sequence_id"
      },
      {
        "id": "d-shoot_beats-results-beat_captions-segments",
        "source": "shoot_beats",
        "target": "beat_captions",
        "kind": "data",
        "source_output": "results",
        "target_input": "segments"
      },
      {
        "id": "d-pitch_project-sequence_id-export_short-sequence_id",
        "source": "pitch_project",
        "target": "export_short",
        "kind": "data",
        "source_output": "sequence_id",
        "target_input": "sequence_id"
      }
    ]
  }
}
