stillmade-sdk 0.1.41 → 0.1.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (285) hide show
  1. package/.stillmade/sdk-baseline.json +19 -21
  2. package/AGENTS.md +17 -12
  3. package/FRAME_VIEWS.md +113 -0
  4. package/INTERFACE_DESIGN.md +67 -22
  5. package/MOBILE_UI.md +4 -2
  6. package/MODULES.md +152 -6
  7. package/PASTE_TO_LLM.md +42 -32
  8. package/README.md +3 -2
  9. package/SDK.md +1028 -563
  10. package/UI_AESTHETIC.md +30 -3
  11. package/blocks/generate/package.js +1 -0
  12. package/blocks/generate/versions/1.0.0/package.js +463 -0
  13. package/docs/build/audio-to-editor.md +36 -0
  14. package/docs/build/block-builder-contract.md +150 -0
  15. package/docs/build/comfyui.md +227 -0
  16. package/docs/build/concepts.md +40 -0
  17. package/docs/build/context.md +159 -0
  18. package/docs/build/cookbook.md +57 -0
  19. package/docs/build/custom-interface.md +617 -0
  20. package/docs/build/data-types.md +83 -0
  21. package/docs/build/frame-views.md +259 -0
  22. package/docs/build/generate-media.md +59 -0
  23. package/docs/build/github-applications.md +314 -0
  24. package/docs/build/hosted-images.md +214 -0
  25. package/docs/build/hosted-music.md +39 -0
  26. package/docs/build/hosted-speech.md +157 -0
  27. package/docs/build/hosted-text.md +246 -0
  28. package/docs/build/image-description.md +49 -0
  29. package/docs/build/interface-design.md +343 -0
  30. package/docs/build/javascript.md +63 -0
  31. package/docs/build/local-preview.md +61 -0
  32. package/docs/build/media-analysis.md +27 -0
  33. package/docs/build/media.md +400 -0
  34. package/docs/build/mobile-ui.md +106 -0
  35. package/docs/build/modules.md +487 -0
  36. package/docs/build/original-blocks.md +70 -0
  37. package/docs/build/outside-apis.md +128 -0
  38. package/docs/build/production-context-templates.md +12 -0
  39. package/docs/build/project-storage.md +94 -0
  40. package/docs/build/quickstart.md +48 -0
  41. package/docs/build/recipes.md +103 -0
  42. package/docs/build/script-handoff.md +45 -0
  43. package/docs/build/script-writer.md +34 -0
  44. package/docs/build/state.md +223 -0
  45. package/docs/build/testing.md +112 -0
  46. package/docs/build/timeline-edits.md +116 -0
  47. package/docs/build/timeline-proposals.md +76 -0
  48. package/docs/build/transcription.md +59 -0
  49. package/docs/build/triggers.md +59 -0
  50. package/docs/build/tutorial.md +52 -0
  51. package/docs/build/typescript.md +34 -0
  52. package/docs/build/video-generation.md +61 -0
  53. package/docs/build/web-reading.md +37 -0
  54. package/docs/build/with-your-ai.md +27 -0
  55. package/docs/changelog.md +9 -0
  56. package/docs/creators.md +21 -0
  57. package/docs/distribute/discovery.md +43 -0
  58. package/docs/distribute/imports.md +58 -0
  59. package/docs/distribute/publishing.md +29 -0
  60. package/docs/distribute/sdk-versions.md +36 -0
  61. package/docs/distribute/selling.md +14 -0
  62. package/docs/distribute/teams.md +60 -0
  63. package/docs/distribute/versioning.md +28 -0
  64. package/docs/examples.md +23 -0
  65. package/docs/gallery.md +26 -0
  66. package/docs/index.md +50 -0
  67. package/docs/native-mcp.md +307 -0
  68. package/docs/project-types/automation.md +43 -0
  69. package/docs/project-types/batches.md +50 -0
  70. package/docs/project-types/build.md +42 -0
  71. package/docs/project-types/completion.md +15 -0
  72. package/docs/project-types/conditions.md +21 -0
  73. package/docs/project-types/hosted-review.md +115 -0
  74. package/docs/project-types/onboarding.md +75 -0
  75. package/docs/project-types/running.md +309 -0
  76. package/docs/project-types/testing.md +72 -0
  77. package/docs/reference/application-artifacts.md +87 -0
  78. package/docs/reference/authoring-guide.md +134 -0
  79. package/docs/reference/browser-applications.md +267 -0
  80. package/docs/reference/capabilities.md +45 -0
  81. package/docs/reference/cli.md +71 -0
  82. package/docs/reference/connection-api.md +59 -0
  83. package/docs/reference/cooperative-jobs.md +13 -0
  84. package/docs/reference/desktop-capabilities.md +172 -0
  85. package/docs/reference/desktop-execution.md +77 -0
  86. package/docs/reference/errors.md +233 -0
  87. package/docs/reference/execution.md +800 -0
  88. package/docs/reference/first-party-blocks.md +40 -0
  89. package/docs/reference/generation-models.md +59 -0
  90. package/docs/reference/limits.md +306 -0
  91. package/docs/reference/manifest-kinds-controls.md +36 -0
  92. package/docs/reference/manifest.md +181 -0
  93. package/docs/reference/operations.md +36 -0
  94. package/docs/reference/package-jobs.md +35 -0
  95. package/docs/reference/parity.md +55 -0
  96. package/docs/reference/permissions.md +86 -0
  97. package/docs/reference/ports.md +26 -0
  98. package/docs/reference/types.md +268 -0
  99. package/docs/reference/universal-resolver.md +303 -0
  100. package/docs/reference/view-bridge.md +60 -0
  101. package/docs/reference/view-rules.md +15 -0
  102. package/docs/reference/workspace-sync.md +25 -0
  103. package/docs/sdk.md +34 -0
  104. package/docs/tools/block-remix.md +211 -0
  105. package/docs/tools/llm.md +2213 -0
  106. package/docs/tools/repository-adaptation.md +613 -0
  107. package/examples/check-clip.stillmade.json +8 -1
  108. package/examples/clean-text.stillmade.json +4 -0
  109. package/examples/custom-interface.stillmade.json +4 -0
  110. package/examples/describe-image.stillmade.json +4 -0
  111. package/examples/foley-cue.stillmade.json +4 -0
  112. package/examples/generate-image.stillmade.json +4 -0
  113. package/examples/generate-video.stillmade.json +10 -2
  114. package/examples/module-word-stats/stillmade.block.json +4 -0
  115. package/examples/narrate-script.stillmade.json +4 -0
  116. package/examples/numbered-takes.stillmade.json +4 -0
  117. package/examples/research-topic.stillmade.json +9 -1
  118. package/examples/score-a-scene.stillmade.json +4 -0
  119. package/examples/script-draft.stillmade.json +4 -0
  120. package/examples/summarize-page.stillmade.json +4 -0
  121. package/examples/text-workflow.stillmade.json +7 -32
  122. package/examples/thicken-lines.stillmade.json +4 -0
  123. package/examples/timeline-polish.stillmade.json +15 -3
  124. package/examples/transcribe-audio.stillmade.json +15 -3
  125. package/examples/word-count.stillmade.json +4 -0
  126. package/package.json +1 -1
  127. package/packages/block-cli/cli.js +13 -6
  128. package/packages/block-cli/dev-host/assets/host.js +81 -38
  129. package/packages/block-cli/dev-host/assets/index.css +1 -1
  130. package/packages/block-cli/format.js +1 -1
  131. package/packages/block-cli/ready-gate.js +4 -0
  132. package/packages/block-cli/templates.js +37 -19
  133. package/packages/block-cli/type-packages.js +119 -0
  134. package/packages/block-platform/block-readiness.js +8 -1
  135. package/packages/block-platform/canvas.js +2 -1
  136. package/packages/block-platform/catalog.js +27 -48
  137. package/packages/block-platform/native-host-inventory.js +0 -226
  138. package/packages/block-platform/plain-descriptions.js +1 -25
  139. package/packages/block-platform/project-type-starters.js +13 -53
  140. package/packages/block-platform/script-handoff.js +2 -4
  141. package/packages/block-platform/type-workspace.js +2 -0
  142. package/packages/block-sdk/appearance.js +3 -1
  143. package/packages/block-sdk/audio-generation-example.js +2 -2
  144. package/packages/block-sdk/block-tier.js +1 -1
  145. package/packages/block-sdk/builder-contract.js +13 -11
  146. package/packages/block-sdk/capabilities.js +1 -1
  147. package/packages/block-sdk/capability-example.js +1 -1
  148. package/packages/block-sdk/contracts.js +6 -2
  149. package/packages/block-sdk/examples.js +3 -3
  150. package/packages/block-sdk/first-party-identities.js +1 -84
  151. package/packages/block-sdk/first-party-packages.js +3 -85
  152. package/packages/block-sdk/generation-catalog.js +15 -3
  153. package/packages/block-sdk/image-description-example.js +1 -1
  154. package/packages/block-sdk/image-generation-example.js +1 -1
  155. package/packages/block-sdk/index.d.ts +2 -1
  156. package/packages/block-sdk/media-analysis-example.js +2 -2
  157. package/packages/block-sdk/mock-host.js +7 -1
  158. package/packages/block-sdk/module-example.js +1 -1
  159. package/packages/block-sdk/module-host-calls.js +35 -10
  160. package/packages/block-sdk/module-hosted.js +15 -2
  161. package/packages/block-sdk/module-media-access.js +71 -0
  162. package/packages/block-sdk/module-node.js +1 -1
  163. package/packages/block-sdk/portable-media-actions.js +1 -1
  164. package/packages/block-sdk/runtime.js +1 -1
  165. package/packages/block-sdk/speech-example.js +1 -1
  166. package/packages/block-sdk/state-example.js +1 -1
  167. package/packages/block-sdk/timeline-proposal-example.js +1 -1
  168. package/packages/block-sdk/transcription-example.js +1 -1
  169. package/packages/block-sdk/trigger-examples.js +2 -2
  170. package/packages/block-sdk/video-generation-example.js +1 -1
  171. package/packages/block-sdk/view-bridge.js +4 -1
  172. package/packages/block-sdk/view-design.js +44 -15
  173. package/packages/block-sdk/web-example.js +2 -2
  174. package/packages/design-system/block-kit.css +53 -12
  175. package/packages/design-system/block-kit.html +3 -2
  176. package/blocks/mcp-motion-planner/versions/1.1.0/package.js +0 -97
  177. package/blocks/motion-designer/versions/1.0.1/package.js +0 -173318
  178. package/blocks/motion-designer/versions/1.0.2/package.js +0 -173318
  179. package/blocks/motion-frame-review/versions/1.1.1/package.js +0 -465
  180. package/blocks/motion-frame-review/versions/1.1.2/package.snapshot.js +0 -572
  181. package/blocks/narration/package.js +0 -1
  182. package/blocks/narration/versions/1.0.0/package.js +0 -221
  183. package/blocks/narration/versions/1.0.1/package.js +0 -221
  184. package/blocks/native/sm.animated-scene/versions/2.0.0/package.js +0 -475
  185. package/blocks/native/sm.animated-scene/versions/2.1.0/package.js +0 -498
  186. package/blocks/native/sm.animated-scene/versions/2.2.0/package.js +0 -524
  187. package/blocks/native/sm.animated-scene/versions/2.3.0/package.js +0 -618
  188. package/blocks/native/sm.animated-scene/versions/2.3.1/package.js +0 -618
  189. package/blocks/native/sm.animated-scene/versions/2.3.2/package.js +0 -723
  190. package/blocks/native/sm.animated-scene/versions/2.3.3/package.js +0 -723
  191. package/blocks/native/sm.animated-scene/versions/2.3.4/package.js +0 -676
  192. package/blocks/native/sm.animated-scene/versions/2.3.5/package.js +0 -693
  193. package/blocks/native/sm.animated-scene/versions/2.3.6/package.js +0 -700
  194. package/blocks/native/sm.animated-scene/versions/2.3.7/package.js +0 -747
  195. package/blocks/native/sm.animated-scene/versions/2.3.8/package.js +0 -769
  196. package/blocks/native/sm.animated-scene/versions/2.3.9/package.js +0 -769
  197. package/blocks/native/sm.animated-scene-assistant/versions/1.0.0/package.js +0 -183
  198. package/blocks/native/sm.blueprint/versions/2.0.0/package.js +0 -358
  199. package/blocks/native/sm.blueprint/versions/2.1.0/package.js +0 -358
  200. package/blocks/native/sm.blueprint/versions/2.1.1/package.js +0 -358
  201. package/blocks/native/sm.blueprint/versions/2.1.2/package.js +0 -358
  202. package/blocks/native/sm.blueprint/versions/2.1.3/package.js +0 -381
  203. package/blocks/native/sm.blueprint/versions/2.1.4/package.js +0 -381
  204. package/blocks/native/sm.blueprint/versions/2.1.5/package.js +0 -339
  205. package/blocks/native/sm.blueprint/versions/2.1.6/package.js +0 -356
  206. package/blocks/native/sm.blueprint/versions/2.1.7/package.js +0 -363
  207. package/blocks/native/sm.blueprint/versions/2.1.8/package.js +0 -410
  208. package/blocks/native/sm.blueprint/versions/2.1.9/package.js +0 -422
  209. package/blocks/native/sm.blueprint-assistant/versions/1.0.0/package.js +0 -172
  210. package/blocks/native/sm.chat/versions/2.0.0/package.js +0 -144
  211. package/blocks/native/sm.chat/versions/2.0.1/package.js +0 -97
  212. package/blocks/native/sm.chat/versions/2.0.2/package.js +0 -100
  213. package/blocks/native/sm.chat/versions/2.0.3/package.js +0 -100
  214. package/blocks/native/sm.continue-if/versions/1.0.0/package.js +0 -168
  215. package/blocks/native/sm.describe-media/versions/2.0.0/package.js +0 -153
  216. package/blocks/native/sm.describe-media/versions/2.0.1/package.js +0 -156
  217. package/blocks/native/sm.describe-media/versions/2.1.0/package.js +0 -140
  218. package/blocks/native/sm.image-editor/versions/2.0.0/package.js +0 -183
  219. package/blocks/native/sm.image-editor/versions/2.0.1/package.js +0 -190
  220. package/blocks/native/sm.new-items/versions/1.0.0/package.js +0 -191
  221. package/blocks/native/sm.pick-photos/versions/1.0.0/package.js +0 -334
  222. package/blocks/native/sm.quality-audit/versions/1.0.0/package.js +0 -192
  223. package/blocks/native/sm.quality-audit/versions/1.0.1/package.js +0 -192
  224. package/blocks/native/sm.quality-audit/versions/1.0.2/package.js +0 -195
  225. package/blocks/native/sm.research/versions/2.0.0/package.js +0 -175
  226. package/blocks/native/sm.research/versions/2.0.1/package.js +0 -184
  227. package/blocks/native/sm.research/versions/2.0.2/package.js +0 -187
  228. package/blocks/native/sm.script/versions/2.0.0/package.js +0 -144
  229. package/blocks/native/sm.script/versions/2.1.0/package.js +0 -144
  230. package/blocks/native/sm.script/versions/2.1.1/package.js +0 -144
  231. package/blocks/native/sm.script/versions/2.1.2/package.js +0 -105
  232. package/blocks/native/sm.script/versions/2.1.3/package.js +0 -152
  233. package/blocks/native/sm.script/versions/2.1.4/package.js +0 -156
  234. package/blocks/native/sm.script/versions/2.1.5/package.js +0 -156
  235. package/blocks/native/sm.shot-plan/versions/2.0.0/package.js +0 -301
  236. package/blocks/native/sm.shot-plan/versions/2.1.0/package.js +0 -528
  237. package/blocks/native/sm.shot-plan/versions/2.1.1/package.js +0 -528
  238. package/blocks/native/sm.shot-plan/versions/2.1.2/package.js +0 -528
  239. package/blocks/native/sm.shot-plan/versions/2.1.3/package.js +0 -536
  240. package/blocks/native/sm.shot-plan/versions/2.2.0/package.js +0 -800
  241. package/blocks/native/sm.shot-plan/versions/2.2.1/package.js +0 -920
  242. package/blocks/native/sm.shot-plan-assistant/versions/1.0.0/package.js +0 -173
  243. package/blocks/native/sm.stock-search/versions/2.0.0/package.js +0 -174
  244. package/blocks/native/sm.thumbnail/versions/2.0.0/package.js +0 -137
  245. package/blocks/native/sm.thumbnail/versions/2.0.1/package.js +0 -140
  246. package/blocks/native/sm.transcribe/versions/2.0.0/package.js +0 -163
  247. package/blocks/native/sm.transcribe/versions/2.0.1/package.js +0 -168
  248. package/blocks/native/sm.whiteboard-assistant/versions/1.0.0/package.js +0 -175
  249. package/blocks/native/sm.youtube/versions/2.0.0/package.js +0 -217
  250. package/blocks/occasion-story/package.js +0 -1
  251. package/blocks/occasion-story/versions/1.0.0/package.js +0 -1658
  252. package/blocks/occasion-story/versions/1.0.1/package.js +0 -1699
  253. package/blocks/occasion-story/versions/1.0.2/package.js +0 -1682
  254. package/blocks/photo-reel-composer/versions/1.0.0/package.js +0 -3043
  255. package/blocks/photo-reel-composer/versions/1.0.1/package.js +0 -3026
  256. package/blocks/photo-reel-composer/versions/1.0.2/package.js +0 -4149
  257. package/blocks/product-ad-variants/versions/1.0.0/package.js +0 -2911
  258. package/blocks/product-launch-director/versions/1.0.0/package.js +0 -103
  259. package/blocks/release-visuals/package.js +0 -1
  260. package/blocks/release-visuals/versions/1.0.0/package.js +0 -1492
  261. package/blocks/release-visuals/versions/1.0.1/package.js +0 -1517
  262. package/blocks/release-visuals/versions/1.0.2/package.js +0 -1500
  263. package/blocks/screen-recorder/package.js +0 -1
  264. package/blocks/screen-recorder/versions/1.0.0/package.js +0 -223
  265. package/blocks/screen-recorder/versions/1.0.1/package.js +0 -223
  266. package/blocks/short-form-finish/package.js +0 -1
  267. package/blocks/short-form-finish/versions/1.0.0/package.js +0 -1043
  268. package/blocks/short-form-finish/versions/1.0.1/package.js +0 -1043
  269. package/blocks/short-form-finish/versions/1.0.2/package.js +0 -1043
  270. package/blocks/short-form-finish/versions/1.0.3/package.js +0 -1026
  271. package/examples/saas-product-launch-reviewed-source.stillmade.json +0 -383
  272. package/examples/saas-product-launch.stillmade.json +0 -304
  273. package/packages/block-platform/dealer-inventory-video-project-type.js +0 -38
  274. package/packages/block-platform/first-revenue-project-types.js +0 -46
  275. package/packages/block-platform/fixture-starters.js +0 -13
  276. package/packages/block-platform/launch-project-source.js +0 -10
  277. package/packages/block-platform/launch-project.js +0 -30
  278. package/packages/block-platform/motion-project-types.js +0 -55
  279. package/packages/block-platform/motion-starters.js +0 -14
  280. package/packages/block-platform/product-ad-variants-project-type.js +0 -30
  281. package/packages/block-platform/product-launch-updated.js +0 -90
  282. package/packages/block-platform/revenue-review-project-types.js +0 -36
  283. package/packages/block-platform/revenue-review-starters.js +0 -13
  284. package/packages/block-platform/script-writer.js +0 -29
  285. package/packages/block-platform/website-source-block.js +0 -14
