Files
ECC/skills/taste-application/workflows/taste-apply.json
T
928c1dea72 feat(tasteforge): package reusable workflows and preserve native edits (#3033)
* feat: bundle standalone taste distillation and application workflows

* docs: fix imported taste skill markdown lint

* docs: align Turkish agent catalog with taste skills

* refactor: make ECC the canonical reusable video engine

* fix: preserve video duration when applying image overlays

* fix: preserve background colors in image compositing

* fix: report best-effort duration targets and shortfalls

* feat: ship verified Fusion presets with compatibility provenance

* feat(tasteforge): preserve native edits in application bundles

* feat(tasteforge): compile local preservation without hosted input

* fix: update js-yaml to patched 4.3.2

* test: report bounded Stop wrapper failure diagnostics

* fix(tasteforge): fail closed on unsafe output names, missing overlays and cadence

- cli: default report and spec paths are derived from pack name and profile
  genre; require the manifest's name pattern before using either as a
  filename part so a traversal string cannot write outside cwd/out.
- apply_local: a pack without cadence.json, or with no measured shots and
  no explicit mean_shot, raises instead of silently planning 1.0s shots and
  reporting a measured cadence.
- legacy apply: a missing overlay aborts before any paid upload; forge()
  would have rejected it after every take was generated.
- requirements-live: pin fal-client>=0.13.0, the first release whose
  subscribe() accepts client_timeout.

Addresses the five P1 findings from the independent review of #3033.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015fxHRsydPqEcYngGbqkgt1

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-10 15:31:36 +01:00

227 lines
5.1 KiB
JSON

{
"name": "taste-apply-30fps",
"title": "taste-apply-30fps",
"contents": {
"name": "workflow",
"nodes": {
"node-xfirst": {
"type": "run",
"id": "node-xfirst",
"depends": [
"input"
],
"metadata": {
"position": {
"x": 340,
"y": -320
}
},
"app": "fal-ai/ffmpeg-api/extract-frame",
"input": {
"video_url": "$input.source_video",
"frame_type": "first"
}
},
"node-gen1": {
"type": "run",
"id": "node-gen1",
"depends": [
"input",
"node-xfirst"
],
"metadata": {
"position": {
"x": 760,
"y": -320
}
},
"app": "bytedance/seedance-2.5/reference-to-video",
"input": {
"prompt": "$input.compiled_prompt",
"image_urls": [
"$node-xfirst.images.0.url"
],
"duration": "5",
"resolution": "720p",
"audio_urls": [],
"generate_audio": false
}
},
"node-xmid": {
"type": "run",
"id": "node-xmid",
"depends": [
"input"
],
"metadata": {
"position": {
"x": 340,
"y": 0
}
},
"app": "fal-ai/ffmpeg-api/extract-frame",
"input": {
"video_url": "$input.source_video",
"frame_type": "middle"
}
},
"node-gen2": {
"type": "run",
"id": "node-gen2",
"depends": [
"input",
"node-xmid"
],
"metadata": {
"position": {
"x": 760,
"y": 0
}
},
"app": "bytedance/seedance-2.5/reference-to-video",
"input": {
"prompt": "$input.compiled_prompt",
"image_urls": [
"$node-xmid.images.0.url"
],
"duration": "5",
"resolution": "720p",
"audio_urls": [],
"generate_audio": false
}
},
"node-xlast": {
"type": "run",
"id": "node-xlast",
"depends": [
"input"
],
"metadata": {
"position": {
"x": 340,
"y": 320
}
},
"app": "fal-ai/ffmpeg-api/extract-frame",
"input": {
"video_url": "$input.source_video",
"frame_type": "last"
}
},
"node-gen3": {
"type": "run",
"id": "node-gen3",
"depends": [
"input",
"node-xlast"
],
"metadata": {
"position": {
"x": 760,
"y": 320
}
},
"app": "bytedance/seedance-2.5/reference-to-video",
"input": {
"prompt": "$input.compiled_prompt",
"image_urls": [
"$node-xlast.images.0.url"
],
"duration": "5",
"resolution": "720p",
"audio_urls": [],
"generate_audio": false
}
},
"node-merge": {
"type": "run",
"id": "node-merge",
"depends": [
"node-gen1",
"node-gen2",
"node-gen3"
],
"metadata": {
"position": {
"x": 1180,
"y": 0
}
},
"app": "fal-ai/ffmpeg-api/merge-videos",
"input": {
"video_urls": [
"$node-gen1.video.url",
"$node-gen2.video.url",
"$node-gen3.video.url"
],
"target_fps": 30
}
},
"output": {
"type": "display",
"id": "output",
"depends": [
"node-merge"
],
"input": {},
"metadata": {
"position": {
"x": 1600,
"y": 0
}
},
"fields": {
"reel": "$node-merge.video",
"take_1": "$node-gen1.video",
"take_2": "$node-gen2.video",
"take_3": "$node-gen3.video"
}
}
},
"output": {
"reel": "$node-merge.video",
"take_1": "$node-gen1.video",
"take_2": "$node-gen2.video",
"take_3": "$node-gen3.video"
},
"schema": {
"input": {
"source_video": {
"name": "video_url",
"label": "Own-content source video",
"description": "Content reference; taste structure comes from compiled_prompt.",
"required": true,
"defaultValue": "",
"examples": [],
"ui": {},
"type": "string",
"modelId": "node-xfirst"
},
"compiled_prompt": {
"name": "text",
"label": "Compiled WHAT / HOW / GRADE prompt",
"description": "Compile offline with workflow_graphs.py.",
"required": true,
"defaultValue": "",
"examples": [],
"ui": {
"field": "textarea"
},
"type": "string",
"modelId": "node-gen1"
}
},
"output": {}
},
"version": "1",
"metadata": {
"input": {
"position": {
"x": 0,
"y": 0
}
}
}
}
}