@@ -1,3026 +0,0 @@
1
- // Generated from the owned 1.0.1 manifest, runtime and fixtures.
2
- export default {
3
- "manifest": {
4
- "schemaVersion": 1,
5
- "sdkVersion": "0.1.0",
6
- "id": "stillmade.photo-reel-composer",
7
- "version": "1.0.1",
8
- "name": "Photo Reel Composer",
9
- "kind": "task",
10
- "runtime": "javascript",
11
- "entry": "src/run.js",
12
- "license": "MIT",
13
- "description": "Arrange original property or product photos and approved copy into a restrained, editable 20–30 second reel. No generated imagery or model calls.",
14
- "inputs": {
15
- "assets": {
16
- "type": "asset[]",
17
- "primary": true,
18
- "default": [],
19
- "description": "Ordered original photo references. Property: 6–8 photos. Product: 3–10. Exact versions and measured dimensions are required.",
20
- "semantic": "legacy.asset-list.assets",
21
- "required": true,
22
- "sources": [
23
- "upstream",
24
- "user"
25
- ]
26
- },
27
- "purpose": {
28
- "type": "text",
29
- "default": "property",
30
- "description": "Property or product photo reel.",
31
- "semantic": "stillmade.photo_reel.purpose",
32
- "required": false,
33
- "sources": [
34
- "user",
35
- "default"
36
- ]
37
- },
38
- "title": {
39
- "type": "text",
40
- "default": "",
41
- "description": "Approved title, up to 64 characters. Use only facts supplied and reviewed by the customer.",
42
- "semantic": "stillmade.photo_reel.title",
43
- "required": true,
44
- "sources": [
45
- "user",
46
- "default"
47
- ]
48
- },
49
- "captions": {
50
- "type": "text",
51
- "default": "",
52
- "description": "One approved short caption per photo, one line each, up to 64 characters per line. Leave all empty for an uncaptioned sequence.",
53
- "semantic": "stillmade.photo_reel.captions",
54
- "required": false,
55
- "sources": [
56
- "user",
57
- "default"
58
- ]
59
- },
60
- "cta": {
61
- "type": "text",
62
- "default": "",
63
- "description": "Approved call to action, up to 56 characters.",
64
- "semantic": "stillmade.photo_reel.cta",
65
- "required": true,
66
- "sources": [
67
- "user",
68
- "default"
69
- ]
70
- },
71
- "contact": {
72
- "type": "text",
73
- "default": "",
74
- "description": "Exact contact or short destination to display, up to 64 characters.",
75
- "semantic": "stillmade.photo_reel.contact",
76
- "required": false,
77
- "sources": [
78
- "user",
79
- "default"
80
- ]
81
- },
82
- "demoDisclosure": {
83
- "type": "text",
84
- "default": "",
85
- "description": "Optional exact disclosure shown throughout, such as Stock-photo demonstration · not a live listing.",
86
- "semantic": "stillmade.photo_reel.demodisclosure",
87
- "required": false,
88
- "sources": [
89
- "user",
90
- "default"
91
- ]
92
- },
93
- "duration": {
94
- "type": "number",
95
- "default": 24,
96
- "min": 20,
97
- "max": 30,
98
- "description": "Total reel duration in seconds, including the four-second closing card.",
99
- "semantic": "stillmade.photo_reel.duration",
100
- "required": false,
101
- "sources": [
102
- "user",
103
- "default"
104
- ]
105
- },
106
- "aspect": {
107
- "type": "text",
108
- "default": "9:16",
109
- "description": "Output frame shape; photos always retain their full original rectangle.",
110
- "semantic": "stillmade.photo_reel.aspect",
111
- "required": false,
112
- "sources": [
113
- "user",
114
- "default"
115
- ]
116
- },
117
- "logo": {
118
- "type": "asset[]",
119
- "default": [],
120
- "description": "Optional single original logo image with exact version and measured dimensions.",
121
- "semantic": "stillmade.photo_reel.logo",
122
- "required": false,
123
- "sources": [
124
- "user",
125
- "default"
126
- ]
127
- },
128
- "music": {
129
- "type": "asset[]",
130
- "default": [],
131
- "description": "Optional single licensed audio track with measured duration covering the reel. Otherwise output is silent.",
132
- "semantic": "stillmade.photo_reel.music",
133
- "required": false,
134
- "sources": [
135
- "user",
136
- "default"
137
- ]
138
- }
139
- },
140
- "outputs": {
141
- "timeline": {
142
- "type": "timeline",
143
- "primary": true,
144
- "semantic": "legacy.timeline.updatededitor",
145
- "description": "Editable complete Editor timeline containing original photo clips, approved text, optional music and logo."
146
- },
147
- "review": {
148
- "type": "json",
149
- "description": "Structural checks and remaining human review. Does not authorize export or certify claims or rights.",
150
- "semantic": "stillmade.photo_reel.review",
151
- "schema": {
152
- "schemaVersion": "integer",
153
- "state": "string",
154
- "durationSec": "number",
155
- "aspect": "string",
156
- "photoCount": "integer",
157
- "checks": [
158
- {
159
- "id": "string",
160
- "passed": "boolean",
161
- "note": "string"
162
- }
163
- ],
164
- "warnings": "string[]",
165
- "humanApproved": "boolean",
166
- "exportAuthorized": "boolean",
167
- "cost": {
168
- "providerCalls": "integer",
169
- "generationCredits": "integer",
170
- "note": "string"
171
- }
172
- }
173
- },
174
- "provenance": {
175
- "type": "json",
176
- "description": "Versioned source references, supplied copy and bounded transformation record.",
177
- "semantic": "stillmade.photo_reel.provenance",
178
- "schema": {
179
- "schemaVersion": "integer",
180
- "kind": "string",
181
- "block": {
182
- "id": "string",
183
- "version": "string"
184
- },
185
- "purpose": "string",
186
- "sourcePhotos": [
187
- {
188
- "index": "integer",
189
- "assetId": "string",
190
- "versionId": "string",
191
- "width": "number",
192
- "height": "number"
193
- }
194
- ],
195
- "logo": "json",
196
- "music": "json",
197
- "approvedCopy": {
198
- "title": "string",
199
- "captions": "string[]",
200
- "cta": "string",
201
- "contact": "string",
202
- "demoDisclosure": "string"
203
- },
204
- "rights": {
205
- "userConfirmed": "boolean",
206
- "independentlyVerified": "boolean"
207
- },
208
- "transformations": "string[]",
209
- "generativeMedia": "boolean",
210
- "providerCalls": "integer"
211
- }
212
- }
213
- },
214
- "permissions": {
215
- "project": [
216
- "asset.read"
217
- ],
218
- "network": [],
219
- "filesystem": [],
220
- "secrets": []
221
- },
222
- "ui": [
223
- {
224
- "port": "purpose",
225
- "control": "select",
226
- "options": [
227
- "property",
228
- "product"
229
- ]
230
- },
231
- {
232
- "port": "aspect",
233
- "control": "select",
234
- "options": [
235
- "9:16",
236
- "16:9",
237
- "1:1"
238
- ]
239
- },
240
- {
241
- "port": "duration",
242
- "control": "slider",
243
- "min": 20,
244
- "max": 30,
245
- "step": 1
246
- }
247
- ],
248
- "platforms": {
249
- "phone": {
250
- "supported": true
251
- },
252
- "browser": {
253
- "supported": true
254
- },
255
- "desktop": {
256
- "supported": true
257
- }
258
- },
259
- "provenance": {
260
- "notice": "Original source (authorship declared by the packager)\nLicense: MIT\nChanges: Original implementation declared by the packager; no reused repository or dependency code.\nFiles: LICENSE, src/run.js\n\nMIT License\n\nCopyright (c) <year> <copyright holders>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and \nassociated documentation files (the \"Software\"), to deal in the Software without restriction, including \nwithout limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell \ncopies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the \nfollowing conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial \nportions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT \nLIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO \nEVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER \nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE \nUSE OR OTHER DEALINGS IN THE SOFTWARE.\n",
261
- "portableSources": [
262
- {
263
- "kind": "original",
264
- "license": "MIT",
265
- "paths": [
266
- "LICENSE",
267
- "src/run.js"
268
- ],
269
- "evidence": [
270
- "upstream/0/LICENSE",
271
- "upstream/0/src/run.js"
272
- ],
273
- "changes": "Original implementation declared by the packager; no reused repository or dependency code."
274
- }
275
- ]
276
- },
277
- "semantics": [
278
- {
279
- "name": "stillmade.photo_reel.purpose",
280
- "description": "Property or product photo reel.",
281
- "parents": []
282
- },
283
- {
284
- "name": "stillmade.photo_reel.title",
285
- "description": "Approved title, up to 64 characters. Use only facts supplied and reviewed by the customer.",
286
- "parents": []
287
- },
288
- {
289
- "name": "stillmade.photo_reel.captions",
290
- "description": "One approved short caption per photo, one line each, up to 64 characters per line. Leave all empty for an uncaptioned sequence.",
291
- "parents": []
292
- },
293
- {
294
- "name": "stillmade.photo_reel.cta",
295
- "description": "Approved call to action, up to 56 characters.",
296
- "parents": []
297
- },
298
- {
299
- "name": "stillmade.photo_reel.contact",
300
- "description": "Exact contact or short destination to display, up to 64 characters.",
301
- "parents": []
302
- },
303
- {
304
- "name": "stillmade.photo_reel.demodisclosure",
305
- "description": "Optional exact disclosure shown throughout, such as Stock-photo demonstration · not a live listing.",
306
- "parents": []
307
- },
308
- {
309
- "name": "stillmade.photo_reel.duration",
310
- "description": "Total reel duration in seconds, including the four-second closing card.",
311
- "parents": []
312
- },
313
- {
314
- "name": "stillmade.photo_reel.aspect",
315
- "description": "Output frame shape; photos always retain their full original rectangle.",
316
- "parents": []
317
- },
318
- {
319
- "name": "stillmade.photo_reel.logo",
320
- "description": "Optional single original logo image with exact version and measured dimensions.",
321
- "parents": []
322
- },
323
- {
324
- "name": "stillmade.photo_reel.music",
325
- "description": "Optional single licensed audio track with measured duration covering the reel. Otherwise output is silent.",
326
- "parents": []
327
- },
328
- {
329
- "name": "stillmade.photo_reel.review",
330
- "description": "Structural checks and remaining human review. Does not authorize export or certify claims or rights.",
331
- "parents": []
332
- },
333
- {
334
- "name": "stillmade.photo_reel.provenance",
335
- "description": "Versioned source references, supplied copy and bounded transformation record.",
336
- "parents": []
337
- }
338
- ]
339
- },
340
- "code": "// Photo Reel Composer 1.0.1. Runs only inside the isolated SDK JavaScript runtime.\n// Rights to supplied media are confirmed in the Content & IP Policy at sign-up.\n// References and supplied copy are data; this Block never reads media bytes,\n// calls a model, changes a photo, authorizes an export, or verifies legal rights.\nconst clone = value => JSON.parse(JSON.stringify(value));\nconst fail = (ok, message) => { if (!ok) throw new Error(message); };\nconst clean = (value, label, maximum, required = false) => {\n fail(value === undefined || typeof value === 'string', label + ' must be text.');\n const text = (value || '').trim();\n fail((!required || text.length > 0) && text.length <= maximum, label + ' must contain ' + (required ? '1' : '0') + ' to ' + maximum + ' characters.');\n fail(!/[\\u0000-\\u0008\\u000b\\u000c\\u000e-\\u001f]/.test(text), label + ' contains unsupported control characters.');\n fail(text.split(/\\s+/).every(word => word.length <= 28), label + ' contains a word or link too long to fit. Use a shorter display label.');\n return text;\n};\nconst purpose = input.purpose || 'property';\nfail(['property', 'product'].includes(purpose), 'Choose property or product.');\nconst assets = input.assets;\nconst minimum = purpose === 'property' ? 6 : 3;\nconst maximum = purpose === 'property' ? 8 : 10;\nfail(Array.isArray(assets) && assets.length >= minimum && assets.length <= maximum, 'Choose ' + minimum + ' to ' + maximum + ' original photos, in the order they should appear.');\nconst validMedia = (asset, kind, label) => {\n fail(asset && typeof asset === 'object' && !Array.isArray(asset) && asset.kind === kind, label + ' must be a ' + kind + ' reference.');\n fail(typeof asset.assetId === 'string' && asset.assetId.length > 0 && asset.assetId.length <= 240 && typeof asset.versionId === 'string' && asset.versionId.length > 0 && asset.versionId.length <= 240, label + ' needs its exact asset and version identities.');\n const mediaUrl = asset.url;\n const supportedUrl = typeof mediaUrl === 'string' && mediaUrl.length > 0 && mediaUrl.length <= 200000 && (\n /^\\/api\\/media\\/[A-Za-z0-9_-]+\\/[A-Za-z0-9_-][A-Za-z0-9._-]*$/.test(mediaUrl) ||\n /^(https:\\/\\/|http:\\/\\/(127\\.0\\.0\\.1|localhost)(:\\d+)?\\/|data:(image\\/(png|jpeg|webp)|audio\\/[a-z0-9.+-]+);base64,|blob:|sm-media:)/i.test(mediaUrl)\n ) && !/^https?:\\/\\/[^/?#]*@/i.test(mediaUrl);\n fail(supportedUrl, label + ' needs an authorized media reference.');\n if (kind === 'image') fail(Number.isFinite(asset.width) && asset.width > 0 && asset.width <= 40000 && Number.isFinite(asset.height) && asset.height > 0 && asset.height <= 40000, label + ' needs its measured original width and height. Upload this original photo again to record its dimensions.');\n return clone(asset);\n};\nconst photos = assets.map((asset, index) => validMedia(asset, 'image', 'Photo ' + (index + 1)));\nfail(new Set(photos.map(asset => asset.assetId + '\\n' + asset.versionId)).size === photos.length, 'Remove duplicate photo versions before composing.');\nconst title = clean(input.title, 'Approved title', 64, true);\nconst cta = clean(input.cta, 'Approved call to action', 56, true);\nconst contact = clean(input.contact, 'Contact or destination', 64);\nconst demoDisclosure = clean(input.demoDisclosure, 'Demo disclosure', 72);\nconst captionsText = input.captions || '';\nfail(typeof captionsText === 'string' && captionsText.length <= 1600, 'Use one short approved caption per photo.');\nconst captions = captionsText.trim() ? captionsText.replace(/\\r/g, '').split('\\n').map((line, index) => clean(line, 'Photo caption ' + (index + 1), 64)) : [];\nfail(captions.length === 0 || captions.length === photos.length, 'Supply exactly one caption line per photo, or leave captions empty. Blank lines keep a photo uncaptioned.');\n\nconst duration = input.duration === undefined ? 24 : input.duration;\nfail(Number.isFinite(duration) && duration >= 20 && duration <= 30, 'Choose a duration from 20 to 30 seconds.');\nconst aspect = input.aspect || '9:16';\nfail(['9:16', '16:9', '1:1'].includes(aspect), 'Choose 9:16, 16:9 or 1:1.');\nconst extra = (value, kind, label) => {\n fail(value === undefined || Array.isArray(value) && value.length <= 1, 'Choose at most one ' + label + '.');\n return value && value.length ? validMedia(value[0], kind, label) : null;\n};\nconst logo = extra(input.logo, 'image', 'logo');\nconst music = extra(input.music, 'audio', 'music track');\nif (music) fail(Number.isFinite(music.duration) && music.duration >= duration, 'The music track must have a measured duration covering the complete reel. Upload a supported MP3 or WAV again to record its duration, choose a longer track, or omit music.');\nconst [aw, ah] = aspect.split(':').map(Number);\nconst frameWidth = aw / ah * 369;\nconst portrait = aspect === '9:16';\nconst square = aspect === '1:1';\nconst backgroundColor = '#101714';\nconst foreground = '#F7F0DB';\nconst accent = '#CEB88B';\nconst overlays = [];\nconst clips = [];\nconst stickers = [];\nconst round = value => Math.round(value * 1000000) / 1000000;\nconst text = (id, value, start, end, y, size, color = foreground, width = .82) => {\n if (!value) return;\n // The shared renderer wraps between words only. Conservatively shrink a\n // single unusually long unbroken word; ordinary short-copy layouts stay put.\n const longest = Math.max(...value.split(/\\s+/).map(word => word.length));\n if (longest > 18) size = Math.min(size, (frameWidth * width - 12) / longest);\n overlays.push({ id, trackId: 'text', type: 'text', text: value, font: 'Hanken Grotesk', size, color, background: 'none', backgroundPadding: 0, width, x: 50, y, position: 'center', start: round(start), end: round(end), duration: round(end - start), animation: 'fade', animIn: .25, animOut: .2, rotation: 0 });\n};\nconst introEnd = 3.5;\nconst cardStart = duration - 4;\nconst sceneDuration = (cardStart - introEnd) / (photos.length - 1);\n// Fit the FULL measured photo inside a reserved rectangle, then add at most 3%\n// optical zoom. No crop, stretching, retouching, or synthetic pixels are requested.\nconst photoClip = (asset, index, start, length, endCard = false) => {\n const rawFit = Math.min(frameWidth / asset.width, 369 / asset.height);\n const fittedWidth = asset.width * rawFit;\n const fittedHeight = asset.height * rawFit;\n const regionWidth = frameWidth * (endCard ? .64 : .9);\n const regionHeight = 369 * (endCard ? .31 : portrait ? .48 : square ? .48 : .49);\n const scale = Math.min(regionWidth / fittedWidth, regionHeight / fittedHeight) / 1.03;\n const center = endCard ? .34 : .5;\n return {\n id: (endCard ? 'end-card-photo-' : 'photo-') + (index + 1), kind: 'image', trackId: 'video',\n asset: clone(asset), assetId: asset.assetId, versionId: asset.versionId, url: asset.url,\n title: asset.name || 'Photo ' + (index + 1), start: round(start), duration: round(length), trimStart: 0, speed: 1, volume: 0,\n transform: { fit: 'contain', scale, x: 0, y: (center - .5) * 369, rotation: 0, opacity: 1 },\n motion: { type: endCard ? 'none' : 'zoom', intensity: 100, zoomAmount: 1.03, zoomDirection: index % 2 ? 'out' : 'in', zoomAnchor: 'center', easing: 'ease-in-out', loop: false, ['window']: [0, 100] },\n transition: { type: endCard ? 'Cut' : 'Cross dissolve', duration: .3 },\n };\n};\nphotos.forEach((asset, index) => {\n const start = index === 0 ? 0 : introEnd + (index - 1) * sceneDuration;\n const end = index === 0 ? introEnd : index === photos.length - 1 ? cardStart : introEnd + index * sceneDuration;\n clips.push(photoClip(asset, index, start, end - start));\n text('photo-caption-' + (index + 1), captions[index], start + .2, end - .1, 79, portrait ? 11 : 14);\n text('photo-number-' + (index + 1), String(index + 1).padStart(2, '0') + ' / ' + String(photos.length).padStart(2, '0'), start, end - .01, 88, portrait ? 6.5 : 8, accent);\n});\nclips.push(photoClip(photos.at(-1), photos.length - 1, cardStart, 4, true));\n// The opening and closing compositions share an editorial rhythm while the\n// photographs remain full, unaltered, independently editable timeline items.\ntext('opening-title', title, 0, introEnd - .1, 18, portrait ? 16 : 22);\ntext('sequence-title', title, introEnd, cardStart, 16, portrait ? 10 : 14, foreground);\ntext('closing-title', title, cardStart, duration, 13, portrait ? 10 : 14, accent);\ntext('closing-cta', cta, cardStart + .1, duration, 65, portrait ? 17 : 23);\ntext('closing-contact', contact, cardStart + .25, duration, 79, portrait ? 9 : 12);\ntext('demo-disclosure', demoDisclosure, 0, duration, 94, portrait ? 6.5 : 8, '#D4D9D0', .84);\nstickers.push({ id: 'editorial-rule', trackId: 'overlay', shape: 'underline', color: accent, x: 50, y: 25, scale: .2, stretchX: 1.1, stretchY: .24, opacity: .85, rotation: 0, start: 0, end: cardStart });\nstickers.push({ id: 'closing-rule', trackId: 'overlay', shape: 'underline', color: accent, x: 50, y: 55, scale: .2, stretchX: 1.1, stretchY: .24, opacity: .85, rotation: 0, start: cardStart, end: duration });\nif (logo) {\n // Use an ordinary image clip on its own upper track. This avoids the GIF\n // sticker renderer's minimum-height distortion for unusually wide wordmarks.\n const fitted = Math.min(frameWidth / logo.width, 369 / logo.height);\n const scale = Math.min(frameWidth * .2 / (logo.width * fitted), 369 * .06 / (logo.height * fitted));\n clips.push({ id: 'brand-logo', kind: 'image', trackId: 'logo', asset: clone(logo), assetId: logo.assetId, versionId: logo.versionId, url: logo.url, start: cardStart, duration: 4, trimStart: 0, speed: 1, volume: 0, transform: { fit: 'contain', scale, x: 0, y: 369 * .39, rotation: 0, opacity: 1 }, motion: { type: 'none' }, transition: { type: 'Cut', duration: 0 } });\n}\nconst audioItems = music ? [{ id: 'music', trackId: 'audio', asset: clone(music), assetId: music.assetId, versionId: music.versionId, url: music.url, start: 0, duration, trimStart: 0, sourceOffset: 0, speed: 1, volume: 35, fadeIn: .5, fadeOut: .8 }] : [];\nconst provenance = {\n schemaVersion: 1, kind: 'photo-reel-source-record', block: { id: 'stillmade.photo-reel-composer', version: '1.0.0' }, purpose,\n sourcePhotos: photos.map((asset, index) => ({ index, assetId: asset.assetId, versionId: asset.versionId, width: asset.width, height: asset.height })),\n logo: logo ? { assetId: logo.assetId, versionId: logo.versionId } : null,\n music: music ? { assetId: music.assetId, versionId: music.versionId } : null,\n approvedCopy: { title, captions, cta, contact, demoDisclosure },\n rights: { userConfirmed: true, independentlyVerified: false },\n transformations: ['contain fit', 'uniform scale', 'at most three percent optical zoom'],\n generativeMedia: false, providerCalls: 0,\n};\nconst timeline = {\n schemaVersion: 1, activeTimelineId: 'photo-reel', name: title, aspect, aspectRatio: aspect, previewH: 369, backgroundColor,\n tracks: [{ id: 'video', type: 'video', label: 'Original photos' }, ...(logo ? [{ id: 'logo', type: 'video', label: 'Original logo' }] : []), { id: 'text', type: 'text', label: 'Approved copy' }, { id: 'overlay', type: 'overlay', label: 'Graphic details' }, { id: 'audio', type: 'audio', label: 'Music' }],\n trackOrder: ['video', 'logo', 'text', 'overlay', 'audio'], clips, audioItems, textOverlays: overlays, captions: [], stickers, effects: [],\n // The device renderer consumes these legacy aliases; Editor keeps the normal\n // editable lanes above. Both refer to the same content at creation time.\n audio: clone(audioItems), overlays: clone(overlays), targetDuration: duration,\n exportSettings: { aspect, fps: 30, resolution: '1080p', quality: 'high' },\n photoReel: clone(provenance),\n};\nconst lowResolution = photos.filter(asset => asset.width < 1080 || asset.height < 720).map(asset => asset.assetId);\nreturn {\n timeline,\n review: {\n schemaVersion: 1, state: 'needs-human-review', durationSec: duration, aspect, photoCount: photos.length,\n checks: [\n { id: 'original-source-versions', passed: true, note: 'Every photo retains its supplied asset/version and full source rectangle.' },\n { id: 'approved-copy-only', passed: true, note: 'No property features, prices, availability or product claims are generated.' },\n { id: 'bounded-local-composition', passed: true, note: 'No provider call or credit spend occurs in this Block.' },\n { id: 'complete-timing', passed: true, note: 'All source photos and a four-second closing card fit the requested duration.' },\n ],\n warnings: [\n 'Review the full export for photo quality, exact facts, readable copy, licensing and the displayed contact before delivering.',\n ...(!music ? ['Silent reel. Add rights-cleared music in this Block or the Editor if wanted.'] : []),\n ...(lowResolution.length ? ['Small source images may look soft in a 1080p export: ' + lowResolution.join(', ')] : []),\n ...(demoDisclosure ? ['This is labeled demonstration material and is not evidence of a real property or product offer.'] : []),\n ],\n humanApproved: false, exportAuthorized: false, cost: { providerCalls: 0, generationCredits: 0, note: 'Host storage, export access and any separately added services use their own policy.' },\n },\n provenance,\n};\n",
341
- "tests": [
342
- {
343
- "name": "Compose exact original property photos and approved copy",
344
- "input": {
345
- "assets": [
346
- {
347
- "kind": "image",
348
- "assetId": "photo-1",
349
- "versionId": "original-v1",
350
- "url": "https://media.example/photo-1.jpg",
351
- "width": 1600,
352
- "height": 1067,
353
- "name": "Approved photo 1"
354
- },
355
- {
356
- "kind": "image",
357
- "assetId": "photo-2",
358
- "versionId": "original-v1",
359
- "url": "https://media.example/photo-2.jpg",
360
- "width": 1600,
361
- "height": 1067,
362
- "name": "Approved photo 2"
363
- },
364
- {
365
- "kind": "image",
366
- "assetId": "photo-3",
367
- "versionId": "original-v1",
368
- "url": "https://media.example/photo-3.jpg",
369
- "width": 1600,
370
- "height": 1067,
371
- "name": "Approved photo 3"
372
- },
373
- {
374
- "kind": "image",
375
- "assetId": "photo-4",
376
- "versionId": "original-v1",
377
- "url": "https://media.example/photo-4.jpg",
378
- "width": 1600,
379
- "height": 1067,
380
- "name": "Approved photo 4"
381
- },
382
- {
383
- "kind": "image",
384
- "assetId": "photo-5",
385
- "versionId": "original-v1",
386
- "url": "https://media.example/photo-5.jpg",
387
- "width": 1600,
388
- "height": 1067,
389
- "name": "Approved photo 5"
390
- },
391
- {
392
- "kind": "image",
393
- "assetId": "photo-6",
394
- "versionId": "original-v1",
395
- "url": "https://media.example/photo-6.jpg",
396
- "width": 1600,
397
- "height": 1067,
398
- "name": "Approved photo 6"
399
- }
400
- ],
401
- "purpose": "property",
402
- "title": "An interior photo collection",
403
- "captions": "Entry\nLiving area\nDining area\nKitchen\nBedroom\nDetail",
404
- "cta": "Ask for the details",
405
- "contact": "Example contact",
406
- "demoDisclosure": "Sample only · not a live listing",
407
- "duration": 24,
408
- "aspect": "9:16",
409
- "logo": [],
410
- "music": []
411
- },
412
- "expected": {
413
- "timeline": {
414
- "schemaVersion": 1,
415
- "activeTimelineId": "photo-reel",
416
- "name": "An interior photo collection",
417
- "aspect": "9:16",
418
- "aspectRatio": "9:16",
419
- "previewH": 369,
420
- "backgroundColor": "#101714",
421
- "tracks": [
422
- {
423
- "id": "video",
424
- "type": "video",
425
- "label": "Original photos"
426
- },
427
- {
428
- "id": "text",
429
- "type": "text",
430
- "label": "Approved copy"
431
- },
432
- {
433
- "id": "overlay",
434
- "type": "overlay",
435
- "label": "Graphic details"
436
- },
437
- {
438
- "id": "audio",
439
- "type": "audio",
440
- "label": "Music"
441
- }
442
- ],
443
- "trackOrder": [
444
- "video",
445
- "logo",
446
- "text",
447
- "overlay",
448
- "audio"
449
- ],
450
- "clips": [
451
- {
452
- "id": "photo-1",
453
- "kind": "image",
454
- "trackId": "video",
455
- "asset": {
456
- "kind": "image",
457
- "assetId": "photo-1",
458
- "versionId": "original-v1",
459
- "url": "https://media.example/photo-1.jpg",
460
- "width": 1600,
461
- "height": 1067,
462
- "name": "Approved photo 1"
463
- },
464
- "assetId": "photo-1",
465
- "versionId": "original-v1",
466
- "url": "https://media.example/photo-1.jpg",
467
- "title": "Approved photo 1",
468
- "start": 0,
469
- "duration": 3.5,
470
- "trimStart": 0,
471
- "speed": 1,
472
- "volume": 0,
473
- "transform": {
474
- "fit": "contain",
475
- "scale": 0.8737864077669902,
476
- "x": 0,
477
- "y": 0,
478
- "rotation": 0,
479
- "opacity": 1
480
- },
481
- "motion": {
482
- "type": "zoom",
483
- "intensity": 100,
484
- "zoomAmount": 1.03,
485
- "zoomDirection": "in",
486
- "zoomAnchor": "center",
487
- "easing": "ease-in-out",
488
- "loop": false,
489
- "window": [
490
- 0,
491
- 100
492
- ]
493
- },
494
- "transition": {
495
- "type": "Cross dissolve",
496
- "duration": 0.3
497
- }
498
- },
499
- {
500
- "id": "photo-2",
501
- "kind": "image",
502
- "trackId": "video",
503
- "asset": {
504
- "kind": "image",
505
- "assetId": "photo-2",
506
- "versionId": "original-v1",
507
- "url": "https://media.example/photo-2.jpg",
508
- "width": 1600,
509
- "height": 1067,
510
- "name": "Approved photo 2"
511
- },
512
- "assetId": "photo-2",
513
- "versionId": "original-v1",
514
- "url": "https://media.example/photo-2.jpg",
515
- "title": "Approved photo 2",
516
- "start": 3.5,
517
- "duration": 3.3,
518
- "trimStart": 0,
519
- "speed": 1,
520
- "volume": 0,
521
- "transform": {
522
- "fit": "contain",
523
- "scale": 0.8737864077669902,
524
- "x": 0,
525
- "y": 0,
526
- "rotation": 0,
527
- "opacity": 1
528
- },
529
- "motion": {
530
- "type": "zoom",
531
- "intensity": 100,
532
- "zoomAmount": 1.03,
533
- "zoomDirection": "out",
534
- "zoomAnchor": "center",
535
- "easing": "ease-in-out",
536
- "loop": false,
537
- "window": [
538
- 0,
539
- 100
540
- ]
541
- },
542
- "transition": {
543
- "type": "Cross dissolve",
544
- "duration": 0.3
545
- }
546
- },
547
- {
548
- "id": "photo-3",
549
- "kind": "image",
550
- "trackId": "video",
551
- "asset": {
552
- "kind": "image",
553
- "assetId": "photo-3",
554
- "versionId": "original-v1",
555
- "url": "https://media.example/photo-3.jpg",
556
- "width": 1600,
557
- "height": 1067,
558
- "name": "Approved photo 3"
559
- },
560
- "assetId": "photo-3",
561
- "versionId": "original-v1",
562
- "url": "https://media.example/photo-3.jpg",
563
- "title": "Approved photo 3",
564
- "start": 6.8,
565
- "duration": 3.3,
566
- "trimStart": 0,
567
- "speed": 1,
568
- "volume": 0,
569
- "transform": {
570
- "fit": "contain",
571
- "scale": 0.8737864077669902,
572
- "x": 0,
573
- "y": 0,
574
- "rotation": 0,
575
- "opacity": 1
576
- },
577
- "motion": {
578
- "type": "zoom",
579
- "intensity": 100,
580
- "zoomAmount": 1.03,
581
- "zoomDirection": "in",
582
- "zoomAnchor": "center",
583
- "easing": "ease-in-out",
584
- "loop": false,
585
- "window": [
586
- 0,
587
- 100
588
- ]
589
- },
590
- "transition": {
591
- "type": "Cross dissolve",
592
- "duration": 0.3
593
- }
594
- },
595
- {
596
- "id": "photo-4",
597
- "kind": "image",
598
- "trackId": "video",
599
- "asset": {
600
- "kind": "image",
601
- "assetId": "photo-4",
602
- "versionId": "original-v1",
603
- "url": "https://media.example/photo-4.jpg",
604
- "width": 1600,
605
- "height": 1067,
606
- "name": "Approved photo 4"
607
- },
608
- "assetId": "photo-4",
609
- "versionId": "original-v1",
610
- "url": "https://media.example/photo-4.jpg",
611
- "title": "Approved photo 4",
612
- "start": 10.1,
613
- "duration": 3.3,
614
- "trimStart": 0,
615
- "speed": 1,
616
- "volume": 0,
617
- "transform": {
618
- "fit": "contain",
619
- "scale": 0.8737864077669902,
620
- "x": 0,
621
- "y": 0,
622
- "rotation": 0,
623
- "opacity": 1
624
- },
625
- "motion": {
626
- "type": "zoom",
627
- "intensity": 100,
628
- "zoomAmount": 1.03,
629
- "zoomDirection": "out",
630
- "zoomAnchor": "center",
631
- "easing": "ease-in-out",
632
- "loop": false,
633
- "window": [
634
- 0,
635
- 100
636
- ]
637
- },
638
- "transition": {
639
- "type": "Cross dissolve",
640
- "duration": 0.3
641
- }
642
- },
643
- {
644
- "id": "photo-5",
645
- "kind": "image",
646
- "trackId": "video",
647
- "asset": {
648
- "kind": "image",
649
- "assetId": "photo-5",
650
- "versionId": "original-v1",
651
- "url": "https://media.example/photo-5.jpg",
652
- "width": 1600,
653
- "height": 1067,
654
- "name": "Approved photo 5"
655
- },
656
- "assetId": "photo-5",
657
- "versionId": "original-v1",
658
- "url": "https://media.example/photo-5.jpg",
659
- "title": "Approved photo 5",
660
- "start": 13.4,
661
- "duration": 3.3,
662
- "trimStart": 0,
663
- "speed": 1,
664
- "volume": 0,
665
- "transform": {
666
- "fit": "contain",
667
- "scale": 0.8737864077669902,
668
- "x": 0,
669
- "y": 0,
670
- "rotation": 0,
671
- "opacity": 1
672
- },
673
- "motion": {
674
- "type": "zoom",
675
- "intensity": 100,
676
- "zoomAmount": 1.03,
677
- "zoomDirection": "in",
678
- "zoomAnchor": "center",
679
- "easing": "ease-in-out",
680
- "loop": false,
681
- "window": [
682
- 0,
683
- 100
684
- ]
685
- },
686
- "transition": {
687
- "type": "Cross dissolve",
688
- "duration": 0.3
689
- }
690
- },
691
- {
692
- "id": "photo-6",
693
- "kind": "image",
694
- "trackId": "video",
695
- "asset": {
696
- "kind": "image",
697
- "assetId": "photo-6",
698
- "versionId": "original-v1",
699
- "url": "https://media.example/photo-6.jpg",
700
- "width": 1600,
701
- "height": 1067,
702
- "name": "Approved photo 6"
703
- },
704
- "assetId": "photo-6",
705
- "versionId": "original-v1",
706
- "url": "https://media.example/photo-6.jpg",
707
- "title": "Approved photo 6",
708
- "start": 16.7,
709
- "duration": 3.3,
710
- "trimStart": 0,
711
- "speed": 1,
712
- "volume": 0,
713
- "transform": {
714
- "fit": "contain",
715
- "scale": 0.8737864077669902,
716
- "x": 0,
717
- "y": 0,
718
- "rotation": 0,
719
- "opacity": 1
720
- },
721
- "motion": {
722
- "type": "zoom",
723
- "intensity": 100,
724
- "zoomAmount": 1.03,
725
- "zoomDirection": "out",
726
- "zoomAnchor": "center",
727
- "easing": "ease-in-out",
728
- "loop": false,
729
- "window": [
730
- 0,
731
- 100
732
- ]
733
- },
734
- "transition": {
735
- "type": "Cross dissolve",
736
- "duration": 0.3
737
- }
738
- },
739
- {
740
- "id": "end-card-photo-6",
741
- "kind": "image",
742
- "trackId": "video",
743
- "asset": {
744
- "kind": "image",
745
- "assetId": "photo-6",
746
- "versionId": "original-v1",
747
- "url": "https://media.example/photo-6.jpg",
748
- "width": 1600,
749
- "height": 1067,
750
- "name": "Approved photo 6"
751
- },
752
- "assetId": "photo-6",
753
- "versionId": "original-v1",
754
- "url": "https://media.example/photo-6.jpg",
755
- "title": "Approved photo 6",
756
- "start": 20,
757
- "duration": 4,
758
- "trimStart": 0,
759
- "speed": 1,
760
- "volume": 0,
761
- "transform": {
762
- "fit": "contain",
763
- "scale": 0.6213592233009708,
764
- "x": 0,
765
- "y": -59.03999999999999,
766
- "rotation": 0,
767
- "opacity": 1
768
- },
769
- "motion": {
770
- "type": "none",
771
- "intensity": 100,
772
- "zoomAmount": 1.03,
773
- "zoomDirection": "out",
774
- "zoomAnchor": "center",
775
- "easing": "ease-in-out",
776
- "loop": false,
777
- "window": [
778
- 0,
779
- 100
780
- ]
781
- },
782
- "transition": {
783
- "type": "Cut",
784
- "duration": 0.3
785
- }
786
- }
787
- ],
788
- "audioItems": [],
789
- "textOverlays": [
790
- {
791
- "id": "photo-caption-1",
792
- "trackId": "text",
793
- "type": "text",
794
- "text": "Entry",
795
- "font": "Hanken Grotesk",
796
- "size": 11,
797
- "color": "#F7F0DB",
798
- "background": "none",
799
- "backgroundPadding": 0,
800
- "width": 0.82,
801
- "x": 50,
802
- "y": 79,
803
- "position": "center",
804
- "start": 0.2,
805
- "end": 3.4,
806
- "duration": 3.2,
807
- "animation": "fade",
808
- "animIn": 0.25,
809
- "animOut": 0.2,
810
- "rotation": 0
811
- },
812
- {
813
- "id": "photo-number-1",
814
- "trackId": "text",
815
- "type": "text",
816
- "text": "01 / 06",
817
- "font": "Hanken Grotesk",
818
- "size": 6.5,
819
- "color": "#CEB88B",
820
- "background": "none",
821
- "backgroundPadding": 0,
822
- "width": 0.82,
823
- "x": 50,
824
- "y": 88,
825
- "position": "center",
826
- "start": 0,
827
- "end": 3.49,
828
- "duration": 3.49,
829
- "animation": "fade",
830
- "animIn": 0.25,
831
- "animOut": 0.2,
832
- "rotation": 0
833
- },
834
- {
835
- "id": "photo-caption-2",
836
- "trackId": "text",
837
- "type": "text",
838
- "text": "Living area",
839
- "font": "Hanken Grotesk",
840
- "size": 11,
841
- "color": "#F7F0DB",
842
- "background": "none",
843
- "backgroundPadding": 0,
844
- "width": 0.82,
845
- "x": 50,
846
- "y": 79,
847
- "position": "center",
848
- "start": 3.7,
849
- "end": 6.7,
850
- "duration": 3,
851
- "animation": "fade",
852
- "animIn": 0.25,
853
- "animOut": 0.2,
854
- "rotation": 0
855
- },
856
- {
857
- "id": "photo-number-2",
858
- "trackId": "text",
859
- "type": "text",
860
- "text": "02 / 06",
861
- "font": "Hanken Grotesk",
862
- "size": 6.5,
863
- "color": "#CEB88B",
864
- "background": "none",
865
- "backgroundPadding": 0,
866
- "width": 0.82,
867
- "x": 50,
868
- "y": 88,
869
- "position": "center",
870
- "start": 3.5,
871
- "end": 6.79,
872
- "duration": 3.29,
873
- "animation": "fade",
874
- "animIn": 0.25,
875
- "animOut": 0.2,
876
- "rotation": 0
877
- },
878
- {
879
- "id": "photo-caption-3",
880
- "trackId": "text",
881
- "type": "text",
882
- "text": "Dining area",
883
- "font": "Hanken Grotesk",
884
- "size": 11,
885
- "color": "#F7F0DB",
886
- "background": "none",
887
- "backgroundPadding": 0,
888
- "width": 0.82,
889
- "x": 50,
890
- "y": 79,
891
- "position": "center",
892
- "start": 7,
893
- "end": 10,
894
- "duration": 3,
895
- "animation": "fade",
896
- "animIn": 0.25,
897
- "animOut": 0.2,
898
- "rotation": 0
899
- },
900
- {
901
- "id": "photo-number-3",
902
- "trackId": "text",
903
- "type": "text",
904
- "text": "03 / 06",
905
- "font": "Hanken Grotesk",
906
- "size": 6.5,
907
- "color": "#CEB88B",
908
- "background": "none",
909
- "backgroundPadding": 0,
910
- "width": 0.82,
911
- "x": 50,
912
- "y": 88,
913
- "position": "center",
914
- "start": 6.8,
915
- "end": 10.09,
916
- "duration": 3.29,
917
- "animation": "fade",
918
- "animIn": 0.25,
919
- "animOut": 0.2,
920
- "rotation": 0
921
- },
922
- {
923
- "id": "photo-caption-4",
924
- "trackId": "text",
925
- "type": "text",
926
- "text": "Kitchen",
927
- "font": "Hanken Grotesk",
928
- "size": 11,
929
- "color": "#F7F0DB",
930
- "background": "none",
931
- "backgroundPadding": 0,
932
- "width": 0.82,
933
- "x": 50,
934
- "y": 79,
935
- "position": "center",
936
- "start": 10.3,
937
- "end": 13.3,
938
- "duration": 3,
939
- "animation": "fade",
940
- "animIn": 0.25,
941
- "animOut": 0.2,
942
- "rotation": 0
943
- },
944
- {
945
- "id": "photo-number-4",
946
- "trackId": "text",
947
- "type": "text",
948
- "text": "04 / 06",
949
- "font": "Hanken Grotesk",
950
- "size": 6.5,
951
- "color": "#CEB88B",
952
- "background": "none",
953
- "backgroundPadding": 0,
954
- "width": 0.82,
955
- "x": 50,
956
- "y": 88,
957
- "position": "center",
958
- "start": 10.1,
959
- "end": 13.39,
960
- "duration": 3.29,
961
- "animation": "fade",
962
- "animIn": 0.25,
963
- "animOut": 0.2,
964
- "rotation": 0
965
- },
966
- {
967
- "id": "photo-caption-5",
968
- "trackId": "text",
969
- "type": "text",
970
- "text": "Bedroom",
971
- "font": "Hanken Grotesk",
972
- "size": 11,
973
- "color": "#F7F0DB",
974
- "background": "none",
975
- "backgroundPadding": 0,
976
- "width": 0.82,
977
- "x": 50,
978
- "y": 79,
979
- "position": "center",
980
- "start": 13.6,
981
- "end": 16.6,
982
- "duration": 3,
983
- "animation": "fade",
984
- "animIn": 0.25,
985
- "animOut": 0.2,
986
- "rotation": 0
987
- },
988
- {
989
- "id": "photo-number-5",
990
- "trackId": "text",
991
- "type": "text",
992
- "text": "05 / 06",
993
- "font": "Hanken Grotesk",
994
- "size": 6.5,
995
- "color": "#CEB88B",
996
- "background": "none",
997
- "backgroundPadding": 0,
998
- "width": 0.82,
999
- "x": 50,
1000
- "y": 88,
1001
- "position": "center",
1002
- "start": 13.4,
1003
- "end": 16.69,
1004
- "duration": 3.29,
1005
- "animation": "fade",
1006
- "animIn": 0.25,
1007
- "animOut": 0.2,
1008
- "rotation": 0
1009
- },
1010
- {
1011
- "id": "photo-caption-6",
1012
- "trackId": "text",
1013
- "type": "text",
1014
- "text": "Detail",
1015
- "font": "Hanken Grotesk",
1016
- "size": 11,
1017
- "color": "#F7F0DB",
1018
- "background": "none",
1019
- "backgroundPadding": 0,
1020
- "width": 0.82,
1021
- "x": 50,
1022
- "y": 79,
1023
- "position": "center",
1024
- "start": 16.9,
1025
- "end": 19.9,
1026
- "duration": 3,
1027
- "animation": "fade",
1028
- "animIn": 0.25,
1029
- "animOut": 0.2,
1030
- "rotation": 0
1031
- },
1032
- {
1033
- "id": "photo-number-6",
1034
- "trackId": "text",
1035
- "type": "text",
1036
- "text": "06 / 06",
1037
- "font": "Hanken Grotesk",
1038
- "size": 6.5,
1039
- "color": "#CEB88B",
1040
- "background": "none",
1041
- "backgroundPadding": 0,
1042
- "width": 0.82,
1043
- "x": 50,
1044
- "y": 88,
1045
- "position": "center",
1046
- "start": 16.7,
1047
- "end": 19.99,
1048
- "duration": 3.29,
1049
- "animation": "fade",
1050
- "animIn": 0.25,
1051
- "animOut": 0.2,
1052
- "rotation": 0
1053
- },
1054
- {
1055
- "id": "opening-title",
1056
- "trackId": "text",
1057
- "type": "text",
1058
- "text": "An interior photo collection",
1059
- "font": "Hanken Grotesk",
1060
- "size": 16,
1061
- "color": "#F7F0DB",
1062
- "background": "none",
1063
- "backgroundPadding": 0,
1064
- "width": 0.82,
1065
- "x": 50,
1066
- "y": 18,
1067
- "position": "center",
1068
- "start": 0,
1069
- "end": 3.4,
1070
- "duration": 3.4,
1071
- "animation": "fade",
1072
- "animIn": 0.25,
1073
- "animOut": 0.2,
1074
- "rotation": 0
1075
- },
1076
- {
1077
- "id": "sequence-title",
1078
- "trackId": "text",
1079
- "type": "text",
1080
- "text": "An interior photo collection",
1081
- "font": "Hanken Grotesk",
1082
- "size": 10,
1083
- "color": "#F7F0DB",
1084
- "background": "none",
1085
- "backgroundPadding": 0,
1086
- "width": 0.82,
1087
- "x": 50,
1088
- "y": 16,
1089
- "position": "center",
1090
- "start": 3.5,
1091
- "end": 20,
1092
- "duration": 16.5,
1093
- "animation": "fade",
1094
- "animIn": 0.25,
1095
- "animOut": 0.2,
1096
- "rotation": 0
1097
- },
1098
- {
1099
- "id": "closing-title",
1100
- "trackId": "text",
1101
- "type": "text",
1102
- "text": "An interior photo collection",
1103
- "font": "Hanken Grotesk",
1104
- "size": 10,
1105
- "color": "#CEB88B",
1106
- "background": "none",
1107
- "backgroundPadding": 0,
1108
- "width": 0.82,
1109
- "x": 50,
1110
- "y": 13,
1111
- "position": "center",
1112
- "start": 20,
1113
- "end": 24,
1114
- "duration": 4,
1115
- "animation": "fade",
1116
- "animIn": 0.25,
1117
- "animOut": 0.2,
1118
- "rotation": 0
1119
- },
1120
- {
1121
- "id": "closing-cta",
1122
- "trackId": "text",
1123
- "type": "text",
1124
- "text": "Ask for the details",
1125
- "font": "Hanken Grotesk",
1126
- "size": 17,
1127
- "color": "#F7F0DB",
1128
- "background": "none",
1129
- "backgroundPadding": 0,
1130
- "width": 0.82,
1131
- "x": 50,
1132
- "y": 65,
1133
- "position": "center",
1134
- "start": 20.1,
1135
- "end": 24,
1136
- "duration": 3.9,
1137
- "animation": "fade",
1138
- "animIn": 0.25,
1139
- "animOut": 0.2,
1140
- "rotation": 0
1141
- },
1142
- {
1143
- "id": "closing-contact",
1144
- "trackId": "text",
1145
- "type": "text",
1146
- "text": "Example contact",
1147
- "font": "Hanken Grotesk",
1148
- "size": 9,
1149
- "color": "#F7F0DB",
1150
- "background": "none",
1151
- "backgroundPadding": 0,
1152
- "width": 0.82,
1153
- "x": 50,
1154
- "y": 79,
1155
- "position": "center",
1156
- "start": 20.25,
1157
- "end": 24,
1158
- "duration": 3.75,
1159
- "animation": "fade",
1160
- "animIn": 0.25,
1161
- "animOut": 0.2,
1162
- "rotation": 0
1163
- },
1164
- {
1165
- "id": "demo-disclosure",
1166
- "trackId": "text",
1167
- "type": "text",
1168
- "text": "Sample only · not a live listing",
1169
- "font": "Hanken Grotesk",
1170
- "size": 6.5,
1171
- "color": "#D4D9D0",
1172
- "background": "none",
1173
- "backgroundPadding": 0,
1174
- "width": 0.84,
1175
- "x": 50,
1176
- "y": 94,
1177
- "position": "center",
1178
- "start": 0,
1179
- "end": 24,
1180
- "duration": 24,
1181
- "animation": "fade",
1182
- "animIn": 0.25,
1183
- "animOut": 0.2,
1184
- "rotation": 0
1185
- }
1186
- ],
1187
- "captions": [],
1188
- "stickers": [
1189
- {
1190
- "id": "editorial-rule",
1191
- "trackId": "overlay",
1192
- "shape": "underline",
1193
- "color": "#CEB88B",
1194
- "x": 50,
1195
- "y": 25,
1196
- "scale": 0.2,
1197
- "stretchX": 1.1,
1198
- "stretchY": 0.24,
1199
- "opacity": 0.85,
1200
- "rotation": 0,
1201
- "start": 0,
1202
- "end": 20
1203
- },
1204
- {
1205
- "id": "closing-rule",
1206
- "trackId": "overlay",
1207
- "shape": "underline",
1208
- "color": "#CEB88B",
1209
- "x": 50,
1210
- "y": 55,
1211
- "scale": 0.2,
1212
- "stretchX": 1.1,
1213
- "stretchY": 0.24,
1214
- "opacity": 0.85,
1215
- "rotation": 0,
1216
- "start": 20,
1217
- "end": 24
1218
- }
1219
- ],
1220
- "effects": [],
1221
- "audio": [],
1222
- "overlays": [
1223
- {
1224
- "id": "photo-caption-1",
1225
- "trackId": "text",
1226
- "type": "text",
1227
- "text": "Entry",
1228
- "font": "Hanken Grotesk",
1229
- "size": 11,
1230
- "color": "#F7F0DB",
1231
- "background": "none",
1232
- "backgroundPadding": 0,
1233
- "width": 0.82,
1234
- "x": 50,
1235
- "y": 79,
1236
- "position": "center",
1237
- "start": 0.2,
1238
- "end": 3.4,
1239
- "duration": 3.2,
1240
- "animation": "fade",
1241
- "animIn": 0.25,
1242
- "animOut": 0.2,
1243
- "rotation": 0
1244
- },
1245
- {
1246
- "id": "photo-number-1",
1247
- "trackId": "text",
1248
- "type": "text",
1249
- "text": "01 / 06",
1250
- "font": "Hanken Grotesk",
1251
- "size": 6.5,
1252
- "color": "#CEB88B",
1253
- "background": "none",
1254
- "backgroundPadding": 0,
1255
- "width": 0.82,
1256
- "x": 50,
1257
- "y": 88,
1258
- "position": "center",
1259
- "start": 0,
1260
- "end": 3.49,
1261
- "duration": 3.49,
1262
- "animation": "fade",
1263
- "animIn": 0.25,
1264
- "animOut": 0.2,
1265
- "rotation": 0
1266
- },
1267
- {
1268
- "id": "photo-caption-2",
1269
- "trackId": "text",
1270
- "type": "text",
1271
- "text": "Living area",
1272
- "font": "Hanken Grotesk",
1273
- "size": 11,
1274
- "color": "#F7F0DB",
1275
- "background": "none",
1276
- "backgroundPadding": 0,
1277
- "width": 0.82,
1278
- "x": 50,
1279
- "y": 79,
1280
- "position": "center",
1281
- "start": 3.7,
1282
- "end": 6.7,
1283
- "duration": 3,
1284
- "animation": "fade",
1285
- "animIn": 0.25,
1286
- "animOut": 0.2,
1287
- "rotation": 0
1288
- },
1289
- {
1290
- "id": "photo-number-2",
1291
- "trackId": "text",
1292
- "type": "text",
1293
- "text": "02 / 06",
1294
- "font": "Hanken Grotesk",
1295
- "size": 6.5,
1296
- "color": "#CEB88B",
1297
- "background": "none",
1298
- "backgroundPadding": 0,
1299
- "width": 0.82,
1300
- "x": 50,
1301
- "y": 88,
1302
- "position": "center",
1303
- "start": 3.5,
1304
- "end": 6.79,
1305
- "duration": 3.29,
1306
- "animation": "fade",
1307
- "animIn": 0.25,
1308
- "animOut": 0.2,
1309
- "rotation": 0
1310
- },
1311
- {
1312
- "id": "photo-caption-3",
1313
- "trackId": "text",
1314
- "type": "text",
1315
- "text": "Dining area",
1316
- "font": "Hanken Grotesk",
1317
- "size": 11,
1318
- "color": "#F7F0DB",
1319
- "background": "none",
1320
- "backgroundPadding": 0,
1321
- "width": 0.82,
1322
- "x": 50,
1323
- "y": 79,
1324
- "position": "center",
1325
- "start": 7,
1326
- "end": 10,
1327
- "duration": 3,
1328
- "animation": "fade",
1329
- "animIn": 0.25,
1330
- "animOut": 0.2,
1331
- "rotation": 0
1332
- },
1333
- {
1334
- "id": "photo-number-3",
1335
- "trackId": "text",
1336
- "type": "text",
1337
- "text": "03 / 06",
1338
- "font": "Hanken Grotesk",
1339
- "size": 6.5,
1340
- "color": "#CEB88B",
1341
- "background": "none",
1342
- "backgroundPadding": 0,
1343
- "width": 0.82,
1344
- "x": 50,
1345
- "y": 88,
1346
- "position": "center",
1347
- "start": 6.8,
1348
- "end": 10.09,
1349
- "duration": 3.29,
1350
- "animation": "fade",
1351
- "animIn": 0.25,
1352
- "animOut": 0.2,
1353
- "rotation": 0
1354
- },
1355
- {
1356
- "id": "photo-caption-4",
1357
- "trackId": "text",
1358
- "type": "text",
1359
- "text": "Kitchen",
1360
- "font": "Hanken Grotesk",
1361
- "size": 11,
1362
- "color": "#F7F0DB",
1363
- "background": "none",
1364
- "backgroundPadding": 0,
1365
- "width": 0.82,
1366
- "x": 50,
1367
- "y": 79,
1368
- "position": "center",
1369
- "start": 10.3,
1370
- "end": 13.3,
1371
- "duration": 3,
1372
- "animation": "fade",
1373
- "animIn": 0.25,
1374
- "animOut": 0.2,
1375
- "rotation": 0
1376
- },
1377
- {
1378
- "id": "photo-number-4",
1379
- "trackId": "text",
1380
- "type": "text",
1381
- "text": "04 / 06",
1382
- "font": "Hanken Grotesk",
1383
- "size": 6.5,
1384
- "color": "#CEB88B",
1385
- "background": "none",
1386
- "backgroundPadding": 0,
1387
- "width": 0.82,
1388
- "x": 50,
1389
- "y": 88,
1390
- "position": "center",
1391
- "start": 10.1,
1392
- "end": 13.39,
1393
- "duration": 3.29,
1394
- "animation": "fade",
1395
- "animIn": 0.25,
1396
- "animOut": 0.2,
1397
- "rotation": 0
1398
- },
1399
- {
1400
- "id": "photo-caption-5",
1401
- "trackId": "text",
1402
- "type": "text",
1403
- "text": "Bedroom",
1404
- "font": "Hanken Grotesk",
1405
- "size": 11,
1406
- "color": "#F7F0DB",
1407
- "background": "none",
1408
- "backgroundPadding": 0,
1409
- "width": 0.82,
1410
- "x": 50,
1411
- "y": 79,
1412
- "position": "center",
1413
- "start": 13.6,
1414
- "end": 16.6,
1415
- "duration": 3,
1416
- "animation": "fade",
1417
- "animIn": 0.25,
1418
- "animOut": 0.2,
1419
- "rotation": 0
1420
- },
1421
- {
1422
- "id": "photo-number-5",
1423
- "trackId": "text",
1424
- "type": "text",
1425
- "text": "05 / 06",
1426
- "font": "Hanken Grotesk",
1427
- "size": 6.5,
1428
- "color": "#CEB88B",
1429
- "background": "none",
1430
- "backgroundPadding": 0,
1431
- "width": 0.82,
1432
- "x": 50,
1433
- "y": 88,
1434
- "position": "center",
1435
- "start": 13.4,
1436
- "end": 16.69,
1437
- "duration": 3.29,
1438
- "animation": "fade",
1439
- "animIn": 0.25,
1440
- "animOut": 0.2,
1441
- "rotation": 0
1442
- },
1443
- {
1444
- "id": "photo-caption-6",
1445
- "trackId": "text",
1446
- "type": "text",
1447
- "text": "Detail",
1448
- "font": "Hanken Grotesk",
1449
- "size": 11,
1450
- "color": "#F7F0DB",
1451
- "background": "none",
1452
- "backgroundPadding": 0,
1453
- "width": 0.82,
1454
- "x": 50,
1455
- "y": 79,
1456
- "position": "center",
1457
- "start": 16.9,
1458
- "end": 19.9,
1459
- "duration": 3,
1460
- "animation": "fade",
1461
- "animIn": 0.25,
1462
- "animOut": 0.2,
1463
- "rotation": 0
1464
- },
1465
- {
1466
- "id": "photo-number-6",
1467
- "trackId": "text",
1468
- "type": "text",
1469
- "text": "06 / 06",
1470
- "font": "Hanken Grotesk",
1471
- "size": 6.5,
1472
- "color": "#CEB88B",
1473
- "background": "none",
1474
- "backgroundPadding": 0,
1475
- "width": 0.82,
1476
- "x": 50,
1477
- "y": 88,
1478
- "position": "center",
1479
- "start": 16.7,
1480
- "end": 19.99,
1481
- "duration": 3.29,
1482
- "animation": "fade",
1483
- "animIn": 0.25,
1484
- "animOut": 0.2,
1485
- "rotation": 0
1486
- },
1487
- {
1488
- "id": "opening-title",
1489
- "trackId": "text",
1490
- "type": "text",
1491
- "text": "An interior photo collection",
1492
- "font": "Hanken Grotesk",
1493
- "size": 16,
1494
- "color": "#F7F0DB",
1495
- "background": "none",
1496
- "backgroundPadding": 0,
1497
- "width": 0.82,
1498
- "x": 50,
1499
- "y": 18,
1500
- "position": "center",
1501
- "start": 0,
1502
- "end": 3.4,
1503
- "duration": 3.4,
1504
- "animation": "fade",
1505
- "animIn": 0.25,
1506
- "animOut": 0.2,
1507
- "rotation": 0
1508
- },
1509
- {
1510
- "id": "sequence-title",
1511
- "trackId": "text",
1512
- "type": "text",
1513
- "text": "An interior photo collection",
1514
- "font": "Hanken Grotesk",
1515
- "size": 10,
1516
- "color": "#F7F0DB",
1517
- "background": "none",
1518
- "backgroundPadding": 0,
1519
- "width": 0.82,
1520
- "x": 50,
1521
- "y": 16,
1522
- "position": "center",
1523
- "start": 3.5,
1524
- "end": 20,
1525
- "duration": 16.5,
1526
- "animation": "fade",
1527
- "animIn": 0.25,
1528
- "animOut": 0.2,
1529
- "rotation": 0
1530
- },
1531
- {
1532
- "id": "closing-title",
1533
- "trackId": "text",
1534
- "type": "text",
1535
- "text": "An interior photo collection",
1536
- "font": "Hanken Grotesk",
1537
- "size": 10,
1538
- "color": "#CEB88B",
1539
- "background": "none",
1540
- "backgroundPadding": 0,
1541
- "width": 0.82,
1542
- "x": 50,
1543
- "y": 13,
1544
- "position": "center",
1545
- "start": 20,
1546
- "end": 24,
1547
- "duration": 4,
1548
- "animation": "fade",
1549
- "animIn": 0.25,
1550
- "animOut": 0.2,
1551
- "rotation": 0
1552
- },
1553
- {
1554
- "id": "closing-cta",
1555
- "trackId": "text",
1556
- "type": "text",
1557
- "text": "Ask for the details",
1558
- "font": "Hanken Grotesk",
1559
- "size": 17,
1560
- "color": "#F7F0DB",
1561
- "background": "none",
1562
- "backgroundPadding": 0,
1563
- "width": 0.82,
1564
- "x": 50,
1565
- "y": 65,
1566
- "position": "center",
1567
- "start": 20.1,
1568
- "end": 24,
1569
- "duration": 3.9,
1570
- "animation": "fade",
1571
- "animIn": 0.25,
1572
- "animOut": 0.2,
1573
- "rotation": 0
1574
- },
1575
- {
1576
- "id": "closing-contact",
1577
- "trackId": "text",
1578
- "type": "text",
1579
- "text": "Example contact",
1580
- "font": "Hanken Grotesk",
1581
- "size": 9,
1582
- "color": "#F7F0DB",
1583
- "background": "none",
1584
- "backgroundPadding": 0,
1585
- "width": 0.82,
1586
- "x": 50,
1587
- "y": 79,
1588
- "position": "center",
1589
- "start": 20.25,
1590
- "end": 24,
1591
- "duration": 3.75,
1592
- "animation": "fade",
1593
- "animIn": 0.25,
1594
- "animOut": 0.2,
1595
- "rotation": 0
1596
- },
1597
- {
1598
- "id": "demo-disclosure",
1599
- "trackId": "text",
1600
- "type": "text",
1601
- "text": "Sample only · not a live listing",
1602
- "font": "Hanken Grotesk",
1603
- "size": 6.5,
1604
- "color": "#D4D9D0",
1605
- "background": "none",
1606
- "backgroundPadding": 0,
1607
- "width": 0.84,
1608
- "x": 50,
1609
- "y": 94,
1610
- "position": "center",
1611
- "start": 0,
1612
- "end": 24,
1613
- "duration": 24,
1614
- "animation": "fade",
1615
- "animIn": 0.25,
1616
- "animOut": 0.2,
1617
- "rotation": 0
1618
- }
1619
- ],
1620
- "targetDuration": 24,
1621
- "exportSettings": {
1622
- "aspect": "9:16",
1623
- "fps": 30,
1624
- "resolution": "1080p",
1625
- "quality": "high"
1626
- },
1627
- "photoReel": {
1628
- "schemaVersion": 1,
1629
- "kind": "photo-reel-source-record",
1630
- "block": {
1631
- "id": "stillmade.photo-reel-composer",
1632
- "version": "1.0.0"
1633
- },
1634
- "purpose": "property",
1635
- "sourcePhotos": [
1636
- {
1637
- "index": 0,
1638
- "assetId": "photo-1",
1639
- "versionId": "original-v1",
1640
- "width": 1600,
1641
- "height": 1067
1642
- },
1643
- {
1644
- "index": 1,
1645
- "assetId": "photo-2",
1646
- "versionId": "original-v1",
1647
- "width": 1600,
1648
- "height": 1067
1649
- },
1650
- {
1651
- "index": 2,
1652
- "assetId": "photo-3",
1653
- "versionId": "original-v1",
1654
- "width": 1600,
1655
- "height": 1067
1656
- },
1657
- {
1658
- "index": 3,
1659
- "assetId": "photo-4",
1660
- "versionId": "original-v1",
1661
- "width": 1600,
1662
- "height": 1067
1663
- },
1664
- {
1665
- "index": 4,
1666
- "assetId": "photo-5",
1667
- "versionId": "original-v1",
1668
- "width": 1600,
1669
- "height": 1067
1670
- },
1671
- {
1672
- "index": 5,
1673
- "assetId": "photo-6",
1674
- "versionId": "original-v1",
1675
- "width": 1600,
1676
- "height": 1067
1677
- }
1678
- ],
1679
- "logo": null,
1680
- "music": null,
1681
- "approvedCopy": {
1682
- "title": "An interior photo collection",
1683
- "captions": [
1684
- "Entry",
1685
- "Living area",
1686
- "Dining area",
1687
- "Kitchen",
1688
- "Bedroom",
1689
- "Detail"
1690
- ],
1691
- "cta": "Ask for the details",
1692
- "contact": "Example contact",
1693
- "demoDisclosure": "Sample only · not a live listing"
1694
- },
1695
- "rights": {
1696
- "userConfirmed": true,
1697
- "independentlyVerified": false
1698
- },
1699
- "transformations": [
1700
- "contain fit",
1701
- "uniform scale",
1702
- "at most three percent optical zoom"
1703
- ],
1704
- "generativeMedia": false,
1705
- "providerCalls": 0
1706
- }
1707
- },
1708
- "review": {
1709
- "schemaVersion": 1,
1710
- "state": "needs-human-review",
1711
- "durationSec": 24,
1712
- "aspect": "9:16",
1713
- "photoCount": 6,
1714
- "checks": [
1715
- {
1716
- "id": "original-source-versions",
1717
- "passed": true,
1718
- "note": "Every photo retains its supplied asset/version and full source rectangle."
1719
- },
1720
- {
1721
- "id": "approved-copy-only",
1722
- "passed": true,
1723
- "note": "No property features, prices, availability or product claims are generated."
1724
- },
1725
- {
1726
- "id": "bounded-local-composition",
1727
- "passed": true,
1728
- "note": "No provider call or credit spend occurs in this Block."
1729
- },
1730
- {
1731
- "id": "complete-timing",
1732
- "passed": true,
1733
- "note": "All source photos and a four-second closing card fit the requested duration."
1734
- }
1735
- ],
1736
- "warnings": [
1737
- "Review the full export for photo quality, exact facts, readable copy, licensing and the displayed contact before delivering.",
1738
- "Silent reel. Add rights-cleared music in this Block or the Editor if wanted.",
1739
- "This is labeled demonstration material and is not evidence of a real property or product offer."
1740
- ],
1741
- "humanApproved": false,
1742
- "exportAuthorized": false,
1743
- "cost": {
1744
- "providerCalls": 0,
1745
- "generationCredits": 0,
1746
- "note": "Host storage, export access and any separately added services use their own policy."
1747
- }
1748
- },
1749
- "provenance": {
1750
- "schemaVersion": 1,
1751
- "kind": "photo-reel-source-record",
1752
- "block": {
1753
- "id": "stillmade.photo-reel-composer",
1754
- "version": "1.0.0"
1755
- },
1756
- "purpose": "property",
1757
- "sourcePhotos": [
1758
- {
1759
- "index": 0,
1760
- "assetId": "photo-1",
1761
- "versionId": "original-v1",
1762
- "width": 1600,
1763
- "height": 1067
1764
- },
1765
- {
1766
- "index": 1,
1767
- "assetId": "photo-2",
1768
- "versionId": "original-v1",
1769
- "width": 1600,
1770
- "height": 1067
1771
- },
1772
- {
1773
- "index": 2,
1774
- "assetId": "photo-3",
1775
- "versionId": "original-v1",
1776
- "width": 1600,
1777
- "height": 1067
1778
- },
1779
- {
1780
- "index": 3,
1781
- "assetId": "photo-4",
1782
- "versionId": "original-v1",
1783
- "width": 1600,
1784
- "height": 1067
1785
- },
1786
- {
1787
- "index": 4,
1788
- "assetId": "photo-5",
1789
- "versionId": "original-v1",
1790
- "width": 1600,
1791
- "height": 1067
1792
- },
1793
- {
1794
- "index": 5,
1795
- "assetId": "photo-6",
1796
- "versionId": "original-v1",
1797
- "width": 1600,
1798
- "height": 1067
1799
- }
1800
- ],
1801
- "logo": null,
1802
- "music": null,
1803
- "approvedCopy": {
1804
- "title": "An interior photo collection",
1805
- "captions": [
1806
- "Entry",
1807
- "Living area",
1808
- "Dining area",
1809
- "Kitchen",
1810
- "Bedroom",
1811
- "Detail"
1812
- ],
1813
- "cta": "Ask for the details",
1814
- "contact": "Example contact",
1815
- "demoDisclosure": "Sample only · not a live listing"
1816
- },
1817
- "rights": {
1818
- "userConfirmed": true,
1819
- "independentlyVerified": false
1820
- },
1821
- "transformations": [
1822
- "contain fit",
1823
- "uniform scale",
1824
- "at most three percent optical zoom"
1825
- ],
1826
- "generativeMedia": false,
1827
- "providerCalls": 0
1828
- }
1829
- }
1830
- },
1831
- {
1832
- "name": "Compose a product reel without inventing product claims",
1833
- "input": {
1834
- "assets": [
1835
- {
1836
- "kind": "image",
1837
- "assetId": "photo-1",
1838
- "versionId": "original-v1",
1839
- "url": "https://media.example/photo-1.jpg",
1840
- "width": 1600,
1841
- "height": 1067,
1842
- "name": "Approved photo 1"
1843
- },
1844
- {
1845
- "kind": "image",
1846
- "assetId": "photo-2",
1847
- "versionId": "original-v1",
1848
- "url": "https://media.example/photo-2.jpg",
1849
- "width": 1600,
1850
- "height": 1067,
1851
- "name": "Approved photo 2"
1852
- },
1853
- {
1854
- "kind": "image",
1855
- "assetId": "photo-3",
1856
- "versionId": "original-v1",
1857
- "url": "https://media.example/photo-3.jpg",
1858
- "width": 1600,
1859
- "height": 1067,
1860
- "name": "Approved photo 3"
1861
- },
1862
- {
1863
- "kind": "image",
1864
- "assetId": "photo-4",
1865
- "versionId": "original-v1",
1866
- "url": "https://media.example/photo-4.jpg",
1867
- "width": 1600,
1868
- "height": 1067,
1869
- "name": "Approved photo 4"
1870
- }
1871
- ],
1872
- "purpose": "product",
1873
- "title": "An object in four views",
1874
- "captions": "Front\nSide\nTexture\nDetail",
1875
- "cta": "Explore the collection",
1876
- "contact": "Example contact",
1877
- "demoDisclosure": "Sample only · not a product offer",
1878
- "duration": 24,
1879
- "aspect": "9:16",
1880
- "logo": [],
1881
- "music": []
1882
- },
1883
- "expected": {
1884
- "timeline": {
1885
- "schemaVersion": 1,
1886
- "activeTimelineId": "photo-reel",
1887
- "name": "An object in four views",
1888
- "aspect": "9:16",
1889
- "aspectRatio": "9:16",
1890
- "previewH": 369,
1891
- "backgroundColor": "#101714",
1892
- "tracks": [
1893
- {
1894
- "id": "video",
1895
- "type": "video",
1896
- "label": "Original photos"
1897
- },
1898
- {
1899
- "id": "text",
1900
- "type": "text",
1901
- "label": "Approved copy"
1902
- },
1903
- {
1904
- "id": "overlay",
1905
- "type": "overlay",
1906
- "label": "Graphic details"
1907
- },
1908
- {
1909
- "id": "audio",
1910
- "type": "audio",
1911
- "label": "Music"
1912
- }
1913
- ],
1914
- "trackOrder": [
1915
- "video",
1916
- "logo",
1917
- "text",
1918
- "overlay",
1919
- "audio"
1920
- ],
1921
- "clips": [
1922
- {
1923
- "id": "photo-1",
1924
- "kind": "image",
1925
- "trackId": "video",
1926
- "asset": {
1927
- "kind": "image",
1928
- "assetId": "photo-1",
1929
- "versionId": "original-v1",
1930
- "url": "https://media.example/photo-1.jpg",
1931
- "width": 1600,
1932
- "height": 1067,
1933
- "name": "Approved photo 1"
1934
- },
1935
- "assetId": "photo-1",
1936
- "versionId": "original-v1",
1937
- "url": "https://media.example/photo-1.jpg",
1938
- "title": "Approved photo 1",
1939
- "start": 0,
1940
- "duration": 3.5,
1941
- "trimStart": 0,
1942
- "speed": 1,
1943
- "volume": 0,
1944
- "transform": {
1945
- "fit": "contain",
1946
- "scale": 0.8737864077669902,
1947
- "x": 0,
1948
- "y": 0,
1949
- "rotation": 0,
1950
- "opacity": 1
1951
- },
1952
- "motion": {
1953
- "type": "zoom",
1954
- "intensity": 100,
1955
- "zoomAmount": 1.03,
1956
- "zoomDirection": "in",
1957
- "zoomAnchor": "center",
1958
- "easing": "ease-in-out",
1959
- "loop": false,
1960
- "window": [
1961
- 0,
1962
- 100
1963
- ]
1964
- },
1965
- "transition": {
1966
- "type": "Cross dissolve",
1967
- "duration": 0.3
1968
- }
1969
- },
1970
- {
1971
- "id": "photo-2",
1972
- "kind": "image",
1973
- "trackId": "video",
1974
- "asset": {
1975
- "kind": "image",
1976
- "assetId": "photo-2",
1977
- "versionId": "original-v1",
1978
- "url": "https://media.example/photo-2.jpg",
1979
- "width": 1600,
1980
- "height": 1067,
1981
- "name": "Approved photo 2"
1982
- },
1983
- "assetId": "photo-2",
1984
- "versionId": "original-v1",
1985
- "url": "https://media.example/photo-2.jpg",
1986
- "title": "Approved photo 2",
1987
- "start": 3.5,
1988
- "duration": 5.5,
1989
- "trimStart": 0,
1990
- "speed": 1,
1991
- "volume": 0,
1992
- "transform": {
1993
- "fit": "contain",
1994
- "scale": 0.8737864077669902,
1995
- "x": 0,
1996
- "y": 0,
1997
- "rotation": 0,
1998
- "opacity": 1
1999
- },
2000
- "motion": {
2001
- "type": "zoom",
2002
- "intensity": 100,
2003
- "zoomAmount": 1.03,
2004
- "zoomDirection": "out",
2005
- "zoomAnchor": "center",
2006
- "easing": "ease-in-out",
2007
- "loop": false,
2008
- "window": [
2009
- 0,
2010
- 100
2011
- ]
2012
- },
2013
- "transition": {
2014
- "type": "Cross dissolve",
2015
- "duration": 0.3
2016
- }
2017
- },
2018
- {
2019
- "id": "photo-3",
2020
- "kind": "image",
2021
- "trackId": "video",
2022
- "asset": {
2023
- "kind": "image",
2024
- "assetId": "photo-3",
2025
- "versionId": "original-v1",
2026
- "url": "https://media.example/photo-3.jpg",
2027
- "width": 1600,
2028
- "height": 1067,
2029
- "name": "Approved photo 3"
2030
- },
2031
- "assetId": "photo-3",
2032
- "versionId": "original-v1",
2033
- "url": "https://media.example/photo-3.jpg",
2034
- "title": "Approved photo 3",
2035
- "start": 9,
2036
- "duration": 5.5,
2037
- "trimStart": 0,
2038
- "speed": 1,
2039
- "volume": 0,
2040
- "transform": {
2041
- "fit": "contain",
2042
- "scale": 0.8737864077669902,
2043
- "x": 0,
2044
- "y": 0,
2045
- "rotation": 0,
2046
- "opacity": 1
2047
- },
2048
- "motion": {
2049
- "type": "zoom",
2050
- "intensity": 100,
2051
- "zoomAmount": 1.03,
2052
- "zoomDirection": "in",
2053
- "zoomAnchor": "center",
2054
- "easing": "ease-in-out",
2055
- "loop": false,
2056
- "window": [
2057
- 0,
2058
- 100
2059
- ]
2060
- },
2061
- "transition": {
2062
- "type": "Cross dissolve",
2063
- "duration": 0.3
2064
- }
2065
- },
2066
- {
2067
- "id": "photo-4",
2068
- "kind": "image",
2069
- "trackId": "video",
2070
- "asset": {
2071
- "kind": "image",
2072
- "assetId": "photo-4",
2073
- "versionId": "original-v1",
2074
- "url": "https://media.example/photo-4.jpg",
2075
- "width": 1600,
2076
- "height": 1067,
2077
- "name": "Approved photo 4"
2078
- },
2079
- "assetId": "photo-4",
2080
- "versionId": "original-v1",
2081
- "url": "https://media.example/photo-4.jpg",
2082
- "title": "Approved photo 4",
2083
- "start": 14.5,
2084
- "duration": 5.5,
2085
- "trimStart": 0,
2086
- "speed": 1,
2087
- "volume": 0,
2088
- "transform": {
2089
- "fit": "contain",
2090
- "scale": 0.8737864077669902,
2091
- "x": 0,
2092
- "y": 0,
2093
- "rotation": 0,
2094
- "opacity": 1
2095
- },
2096
- "motion": {
2097
- "type": "zoom",
2098
- "intensity": 100,
2099
- "zoomAmount": 1.03,
2100
- "zoomDirection": "out",
2101
- "zoomAnchor": "center",
2102
- "easing": "ease-in-out",
2103
- "loop": false,
2104
- "window": [
2105
- 0,
2106
- 100
2107
- ]
2108
- },
2109
- "transition": {
2110
- "type": "Cross dissolve",
2111
- "duration": 0.3
2112
- }
2113
- },
2114
- {
2115
- "id": "end-card-photo-4",
2116
- "kind": "image",
2117
- "trackId": "video",
2118
- "asset": {
2119
- "kind": "image",
2120
- "assetId": "photo-4",
2121
- "versionId": "original-v1",
2122
- "url": "https://media.example/photo-4.jpg",
2123
- "width": 1600,
2124
- "height": 1067,
2125
- "name": "Approved photo 4"
2126
- },
2127
- "assetId": "photo-4",
2128
- "versionId": "original-v1",
2129
- "url": "https://media.example/photo-4.jpg",
2130
- "title": "Approved photo 4",
2131
- "start": 20,
2132
- "duration": 4,
2133
- "trimStart": 0,
2134
- "speed": 1,
2135
- "volume": 0,
2136
- "transform": {
2137
- "fit": "contain",
2138
- "scale": 0.6213592233009708,
2139
- "x": 0,
2140
- "y": -59.03999999999999,
2141
- "rotation": 0,
2142
- "opacity": 1
2143
- },
2144
- "motion": {
2145
- "type": "none",
2146
- "intensity": 100,
2147
- "zoomAmount": 1.03,
2148
- "zoomDirection": "out",
2149
- "zoomAnchor": "center",
2150
- "easing": "ease-in-out",
2151
- "loop": false,
2152
- "window": [
2153
- 0,
2154
- 100
2155
- ]
2156
- },
2157
- "transition": {
2158
- "type": "Cut",
2159
- "duration": 0.3
2160
- }
2161
- }
2162
- ],
2163
- "audioItems": [],
2164
- "textOverlays": [
2165
- {
2166
- "id": "photo-caption-1",
2167
- "trackId": "text",
2168
- "type": "text",
2169
- "text": "Front",
2170
- "font": "Hanken Grotesk",
2171
- "size": 11,
2172
- "color": "#F7F0DB",
2173
- "background": "none",
2174
- "backgroundPadding": 0,
2175
- "width": 0.82,
2176
- "x": 50,
2177
- "y": 79,
2178
- "position": "center",
2179
- "start": 0.2,
2180
- "end": 3.4,
2181
- "duration": 3.2,
2182
- "animation": "fade",
2183
- "animIn": 0.25,
2184
- "animOut": 0.2,
2185
- "rotation": 0
2186
- },
2187
- {
2188
- "id": "photo-number-1",
2189
- "trackId": "text",
2190
- "type": "text",
2191
- "text": "01 / 04",
2192
- "font": "Hanken Grotesk",
2193
- "size": 6.5,
2194
- "color": "#CEB88B",
2195
- "background": "none",
2196
- "backgroundPadding": 0,
2197
- "width": 0.82,
2198
- "x": 50,
2199
- "y": 88,
2200
- "position": "center",
2201
- "start": 0,
2202
- "end": 3.49,
2203
- "duration": 3.49,
2204
- "animation": "fade",
2205
- "animIn": 0.25,
2206
- "animOut": 0.2,
2207
- "rotation": 0
2208
- },
2209
- {
2210
- "id": "photo-caption-2",
2211
- "trackId": "text",
2212
- "type": "text",
2213
- "text": "Side",
2214
- "font": "Hanken Grotesk",
2215
- "size": 11,
2216
- "color": "#F7F0DB",
2217
- "background": "none",
2218
- "backgroundPadding": 0,
2219
- "width": 0.82,
2220
- "x": 50,
2221
- "y": 79,
2222
- "position": "center",
2223
- "start": 3.7,
2224
- "end": 8.9,
2225
- "duration": 5.2,
2226
- "animation": "fade",
2227
- "animIn": 0.25,
2228
- "animOut": 0.2,
2229
- "rotation": 0
2230
- },
2231
- {
2232
- "id": "photo-number-2",
2233
- "trackId": "text",
2234
- "type": "text",
2235
- "text": "02 / 04",
2236
- "font": "Hanken Grotesk",
2237
- "size": 6.5,
2238
- "color": "#CEB88B",
2239
- "background": "none",
2240
- "backgroundPadding": 0,
2241
- "width": 0.82,
2242
- "x": 50,
2243
- "y": 88,
2244
- "position": "center",
2245
- "start": 3.5,
2246
- "end": 8.99,
2247
- "duration": 5.49,
2248
- "animation": "fade",
2249
- "animIn": 0.25,
2250
- "animOut": 0.2,
2251
- "rotation": 0
2252
- },
2253
- {
2254
- "id": "photo-caption-3",
2255
- "trackId": "text",
2256
- "type": "text",
2257
- "text": "Texture",
2258
- "font": "Hanken Grotesk",
2259
- "size": 11,
2260
- "color": "#F7F0DB",
2261
- "background": "none",
2262
- "backgroundPadding": 0,
2263
- "width": 0.82,
2264
- "x": 50,
2265
- "y": 79,
2266
- "position": "center",
2267
- "start": 9.2,
2268
- "end": 14.4,
2269
- "duration": 5.2,
2270
- "animation": "fade",
2271
- "animIn": 0.25,
2272
- "animOut": 0.2,
2273
- "rotation": 0
2274
- },
2275
- {
2276
- "id": "photo-number-3",
2277
- "trackId": "text",
2278
- "type": "text",
2279
- "text": "03 / 04",
2280
- "font": "Hanken Grotesk",
2281
- "size": 6.5,
2282
- "color": "#CEB88B",
2283
- "background": "none",
2284
- "backgroundPadding": 0,
2285
- "width": 0.82,
2286
- "x": 50,
2287
- "y": 88,
2288
- "position": "center",
2289
- "start": 9,
2290
- "end": 14.49,
2291
- "duration": 5.49,
2292
- "animation": "fade",
2293
- "animIn": 0.25,
2294
- "animOut": 0.2,
2295
- "rotation": 0
2296
- },
2297
- {
2298
- "id": "photo-caption-4",
2299
- "trackId": "text",
2300
- "type": "text",
2301
- "text": "Detail",
2302
- "font": "Hanken Grotesk",
2303
- "size": 11,
2304
- "color": "#F7F0DB",
2305
- "background": "none",
2306
- "backgroundPadding": 0,
2307
- "width": 0.82,
2308
- "x": 50,
2309
- "y": 79,
2310
- "position": "center",
2311
- "start": 14.7,
2312
- "end": 19.9,
2313
- "duration": 5.2,
2314
- "animation": "fade",
2315
- "animIn": 0.25,
2316
- "animOut": 0.2,
2317
- "rotation": 0
2318
- },
2319
- {
2320
- "id": "photo-number-4",
2321
- "trackId": "text",
2322
- "type": "text",
2323
- "text": "04 / 04",
2324
- "font": "Hanken Grotesk",
2325
- "size": 6.5,
2326
- "color": "#CEB88B",
2327
- "background": "none",
2328
- "backgroundPadding": 0,
2329
- "width": 0.82,
2330
- "x": 50,
2331
- "y": 88,
2332
- "position": "center",
2333
- "start": 14.5,
2334
- "end": 19.99,
2335
- "duration": 5.49,
2336
- "animation": "fade",
2337
- "animIn": 0.25,
2338
- "animOut": 0.2,
2339
- "rotation": 0
2340
- },
2341
- {
2342
- "id": "opening-title",
2343
- "trackId": "text",
2344
- "type": "text",
2345
- "text": "An object in four views",
2346
- "font": "Hanken Grotesk",
2347
- "size": 16,
2348
- "color": "#F7F0DB",
2349
- "background": "none",
2350
- "backgroundPadding": 0,
2351
- "width": 0.82,
2352
- "x": 50,
2353
- "y": 18,
2354
- "position": "center",
2355
- "start": 0,
2356
- "end": 3.4,
2357
- "duration": 3.4,
2358
- "animation": "fade",
2359
- "animIn": 0.25,
2360
- "animOut": 0.2,
2361
- "rotation": 0
2362
- },
2363
- {
2364
- "id": "sequence-title",
2365
- "trackId": "text",
2366
- "type": "text",
2367
- "text": "An object in four views",
2368
- "font": "Hanken Grotesk",
2369
- "size": 10,
2370
- "color": "#F7F0DB",
2371
- "background": "none",
2372
- "backgroundPadding": 0,
2373
- "width": 0.82,
2374
- "x": 50,
2375
- "y": 16,
2376
- "position": "center",
2377
- "start": 3.5,
2378
- "end": 20,
2379
- "duration": 16.5,
2380
- "animation": "fade",
2381
- "animIn": 0.25,
2382
- "animOut": 0.2,
2383
- "rotation": 0
2384
- },
2385
- {
2386
- "id": "closing-title",
2387
- "trackId": "text",
2388
- "type": "text",
2389
- "text": "An object in four views",
2390
- "font": "Hanken Grotesk",
2391
- "size": 10,
2392
- "color": "#CEB88B",
2393
- "background": "none",
2394
- "backgroundPadding": 0,
2395
- "width": 0.82,
2396
- "x": 50,
2397
- "y": 13,
2398
- "position": "center",
2399
- "start": 20,
2400
- "end": 24,
2401
- "duration": 4,
2402
- "animation": "fade",
2403
- "animIn": 0.25,
2404
- "animOut": 0.2,
2405
- "rotation": 0
2406
- },
2407
- {
2408
- "id": "closing-cta",
2409
- "trackId": "text",
2410
- "type": "text",
2411
- "text": "Explore the collection",
2412
- "font": "Hanken Grotesk",
2413
- "size": 17,
2414
- "color": "#F7F0DB",
2415
- "background": "none",
2416
- "backgroundPadding": 0,
2417
- "width": 0.82,
2418
- "x": 50,
2419
- "y": 65,
2420
- "position": "center",
2421
- "start": 20.1,
2422
- "end": 24,
2423
- "duration": 3.9,
2424
- "animation": "fade",
2425
- "animIn": 0.25,
2426
- "animOut": 0.2,
2427
- "rotation": 0
2428
- },
2429
- {
2430
- "id": "closing-contact",
2431
- "trackId": "text",
2432
- "type": "text",
2433
- "text": "Example contact",
2434
- "font": "Hanken Grotesk",
2435
- "size": 9,
2436
- "color": "#F7F0DB",
2437
- "background": "none",
2438
- "backgroundPadding": 0,
2439
- "width": 0.82,
2440
- "x": 50,
2441
- "y": 79,
2442
- "position": "center",
2443
- "start": 20.25,
2444
- "end": 24,
2445
- "duration": 3.75,
2446
- "animation": "fade",
2447
- "animIn": 0.25,
2448
- "animOut": 0.2,
2449
- "rotation": 0
2450
- },
2451
- {
2452
- "id": "demo-disclosure",
2453
- "trackId": "text",
2454
- "type": "text",
2455
- "text": "Sample only · not a product offer",
2456
- "font": "Hanken Grotesk",
2457
- "size": 6.5,
2458
- "color": "#D4D9D0",
2459
- "background": "none",
2460
- "backgroundPadding": 0,
2461
- "width": 0.84,
2462
- "x": 50,
2463
- "y": 94,
2464
- "position": "center",
2465
- "start": 0,
2466
- "end": 24,
2467
- "duration": 24,
2468
- "animation": "fade",
2469
- "animIn": 0.25,
2470
- "animOut": 0.2,
2471
- "rotation": 0
2472
- }
2473
- ],
2474
- "captions": [],
2475
- "stickers": [
2476
- {
2477
- "id": "editorial-rule",
2478
- "trackId": "overlay",
2479
- "shape": "underline",
2480
- "color": "#CEB88B",
2481
- "x": 50,
2482
- "y": 25,
2483
- "scale": 0.2,
2484
- "stretchX": 1.1,
2485
- "stretchY": 0.24,
2486
- "opacity": 0.85,
2487
- "rotation": 0,
2488
- "start": 0,
2489
- "end": 20
2490
- },
2491
- {
2492
- "id": "closing-rule",
2493
- "trackId": "overlay",
2494
- "shape": "underline",
2495
- "color": "#CEB88B",
2496
- "x": 50,
2497
- "y": 55,
2498
- "scale": 0.2,
2499
- "stretchX": 1.1,
2500
- "stretchY": 0.24,
2501
- "opacity": 0.85,
2502
- "rotation": 0,
2503
- "start": 20,
2504
- "end": 24
2505
- }
2506
- ],
2507
- "effects": [],
2508
- "audio": [],
2509
- "overlays": [
2510
- {
2511
- "id": "photo-caption-1",
2512
- "trackId": "text",
2513
- "type": "text",
2514
- "text": "Front",
2515
- "font": "Hanken Grotesk",
2516
- "size": 11,
2517
- "color": "#F7F0DB",
2518
- "background": "none",
2519
- "backgroundPadding": 0,
2520
- "width": 0.82,
2521
- "x": 50,
2522
- "y": 79,
2523
- "position": "center",
2524
- "start": 0.2,
2525
- "end": 3.4,
2526
- "duration": 3.2,
2527
- "animation": "fade",
2528
- "animIn": 0.25,
2529
- "animOut": 0.2,
2530
- "rotation": 0
2531
- },
2532
- {
2533
- "id": "photo-number-1",
2534
- "trackId": "text",
2535
- "type": "text",
2536
- "text": "01 / 04",
2537
- "font": "Hanken Grotesk",
2538
- "size": 6.5,
2539
- "color": "#CEB88B",
2540
- "background": "none",
2541
- "backgroundPadding": 0,
2542
- "width": 0.82,
2543
- "x": 50,
2544
- "y": 88,
2545
- "position": "center",
2546
- "start": 0,
2547
- "end": 3.49,
2548
- "duration": 3.49,
2549
- "animation": "fade",
2550
- "animIn": 0.25,
2551
- "animOut": 0.2,
2552
- "rotation": 0
2553
- },
2554
- {
2555
- "id": "photo-caption-2",
2556
- "trackId": "text",
2557
- "type": "text",
2558
- "text": "Side",
2559
- "font": "Hanken Grotesk",
2560
- "size": 11,
2561
- "color": "#F7F0DB",
2562
- "background": "none",
2563
- "backgroundPadding": 0,
2564
- "width": 0.82,
2565
- "x": 50,
2566
- "y": 79,
2567
- "position": "center",
2568
- "start": 3.7,
2569
- "end": 8.9,
2570
- "duration": 5.2,
2571
- "animation": "fade",
2572
- "animIn": 0.25,
2573
- "animOut": 0.2,
2574
- "rotation": 0
2575
- },
2576
- {
2577
- "id": "photo-number-2",
2578
- "trackId": "text",
2579
- "type": "text",
2580
- "text": "02 / 04",
2581
- "font": "Hanken Grotesk",
2582
- "size": 6.5,
2583
- "color": "#CEB88B",
2584
- "background": "none",
2585
- "backgroundPadding": 0,
2586
- "width": 0.82,
2587
- "x": 50,
2588
- "y": 88,
2589
- "position": "center",
2590
- "start": 3.5,
2591
- "end": 8.99,
2592
- "duration": 5.49,
2593
- "animation": "fade",
2594
- "animIn": 0.25,
2595
- "animOut": 0.2,
2596
- "rotation": 0
2597
- },
2598
- {
2599
- "id": "photo-caption-3",
2600
- "trackId": "text",
2601
- "type": "text",
2602
- "text": "Texture",
2603
- "font": "Hanken Grotesk",
2604
- "size": 11,
2605
- "color": "#F7F0DB",
2606
- "background": "none",
2607
- "backgroundPadding": 0,
2608
- "width": 0.82,
2609
- "x": 50,
2610
- "y": 79,
2611
- "position": "center",
2612
- "start": 9.2,
2613
- "end": 14.4,
2614
- "duration": 5.2,
2615
- "animation": "fade",
2616
- "animIn": 0.25,
2617
- "animOut": 0.2,
2618
- "rotation": 0
2619
- },
2620
- {
2621
- "id": "photo-number-3",
2622
- "trackId": "text",
2623
- "type": "text",
2624
- "text": "03 / 04",
2625
- "font": "Hanken Grotesk",
2626
- "size": 6.5,
2627
- "color": "#CEB88B",
2628
- "background": "none",
2629
- "backgroundPadding": 0,
2630
- "width": 0.82,
2631
- "x": 50,
2632
- "y": 88,
2633
- "position": "center",
2634
- "start": 9,
2635
- "end": 14.49,
2636
- "duration": 5.49,
2637
- "animation": "fade",
2638
- "animIn": 0.25,
2639
- "animOut": 0.2,
2640
- "rotation": 0
2641
- },
2642
- {
2643
- "id": "photo-caption-4",
2644
- "trackId": "text",
2645
- "type": "text",
2646
- "text": "Detail",
2647
- "font": "Hanken Grotesk",
2648
- "size": 11,
2649
- "color": "#F7F0DB",
2650
- "background": "none",
2651
- "backgroundPadding": 0,
2652
- "width": 0.82,
2653
- "x": 50,
2654
- "y": 79,
2655
- "position": "center",
2656
- "start": 14.7,
2657
- "end": 19.9,
2658
- "duration": 5.2,
2659
- "animation": "fade",
2660
- "animIn": 0.25,
2661
- "animOut": 0.2,
2662
- "rotation": 0
2663
- },
2664
- {
2665
- "id": "photo-number-4",
2666
- "trackId": "text",
2667
- "type": "text",
2668
- "text": "04 / 04",
2669
- "font": "Hanken Grotesk",
2670
- "size": 6.5,
2671
- "color": "#CEB88B",
2672
- "background": "none",
2673
- "backgroundPadding": 0,
2674
- "width": 0.82,
2675
- "x": 50,
2676
- "y": 88,
2677
- "position": "center",
2678
- "start": 14.5,
2679
- "end": 19.99,
2680
- "duration": 5.49,
2681
- "animation": "fade",
2682
- "animIn": 0.25,
2683
- "animOut": 0.2,
2684
- "rotation": 0
2685
- },
2686
- {
2687
- "id": "opening-title",
2688
- "trackId": "text",
2689
- "type": "text",
2690
- "text": "An object in four views",
2691
- "font": "Hanken Grotesk",
2692
- "size": 16,
2693
- "color": "#F7F0DB",
2694
- "background": "none",
2695
- "backgroundPadding": 0,
2696
- "width": 0.82,
2697
- "x": 50,
2698
- "y": 18,
2699
- "position": "center",
2700
- "start": 0,
2701
- "end": 3.4,
2702
- "duration": 3.4,
2703
- "animation": "fade",
2704
- "animIn": 0.25,
2705
- "animOut": 0.2,
2706
- "rotation": 0
2707
- },
2708
- {
2709
- "id": "sequence-title",
2710
- "trackId": "text",
2711
- "type": "text",
2712
- "text": "An object in four views",
2713
- "font": "Hanken Grotesk",
2714
- "size": 10,
2715
- "color": "#F7F0DB",
2716
- "background": "none",
2717
- "backgroundPadding": 0,
2718
- "width": 0.82,
2719
- "x": 50,
2720
- "y": 16,
2721
- "position": "center",
2722
- "start": 3.5,
2723
- "end": 20,
2724
- "duration": 16.5,
2725
- "animation": "fade",
2726
- "animIn": 0.25,
2727
- "animOut": 0.2,
2728
- "rotation": 0
2729
- },
2730
- {
2731
- "id": "closing-title",
2732
- "trackId": "text",
2733
- "type": "text",
2734
- "text": "An object in four views",
2735
- "font": "Hanken Grotesk",
2736
- "size": 10,
2737
- "color": "#CEB88B",
2738
- "background": "none",
2739
- "backgroundPadding": 0,
2740
- "width": 0.82,
2741
- "x": 50,
2742
- "y": 13,
2743
- "position": "center",
2744
- "start": 20,
2745
- "end": 24,
2746
- "duration": 4,
2747
- "animation": "fade",
2748
- "animIn": 0.25,
2749
- "animOut": 0.2,
2750
- "rotation": 0
2751
- },
2752
- {
2753
- "id": "closing-cta",
2754
- "trackId": "text",
2755
- "type": "text",
2756
- "text": "Explore the collection",
2757
- "font": "Hanken Grotesk",
2758
- "size": 17,
2759
- "color": "#F7F0DB",
2760
- "background": "none",
2761
- "backgroundPadding": 0,
2762
- "width": 0.82,
2763
- "x": 50,
2764
- "y": 65,
2765
- "position": "center",
2766
- "start": 20.1,
2767
- "end": 24,
2768
- "duration": 3.9,
2769
- "animation": "fade",
2770
- "animIn": 0.25,
2771
- "animOut": 0.2,
2772
- "rotation": 0
2773
- },
2774
- {
2775
- "id": "closing-contact",
2776
- "trackId": "text",
2777
- "type": "text",
2778
- "text": "Example contact",
2779
- "font": "Hanken Grotesk",
2780
- "size": 9,
2781
- "color": "#F7F0DB",
2782
- "background": "none",
2783
- "backgroundPadding": 0,
2784
- "width": 0.82,
2785
- "x": 50,
2786
- "y": 79,
2787
- "position": "center",
2788
- "start": 20.25,
2789
- "end": 24,
2790
- "duration": 3.75,
2791
- "animation": "fade",
2792
- "animIn": 0.25,
2793
- "animOut": 0.2,
2794
- "rotation": 0
2795
- },
2796
- {
2797
- "id": "demo-disclosure",
2798
- "trackId": "text",
2799
- "type": "text",
2800
- "text": "Sample only · not a product offer",
2801
- "font": "Hanken Grotesk",
2802
- "size": 6.5,
2803
- "color": "#D4D9D0",
2804
- "background": "none",
2805
- "backgroundPadding": 0,
2806
- "width": 0.84,
2807
- "x": 50,
2808
- "y": 94,
2809
- "position": "center",
2810
- "start": 0,
2811
- "end": 24,
2812
- "duration": 24,
2813
- "animation": "fade",
2814
- "animIn": 0.25,
2815
- "animOut": 0.2,
2816
- "rotation": 0
2817
- }
2818
- ],
2819
- "targetDuration": 24,
2820
- "exportSettings": {
2821
- "aspect": "9:16",
2822
- "fps": 30,
2823
- "resolution": "1080p",
2824
- "quality": "high"
2825
- },
2826
- "photoReel": {
2827
- "schemaVersion": 1,
2828
- "kind": "photo-reel-source-record",
2829
- "block": {
2830
- "id": "stillmade.photo-reel-composer",
2831
- "version": "1.0.0"
2832
- },
2833
- "purpose": "product",
2834
- "sourcePhotos": [
2835
- {
2836
- "index": 0,
2837
- "assetId": "photo-1",
2838
- "versionId": "original-v1",
2839
- "width": 1600,
2840
- "height": 1067
2841
- },
2842
- {
2843
- "index": 1,
2844
- "assetId": "photo-2",
2845
- "versionId": "original-v1",
2846
- "width": 1600,
2847
- "height": 1067
2848
- },
2849
- {
2850
- "index": 2,
2851
- "assetId": "photo-3",
2852
- "versionId": "original-v1",
2853
- "width": 1600,
2854
- "height": 1067
2855
- },
2856
- {
2857
- "index": 3,
2858
- "assetId": "photo-4",
2859
- "versionId": "original-v1",
2860
- "width": 1600,
2861
- "height": 1067
2862
- }
2863
- ],
2864
- "logo": null,
2865
- "music": null,
2866
- "approvedCopy": {
2867
- "title": "An object in four views",
2868
- "captions": [
2869
- "Front",
2870
- "Side",
2871
- "Texture",
2872
- "Detail"
2873
- ],
2874
- "cta": "Explore the collection",
2875
- "contact": "Example contact",
2876
- "demoDisclosure": "Sample only · not a product offer"
2877
- },
2878
- "rights": {
2879
- "userConfirmed": true,
2880
- "independentlyVerified": false
2881
- },
2882
- "transformations": [
2883
- "contain fit",
2884
- "uniform scale",
2885
- "at most three percent optical zoom"
2886
- ],
2887
- "generativeMedia": false,
2888
- "providerCalls": 0
2889
- }
2890
- },
2891
- "review": {
2892
- "schemaVersion": 1,
2893
- "state": "needs-human-review",
2894
- "durationSec": 24,
2895
- "aspect": "9:16",
2896
- "photoCount": 4,
2897
- "checks": [
2898
- {
2899
- "id": "original-source-versions",
2900
- "passed": true,
2901
- "note": "Every photo retains its supplied asset/version and full source rectangle."
2902
- },
2903
- {
2904
- "id": "approved-copy-only",
2905
- "passed": true,
2906
- "note": "No property features, prices, availability or product claims are generated."
2907
- },
2908
- {
2909
- "id": "bounded-local-composition",
2910
- "passed": true,
2911
- "note": "No provider call or credit spend occurs in this Block."
2912
- },
2913
- {
2914
- "id": "complete-timing",
2915
- "passed": true,
2916
- "note": "All source photos and a four-second closing card fit the requested duration."
2917
- }
2918
- ],
2919
- "warnings": [
2920
- "Review the full export for photo quality, exact facts, readable copy, licensing and the displayed contact before delivering.",
2921
- "Silent reel. Add rights-cleared music in this Block or the Editor if wanted.",
2922
- "This is labeled demonstration material and is not evidence of a real property or product offer."
2923
- ],
2924
- "humanApproved": false,
2925
- "exportAuthorized": false,
2926
- "cost": {
2927
- "providerCalls": 0,
2928
- "generationCredits": 0,
2929
- "note": "Host storage, export access and any separately added services use their own policy."
2930
- }
2931
- },
2932
- "provenance": {
2933
- "schemaVersion": 1,
2934
- "kind": "photo-reel-source-record",
2935
- "block": {
2936
- "id": "stillmade.photo-reel-composer",
2937
- "version": "1.0.0"
2938
- },
2939
- "purpose": "product",
2940
- "sourcePhotos": [
2941
- {
2942
- "index": 0,
2943
- "assetId": "photo-1",
2944
- "versionId": "original-v1",
2945
- "width": 1600,
2946
- "height": 1067
2947
- },
2948
- {
2949
- "index": 1,
2950
- "assetId": "photo-2",
2951
- "versionId": "original-v1",
2952
- "width": 1600,
2953
- "height": 1067
2954
- },
2955
- {
2956
- "index": 2,
2957
- "assetId": "photo-3",
2958
- "versionId": "original-v1",
2959
- "width": 1600,
2960
- "height": 1067
2961
- },
2962
- {
2963
- "index": 3,
2964
- "assetId": "photo-4",
2965
- "versionId": "original-v1",
2966
- "width": 1600,
2967
- "height": 1067
2968
- }
2969
- ],
2970
- "logo": null,
2971
- "music": null,
2972
- "approvedCopy": {
2973
- "title": "An object in four views",
2974
- "captions": [
2975
- "Front",
2976
- "Side",
2977
- "Texture",
2978
- "Detail"
2979
- ],
2980
- "cta": "Explore the collection",
2981
- "contact": "Example contact",
2982
- "demoDisclosure": "Sample only · not a product offer"
2983
- },
2984
- "rights": {
2985
- "userConfirmed": true,
2986
- "independentlyVerified": false
2987
- },
2988
- "transformations": [
2989
- "contain fit",
2990
- "uniform scale",
2991
- "at most three percent optical zoom"
2992
- ],
2993
- "generativeMedia": false,
2994
- "providerCalls": 0
2995
- }
2996
- }
2997
- }
2998
- ],
2999
- "portable": {
3000
- "format": "stillmade-block/1",
3001
- "dependencies": [],
3002
- "sources": [
3003
- {
3004
- "kind": "original",
3005
- "license": "MIT",
3006
- "paths": [
3007
- "LICENSE",
3008
- "src/run.js"
3009
- ],
3010
- "evidence": [
3011
- "upstream/0/LICENSE",
3012
- "upstream/0/src/run.js"
3013
- ],
3014
- "changes": "Original implementation declared by the packager; no reused repository or dependency code."
3015
- }
3016
- ],
3017
- "files": {
3018
- "upstream/0/LICENSE": "MIT License\n\nCopyright (c) <year> <copyright holders>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and \nassociated documentation files (the \"Software\"), to deal in the Software without restriction, including \nwithout limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell \ncopies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the \nfollowing conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial \nportions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT \nLIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO \nEVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER \nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE \nUSE OR OTHER DEALINGS IN THE SOFTWARE.\n",
3019
- "upstream/0/src/run.js": "// Photo Reel Composer 1.0.1. Runs only inside the isolated SDK JavaScript runtime.\n// Rights to supplied media are confirmed in the Content & IP Policy at sign-up.\n// References and supplied copy are data; this Block never reads media bytes,\n// calls a model, changes a photo, authorizes an export, or verifies legal rights.\nconst clone = value => JSON.parse(JSON.stringify(value));\nconst fail = (ok, message) => { if (!ok) throw new Error(message); };\nconst clean = (value, label, maximum, required = false) => {\n fail(value === undefined || typeof value === 'string', label + ' must be text.');\n const text = (value || '').trim();\n fail((!required || text.length > 0) && text.length <= maximum, label + ' must contain ' + (required ? '1' : '0') + ' to ' + maximum + ' characters.');\n fail(!/[\\u0000-\\u0008\\u000b\\u000c\\u000e-\\u001f]/.test(text), label + ' contains unsupported control characters.');\n fail(text.split(/\\s+/).every(word => word.length <= 28), label + ' contains a word or link too long to fit. Use a shorter display label.');\n return text;\n};\nconst purpose = input.purpose || 'property';\nfail(['property', 'product'].includes(purpose), 'Choose property or product.');\nconst assets = input.assets;\nconst minimum = purpose === 'property' ? 6 : 3;\nconst maximum = purpose === 'property' ? 8 : 10;\nfail(Array.isArray(assets) && assets.length >= minimum && assets.length <= maximum, 'Choose ' + minimum + ' to ' + maximum + ' original photos, in the order they should appear.');\nconst validMedia = (asset, kind, label) => {\n fail(asset && typeof asset === 'object' && !Array.isArray(asset) && asset.kind === kind, label + ' must be a ' + kind + ' reference.');\n fail(typeof asset.assetId === 'string' && asset.assetId.length > 0 && asset.assetId.length <= 240 && typeof asset.versionId === 'string' && asset.versionId.length > 0 && asset.versionId.length <= 240, label + ' needs its exact asset and version identities.');\n const mediaUrl = asset.url;\n const supportedUrl = typeof mediaUrl === 'string' && mediaUrl.length > 0 && mediaUrl.length <= 200000 && (\n /^\\/api\\/media\\/[A-Za-z0-9_-]+\\/[A-Za-z0-9_-][A-Za-z0-9._-]*$/.test(mediaUrl) ||\n /^(https:\\/\\/|http:\\/\\/(127\\.0\\.0\\.1|localhost)(:\\d+)?\\/|data:(image\\/(png|jpeg|webp)|audio\\/[a-z0-9.+-]+);base64,|blob:|sm-media:)/i.test(mediaUrl)\n ) && !/^https?:\\/\\/[^/?#]*@/i.test(mediaUrl);\n fail(supportedUrl, label + ' needs an authorized media reference.');\n if (kind === 'image') fail(Number.isFinite(asset.width) && asset.width > 0 && asset.width <= 40000 && Number.isFinite(asset.height) && asset.height > 0 && asset.height <= 40000, label + ' needs its measured original width and height. Upload this original photo again to record its dimensions.');\n return clone(asset);\n};\nconst photos = assets.map((asset, index) => validMedia(asset, 'image', 'Photo ' + (index + 1)));\nfail(new Set(photos.map(asset => asset.assetId + '\\n' + asset.versionId)).size === photos.length, 'Remove duplicate photo versions before composing.');\nconst title = clean(input.title, 'Approved title', 64, true);\nconst cta = clean(input.cta, 'Approved call to action', 56, true);\nconst contact = clean(input.contact, 'Contact or destination', 64);\nconst demoDisclosure = clean(input.demoDisclosure, 'Demo disclosure', 72);\nconst captionsText = input.captions || '';\nfail(typeof captionsText === 'string' && captionsText.length <= 1600, 'Use one short approved caption per photo.');\nconst captions = captionsText.trim() ? captionsText.replace(/\\r/g, '').split('\\n').map((line, index) => clean(line, 'Photo caption ' + (index + 1), 64)) : [];\nfail(captions.length === 0 || captions.length === photos.length, 'Supply exactly one caption line per photo, or leave captions empty. Blank lines keep a photo uncaptioned.');\n\nconst duration = input.duration === undefined ? 24 : input.duration;\nfail(Number.isFinite(duration) && duration >= 20 && duration <= 30, 'Choose a duration from 20 to 30 seconds.');\nconst aspect = input.aspect || '9:16';\nfail(['9:16', '16:9', '1:1'].includes(aspect), 'Choose 9:16, 16:9 or 1:1.');\nconst extra = (value, kind, label) => {\n fail(value === undefined || Array.isArray(value) && value.length <= 1, 'Choose at most one ' + label + '.');\n return value && value.length ? validMedia(value[0], kind, label) : null;\n};\nconst logo = extra(input.logo, 'image', 'logo');\nconst music = extra(input.music, 'audio', 'music track');\nif (music) fail(Number.isFinite(music.duration) && music.duration >= duration, 'The music track must have a measured duration covering the complete reel. Upload a supported MP3 or WAV again to record its duration, choose a longer track, or omit music.');\nconst [aw, ah] = aspect.split(':').map(Number);\nconst frameWidth = aw / ah * 369;\nconst portrait = aspect === '9:16';\nconst square = aspect === '1:1';\nconst backgroundColor = '#101714';\nconst foreground = '#F7F0DB';\nconst accent = '#CEB88B';\nconst overlays = [];\nconst clips = [];\nconst stickers = [];\nconst round = value => Math.round(value * 1000000) / 1000000;\nconst text = (id, value, start, end, y, size, color = foreground, width = .82) => {\n if (!value) return;\n // The shared renderer wraps between words only. Conservatively shrink a\n // single unusually long unbroken word; ordinary short-copy layouts stay put.\n const longest = Math.max(...value.split(/\\s+/).map(word => word.length));\n if (longest > 18) size = Math.min(size, (frameWidth * width - 12) / longest);\n overlays.push({ id, trackId: 'text', type: 'text', text: value, font: 'Hanken Grotesk', size, color, background: 'none', backgroundPadding: 0, width, x: 50, y, position: 'center', start: round(start), end: round(end), duration: round(end - start), animation: 'fade', animIn: .25, animOut: .2, rotation: 0 });\n};\nconst introEnd = 3.5;\nconst cardStart = duration - 4;\nconst sceneDuration = (cardStart - introEnd) / (photos.length - 1);\n// Fit the FULL measured photo inside a reserved rectangle, then add at most 3%\n// optical zoom. No crop, stretching, retouching, or synthetic pixels are requested.\nconst photoClip = (asset, index, start, length, endCard = false) => {\n const rawFit = Math.min(frameWidth / asset.width, 369 / asset.height);\n const fittedWidth = asset.width * rawFit;\n const fittedHeight = asset.height * rawFit;\n const regionWidth = frameWidth * (endCard ? .64 : .9);\n const regionHeight = 369 * (endCard ? .31 : portrait ? .48 : square ? .48 : .49);\n const scale = Math.min(regionWidth / fittedWidth, regionHeight / fittedHeight) / 1.03;\n const center = endCard ? .34 : .5;\n return {\n id: (endCard ? 'end-card-photo-' : 'photo-') + (index + 1), kind: 'image', trackId: 'video',\n asset: clone(asset), assetId: asset.assetId, versionId: asset.versionId, url: asset.url,\n title: asset.name || 'Photo ' + (index + 1), start: round(start), duration: round(length), trimStart: 0, speed: 1, volume: 0,\n transform: { fit: 'contain', scale, x: 0, y: (center - .5) * 369, rotation: 0, opacity: 1 },\n motion: { type: endCard ? 'none' : 'zoom', intensity: 100, zoomAmount: 1.03, zoomDirection: index % 2 ? 'out' : 'in', zoomAnchor: 'center', easing: 'ease-in-out', loop: false, ['window']: [0, 100] },\n transition: { type: endCard ? 'Cut' : 'Cross dissolve', duration: .3 },\n };\n};\nphotos.forEach((asset, index) => {\n const start = index === 0 ? 0 : introEnd + (index - 1) * sceneDuration;\n const end = index === 0 ? introEnd : index === photos.length - 1 ? cardStart : introEnd + index * sceneDuration;\n clips.push(photoClip(asset, index, start, end - start));\n text('photo-caption-' + (index + 1), captions[index], start + .2, end - .1, 79, portrait ? 11 : 14);\n text('photo-number-' + (index + 1), String(index + 1).padStart(2, '0') + ' / ' + String(photos.length).padStart(2, '0'), start, end - .01, 88, portrait ? 6.5 : 8, accent);\n});\nclips.push(photoClip(photos.at(-1), photos.length - 1, cardStart, 4, true));\n// The opening and closing compositions share an editorial rhythm while the\n// photographs remain full, unaltered, independently editable timeline items.\ntext('opening-title', title, 0, introEnd - .1, 18, portrait ? 16 : 22);\ntext('sequence-title', title, introEnd, cardStart, 16, portrait ? 10 : 14, foreground);\ntext('closing-title', title, cardStart, duration, 13, portrait ? 10 : 14, accent);\ntext('closing-cta', cta, cardStart + .1, duration, 65, portrait ? 17 : 23);\ntext('closing-contact', contact, cardStart + .25, duration, 79, portrait ? 9 : 12);\ntext('demo-disclosure', demoDisclosure, 0, duration, 94, portrait ? 6.5 : 8, '#D4D9D0', .84);\nstickers.push({ id: 'editorial-rule', trackId: 'overlay', shape: 'underline', color: accent, x: 50, y: 25, scale: .2, stretchX: 1.1, stretchY: .24, opacity: .85, rotation: 0, start: 0, end: cardStart });\nstickers.push({ id: 'closing-rule', trackId: 'overlay', shape: 'underline', color: accent, x: 50, y: 55, scale: .2, stretchX: 1.1, stretchY: .24, opacity: .85, rotation: 0, start: cardStart, end: duration });\nif (logo) {\n // Use an ordinary image clip on its own upper track. This avoids the GIF\n // sticker renderer's minimum-height distortion for unusually wide wordmarks.\n const fitted = Math.min(frameWidth / logo.width, 369 / logo.height);\n const scale = Math.min(frameWidth * .2 / (logo.width * fitted), 369 * .06 / (logo.height * fitted));\n clips.push({ id: 'brand-logo', kind: 'image', trackId: 'logo', asset: clone(logo), assetId: logo.assetId, versionId: logo.versionId, url: logo.url, start: cardStart, duration: 4, trimStart: 0, speed: 1, volume: 0, transform: { fit: 'contain', scale, x: 0, y: 369 * .39, rotation: 0, opacity: 1 }, motion: { type: 'none' }, transition: { type: 'Cut', duration: 0 } });\n}\nconst audioItems = music ? [{ id: 'music', trackId: 'audio', asset: clone(music), assetId: music.assetId, versionId: music.versionId, url: music.url, start: 0, duration, trimStart: 0, sourceOffset: 0, speed: 1, volume: 35, fadeIn: .5, fadeOut: .8 }] : [];\nconst provenance = {\n schemaVersion: 1, kind: 'photo-reel-source-record', block: { id: 'stillmade.photo-reel-composer', version: '1.0.0' }, purpose,\n sourcePhotos: photos.map((asset, index) => ({ index, assetId: asset.assetId, versionId: asset.versionId, width: asset.width, height: asset.height })),\n logo: logo ? { assetId: logo.assetId, versionId: logo.versionId } : null,\n music: music ? { assetId: music.assetId, versionId: music.versionId } : null,\n approvedCopy: { title, captions, cta, contact, demoDisclosure },\n rights: { userConfirmed: true, independentlyVerified: false },\n transformations: ['contain fit', 'uniform scale', 'at most three percent optical zoom'],\n generativeMedia: false, providerCalls: 0,\n};\nconst timeline = {\n schemaVersion: 1, activeTimelineId: 'photo-reel', name: title, aspect, aspectRatio: aspect, previewH: 369, backgroundColor,\n tracks: [{ id: 'video', type: 'video', label: 'Original photos' }, ...(logo ? [{ id: 'logo', type: 'video', label: 'Original logo' }] : []), { id: 'text', type: 'text', label: 'Approved copy' }, { id: 'overlay', type: 'overlay', label: 'Graphic details' }, { id: 'audio', type: 'audio', label: 'Music' }],\n trackOrder: ['video', 'logo', 'text', 'overlay', 'audio'], clips, audioItems, textOverlays: overlays, captions: [], stickers, effects: [],\n // The device renderer consumes these legacy aliases; Editor keeps the normal\n // editable lanes above. Both refer to the same content at creation time.\n audio: clone(audioItems), overlays: clone(overlays), targetDuration: duration,\n exportSettings: { aspect, fps: 30, resolution: '1080p', quality: 'high' },\n photoReel: clone(provenance),\n};\nconst lowResolution = photos.filter(asset => asset.width < 1080 || asset.height < 720).map(asset => asset.assetId);\nreturn {\n timeline,\n review: {\n schemaVersion: 1, state: 'needs-human-review', durationSec: duration, aspect, photoCount: photos.length,\n checks: [\n { id: 'original-source-versions', passed: true, note: 'Every photo retains its supplied asset/version and full source rectangle.' },\n { id: 'approved-copy-only', passed: true, note: 'No property features, prices, availability or product claims are generated.' },\n { id: 'bounded-local-composition', passed: true, note: 'No provider call or credit spend occurs in this Block.' },\n { id: 'complete-timing', passed: true, note: 'All source photos and a four-second closing card fit the requested duration.' },\n ],\n warnings: [\n 'Review the full export for photo quality, exact facts, readable copy, licensing and the displayed contact before delivering.',\n ...(!music ? ['Silent reel. Add rights-cleared music in this Block or the Editor if wanted.'] : []),\n ...(lowResolution.length ? ['Small source images may look soft in a 1080p export: ' + lowResolution.join(', ')] : []),\n ...(demoDisclosure ? ['This is labeled demonstration material and is not evidence of a real property or product offer.'] : []),\n ],\n humanApproved: false, exportAuthorized: false, cost: { providerCalls: 0, generationCredits: 0, note: 'Host storage, export access and any separately added services use their own policy.' },\n },\n provenance,\n};\n"
3020
- },
3021
- "lineage": {
3022
- "parents": [],
3023
- "changes": "Packaged original Block source for StillMade."
3024
- }
3025
- }
3026
- };