frameyard 0.8.0 → 0.9.0

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/CHANGELOG.md +110 -14
  2. package/GLOSSARY.md +112 -2
  3. package/README.md +302 -265
  4. package/dist/assets/integrations.d.ts +8 -4
  5. package/dist/assets/integrations.d.ts.map +1 -1
  6. package/dist/assets/integrations.js +8 -4
  7. package/dist/assets/integrations.js.map +1 -1
  8. package/dist/assets/provenance.d.ts +2 -2
  9. package/dist/assets/provenance.d.ts.map +1 -1
  10. package/dist/assets/provenance.js +5 -3
  11. package/dist/assets/provenance.js.map +1 -1
  12. package/dist/assets/tts-supertonic.d.ts +28 -0
  13. package/dist/assets/tts-supertonic.d.ts.map +1 -0
  14. package/dist/assets/tts-supertonic.js +156 -0
  15. package/dist/assets/tts-supertonic.js.map +1 -0
  16. package/dist/assets/tts.d.ts +18 -6
  17. package/dist/assets/tts.d.ts.map +1 -1
  18. package/dist/assets/tts.js +219 -97
  19. package/dist/assets/tts.js.map +1 -1
  20. package/dist/cli.js +1685 -93
  21. package/dist/cli.js.map +1 -1
  22. package/dist/composition/format.d.ts +1 -1
  23. package/dist/composition/format.d.ts.map +1 -1
  24. package/dist/composition/format.js +1 -1
  25. package/dist/composition/format.js.map +1 -1
  26. package/dist/context.d.ts +82 -0
  27. package/dist/context.d.ts.map +1 -0
  28. package/dist/context.js +277 -0
  29. package/dist/context.js.map +1 -0
  30. package/dist/contracts.d.ts +25 -0
  31. package/dist/contracts.d.ts.map +1 -1
  32. package/dist/contracts.js.map +1 -1
  33. package/dist/doctor.d.ts +14 -1
  34. package/dist/doctor.d.ts.map +1 -1
  35. package/dist/doctor.js +166 -7
  36. package/dist/doctor.js.map +1 -1
  37. package/dist/errors.d.ts +1 -1
  38. package/dist/errors.d.ts.map +1 -1
  39. package/dist/errors.js.map +1 -1
  40. package/dist/fonts/add.d.ts +41 -0
  41. package/dist/fonts/add.d.ts.map +1 -0
  42. package/dist/fonts/add.js +259 -0
  43. package/dist/fonts/add.js.map +1 -0
  44. package/dist/fonts/binary.d.ts +4 -0
  45. package/dist/fonts/binary.d.ts.map +1 -0
  46. package/dist/fonts/binary.js +21 -0
  47. package/dist/fonts/binary.js.map +1 -0
  48. package/dist/fonts/css.d.ts +4 -0
  49. package/dist/fonts/css.d.ts.map +1 -0
  50. package/dist/fonts/css.js +50 -0
  51. package/dist/fonts/css.js.map +1 -0
  52. package/dist/fonts/fontsource.d.ts +107 -0
  53. package/dist/fonts/fontsource.d.ts.map +1 -0
  54. package/dist/fonts/fontsource.js +565 -0
  55. package/dist/fonts/fontsource.js.map +1 -0
  56. package/dist/fonts/index.d.ts +11 -0
  57. package/dist/fonts/index.d.ts.map +1 -0
  58. package/dist/fonts/index.js +11 -0
  59. package/dist/fonts/index.js.map +1 -0
  60. package/dist/fonts/install.d.ts +24 -0
  61. package/dist/fonts/install.d.ts.map +1 -0
  62. package/dist/fonts/install.js +145 -0
  63. package/dist/fonts/install.js.map +1 -0
  64. package/dist/fonts/manifest.d.ts +21 -0
  65. package/dist/fonts/manifest.d.ts.map +1 -0
  66. package/dist/fonts/manifest.js +96 -0
  67. package/dist/fonts/manifest.js.map +1 -0
  68. package/dist/fonts/options.d.ts +9 -0
  69. package/dist/fonts/options.d.ts.map +1 -0
  70. package/dist/fonts/options.js +66 -0
  71. package/dist/fonts/options.js.map +1 -0
  72. package/dist/fonts/schema.d.ts +4 -0
  73. package/dist/fonts/schema.d.ts.map +1 -0
  74. package/dist/fonts/schema.js +316 -0
  75. package/dist/fonts/schema.js.map +1 -0
  76. package/dist/fonts/summary.d.ts +16 -0
  77. package/dist/fonts/summary.d.ts.map +1 -0
  78. package/dist/fonts/summary.js +22 -0
  79. package/dist/fonts/summary.js.map +1 -0
  80. package/dist/fonts/types.d.ts +56 -0
  81. package/dist/fonts/types.d.ts.map +1 -0
  82. package/dist/fonts/types.js +8 -0
  83. package/dist/fonts/types.js.map +1 -0
  84. package/dist/fonts/verify.d.ts +33 -0
  85. package/dist/fonts/verify.d.ts.map +1 -0
  86. package/dist/fonts/verify.js +200 -0
  87. package/dist/fonts/verify.js.map +1 -0
  88. package/dist/html/validate.d.ts.map +1 -1
  89. package/dist/html/validate.js +59 -0
  90. package/dist/html/validate.js.map +1 -1
  91. package/dist/index.d.ts +3 -3
  92. package/dist/index.d.ts.map +1 -1
  93. package/dist/index.js +1 -1
  94. package/dist/index.js.map +1 -1
  95. package/dist/inspect.d.ts +61 -0
  96. package/dist/inspect.d.ts.map +1 -0
  97. package/dist/inspect.js +325 -0
  98. package/dist/inspect.js.map +1 -0
  99. package/dist/lint.d.ts +63 -0
  100. package/dist/lint.d.ts.map +1 -0
  101. package/dist/lint.js +265 -0
  102. package/dist/lint.js.map +1 -0
  103. package/dist/policy.d.ts +69 -0
  104. package/dist/policy.d.ts.map +1 -0
  105. package/dist/policy.js +361 -0
  106. package/dist/policy.js.map +1 -0
  107. package/dist/preview/timeline-data.d.ts +17 -69
  108. package/dist/preview/timeline-data.d.ts.map +1 -1
  109. package/dist/preview/timeline-host.d.ts.map +1 -1
  110. package/dist/preview/timeline-host.js +70 -45
  111. package/dist/preview/timeline-host.js.map +1 -1
  112. package/dist/preview/timeline-main.d.ts.map +1 -1
  113. package/dist/preview/timeline-main.js +47 -4
  114. package/dist/preview/timeline-main.js.map +1 -1
  115. package/dist/project.d.ts +10 -3
  116. package/dist/project.d.ts.map +1 -1
  117. package/dist/project.js +20 -17
  118. package/dist/project.js.map +1 -1
  119. package/dist/renderer/ffmpeg.d.ts +42 -2
  120. package/dist/renderer/ffmpeg.d.ts.map +1 -1
  121. package/dist/renderer/ffmpeg.js +254 -22
  122. package/dist/renderer/ffmpeg.js.map +1 -1
  123. package/dist/renderer/index.js +1 -1
  124. package/dist/renderer/index.js.map +1 -1
  125. package/dist/renderer/keyframe-expressions.d.ts +39 -0
  126. package/dist/renderer/keyframe-expressions.d.ts.map +1 -0
  127. package/dist/renderer/keyframe-expressions.js +180 -0
  128. package/dist/renderer/keyframe-expressions.js.map +1 -0
  129. package/dist/renderer/timeline.d.ts +2 -0
  130. package/dist/renderer/timeline.d.ts.map +1 -1
  131. package/dist/renderer/timeline.js +89 -116
  132. package/dist/renderer/timeline.js.map +1 -1
  133. package/dist/runtime/host.d.ts.map +1 -1
  134. package/dist/runtime/host.js +4 -0
  135. package/dist/runtime/host.js.map +1 -1
  136. package/dist/scaffold.d.ts +3 -0
  137. package/dist/scaffold.d.ts.map +1 -1
  138. package/dist/scaffold.js +48 -320
  139. package/dist/scaffold.js.map +1 -1
  140. package/dist/server/composition-html.d.ts +2 -0
  141. package/dist/server/composition-html.d.ts.map +1 -1
  142. package/dist/server/composition-html.js +7 -0
  143. package/dist/server/composition-html.js.map +1 -1
  144. package/dist/server/server.d.ts.map +1 -1
  145. package/dist/server/server.js +31 -1
  146. package/dist/server/server.js.map +1 -1
  147. package/dist/server/timeline-preview-data.d.ts.map +1 -1
  148. package/dist/server/timeline-preview-data.js +12 -34
  149. package/dist/server/timeline-preview-data.js.map +1 -1
  150. package/dist/server/timeline-preview-html.d.ts.map +1 -1
  151. package/dist/server/timeline-preview-html.js +18 -2
  152. package/dist/server/timeline-preview-html.js.map +1 -1
  153. package/dist/templates.d.ts +16 -0
  154. package/dist/templates.d.ts.map +1 -0
  155. package/dist/templates.js +186 -0
  156. package/dist/templates.js.map +1 -0
  157. package/dist/timeline/easing.d.ts +36 -0
  158. package/dist/timeline/easing.d.ts.map +1 -0
  159. package/dist/timeline/easing.js +225 -0
  160. package/dist/timeline/easing.js.map +1 -0
  161. package/dist/timeline/keyframes.d.ts +23 -0
  162. package/dist/timeline/keyframes.d.ts.map +1 -0
  163. package/dist/timeline/keyframes.js +95 -0
  164. package/dist/timeline/keyframes.js.map +1 -0
  165. package/dist/timeline/plan.d.ts +6 -12
  166. package/dist/timeline/plan.d.ts.map +1 -1
  167. package/dist/timeline/plan.js +17 -30
  168. package/dist/timeline/plan.js.map +1 -1
  169. package/dist/timeline/resolve.d.ts +12 -0
  170. package/dist/timeline/resolve.d.ts.map +1 -1
  171. package/dist/timeline/resolve.js +105 -9
  172. package/dist/timeline/resolve.js.map +1 -1
  173. package/dist/timeline/scene.d.ts +126 -0
  174. package/dist/timeline/scene.d.ts.map +1 -0
  175. package/dist/timeline/scene.js +109 -0
  176. package/dist/timeline/scene.js.map +1 -0
  177. package/dist/timeline/schema.d.ts +31 -0
  178. package/dist/timeline/schema.d.ts.map +1 -1
  179. package/dist/timeline/schema.js +240 -9
  180. package/dist/timeline/schema.js.map +1 -1
  181. package/dist/timeline/transitions.d.ts +21 -0
  182. package/dist/timeline/transitions.d.ts.map +1 -0
  183. package/dist/timeline/transitions.js +23 -0
  184. package/dist/timeline/transitions.js.map +1 -0
  185. package/dist/version.d.ts +1 -1
  186. package/dist/version.js +1 -1
  187. package/docs/adr/0007-make-html-documents-the-composition-unit.md +1 -1
  188. package/docs/adr/0010-make-timelines-the-render-unit.md +3 -2
  189. package/docs/adr/0014-compose-timeline-clips-with-css-blend-modes.md +2 -1
  190. package/docs/adr/0015-inherit-composition-format-from-the-project.md +2 -2
  191. package/docs/adr/0016-author-compositions-as-html-fragments.md +1 -1
  192. package/docs/adr/0018-animate-timeline-clips-with-keyframes.md +35 -0
  193. package/docs/adr/0019-make-same-track-overlap-the-transition-window.md +36 -0
  194. package/docs/adr/0020-crossfade-audio-clips-on-audio-tracks.md +27 -0
  195. package/docs/adr/0021-project-timeline-scenes-once.md +32 -0
  196. package/docs/adr/0022-gate-heavy-operations-with-a-workspace-resource-policy.md +35 -0
  197. package/docs/adr/0023-pin-fonts-as-project-assets.md +98 -0
  198. package/docs/migration-0.4.md +2 -2
  199. package/docs/preview-testing.md +19 -6
  200. package/docs/{v0.1-design.md → v0.x-design.md} +55 -30
  201. package/examples/blend/README.md +3 -3
  202. package/examples/demo/README.md +2 -2
  203. package/examples/intro/README.md +71 -0
  204. package/examples/intro/assets/fonts/figtree/LICENSE.txt +93 -0
  205. package/examples/intro/assets/fonts/figtree/figtree-latin-wght-normal.woff2 +0 -0
  206. package/examples/intro/assets/fonts/instrument-serif/LICENSE.txt +93 -0
  207. package/examples/intro/assets/fonts/instrument-serif/instrument-serif-latin-400-italic.woff2 +0 -0
  208. package/examples/intro/assets/fonts/space-mono/LICENSE.txt +93 -0
  209. package/examples/intro/assets/fonts/space-mono/space-mono-latin-400-normal.woff2 +0 -0
  210. package/examples/intro/assets/fonts/space-mono/space-mono-latin-700-normal.woff2 +0 -0
  211. package/examples/intro/assets/grain.png +0 -0
  212. package/examples/intro/assets/score.ogg +0 -0
  213. package/examples/intro/compositions/brand.html +412 -0
  214. package/examples/intro/compositions/chrome.controller.js +63 -0
  215. package/examples/intro/compositions/chrome.html +256 -0
  216. package/examples/intro/compositions/lattice.controller.js +148 -0
  217. package/examples/intro/compositions/lattice.html +308 -0
  218. package/examples/intro/compositions/opening.html +504 -0
  219. package/examples/intro/compositions/studio.html +930 -0
  220. package/examples/intro/compositions/theme.css +218 -0
  221. package/examples/intro/fy.config.js +13 -0
  222. package/examples/intro/fy.fonts.json +100 -0
  223. package/examples/intro/scripts/make-grain.mjs +79 -0
  224. package/examples/intro/scripts/make-score.mjs +702 -0
  225. package/examples/intro/timelines/intro.timeline.json +60 -0
  226. package/examples/keyframes/README.md +76 -0
  227. package/examples/keyframes/compositions/backdrop.html +60 -0
  228. package/examples/keyframes/compositions/card.html +99 -0
  229. package/examples/keyframes/fy.config.js +10 -0
  230. package/examples/keyframes/timelines/keyframes.timeline.json +60 -0
  231. package/examples/nested/README.md +112 -0
  232. package/examples/nested/assets/pulse.wav +0 -0
  233. package/examples/nested/compositions/backdrop.html +84 -0
  234. package/examples/nested/compositions/card.html +275 -0
  235. package/examples/nested/compositions/overlay.html +307 -0
  236. package/examples/nested/fy.config.js +13 -0
  237. package/examples/nested/scripts/make-pulse.sh +20 -0
  238. package/examples/nested/timelines/chapter-a.timeline.json +39 -0
  239. package/examples/nested/timelines/chapter-b.timeline.json +39 -0
  240. package/examples/nested/timelines/nested-reel.timeline.json +52 -0
  241. package/examples/static/README.md +2 -2
  242. package/examples/transitions/README.md +128 -0
  243. package/examples/transitions/assets/alpha.wav +0 -0
  244. package/examples/transitions/assets/beta.wav +0 -0
  245. package/examples/transitions/assets/gamma.wav +0 -0
  246. package/examples/transitions/compositions/alpha.html +56 -0
  247. package/examples/transitions/compositions/beta.html +56 -0
  248. package/examples/transitions/compositions/gamma.html +56 -0
  249. package/examples/transitions/fy.config.js +12 -0
  250. package/examples/transitions/timelines/audio-crossfade.timeline.json +44 -0
  251. package/examples/transitions/timelines/transitions.timeline.json +31 -0
  252. package/examples/video/README.md +4 -4
  253. package/examples/webgl/README.md +1 -1
  254. package/package.json +12 -5
  255. package/scaffolds/init/AGENTS.md +131 -0
  256. package/scaffolds/init/README.md +56 -0
  257. package/scaffolds/init/compositions/hello.html +79 -0
  258. package/scaffolds/init/fy.config.js +9 -0
  259. package/scaffolds/init/gitignore.template +1 -0
  260. package/scaffolds/init/package.json +11 -0
  261. package/scaffolds/init/props/hello.json +4 -0
  262. package/scaffolds/init/props/main.json +6 -0
  263. package/scaffolds/init/timelines/main.timeline.json +20 -0
  264. package/scaffolds/local-models/LOCAL-MODELS.md +77 -0
  265. package/scaffolds/local-models/fy.policy.json +5 -0
  266. package/scaffolds/local-models/opencode/opencode.jsonc +17 -0
  267. package/scaffolds/local-models/pi/APPEND_SYSTEM.md +21 -0
  268. package/scaffolds/local-models/pi/sandbox.json +15 -0
  269. package/scaffolds/local-models/pi/settings.json +15 -0
  270. package/skills/frameyard/README.md +1 -0
  271. package/skills/frameyard/SKILL.md +59 -61
  272. package/skills/frameyard/references/audio-assets.md +32 -3
  273. package/skills/frameyard/references/common-mistakes.md +53 -2
  274. package/skills/frameyard/references/deterministic-authoring.md +10 -3
  275. package/skills/frameyard/references/diagnostics.md +31 -1
  276. package/skills/frameyard/references/failure-recovery.md +32 -6
  277. package/skills/frameyard/references/fonts.md +132 -0
  278. package/skills/frameyard/references/json-results.md +119 -6
  279. package/skills/frameyard/references/quick-reference.md +222 -0
  280. package/skills/frameyard/references/timelines.md +97 -7
  281. /package/examples/blend/{video.config.js → fy.config.js} +0 -0
  282. /package/examples/demo/{video.config.js → fy.config.js} +0 -0
  283. /package/examples/static/{video.config.js → fy.config.js} +0 -0
  284. /package/examples/video/{video.config.js → fy.config.js} +0 -0
  285. /package/examples/webgl/{video.config.js → fy.config.js} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"project.js","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,aAAa,EAA0B,MAAM,gBAAgB,CAAC;AAgCvE,MAAM,UAAU,GAAG,8BAA8B,CAAC;AAElD,KAAK,UAAU,MAAM,CAAC,QAAgB;IACpC,IAAI,CAAC;QACH,OAAO,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,gEAAgE;AAChE,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE;IAC5D,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAElC,IAAI,CAAC;QACH,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;YACzC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,cAAc,CAAC,kBAAkB,EAAE,qCAAqC,OAAO,EAAE,CAAC,CAAC;IAC/F,CAAC;IAED,OAAO,IAAI,EAAE,CAAC;QACZ,IAAI,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC,EAAE,CAAC;YACxD,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACrC,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;YACvB,MAAM,IAAI,cAAc,CACtB,kBAAkB,EAClB,iCAAiC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,4DAA4D,CACjH,CAAC;QACJ,CAAC;QACD,OAAO,GAAG,MAAM,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,KAAc;IACrC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,cAAc,CAAC,gBAAgB,EAAE,uEAAuE,CAAC,CAAC;IACtH,CAAC;IAED,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;IACrC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAK,KAAgB,IAAI,CAAC,EAAE,CAAC;QACvD,MAAM,IAAI,cAAc,CAAC,gBAAgB,EAAE,0DAA0D,CAAC,CAAC;IACzG,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAK,MAAiB,IAAI,CAAC,EAAE,CAAC;QACzD,MAAM,IAAI,cAAc,CAAC,gBAAgB,EAAE,2DAA2D,CAAC,CAAC;IAC1G,CAAC;IACD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC;QACjE,MAAM,IAAI,cAAc,CAAC,gBAAgB,EAAE,uDAAuD,CAAC,CAAC;IACtG,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,KAAe,EAAE,MAAM,EAAE,MAAgB,EAAE,GAAG,EAAE,CAAC;AACnE,CAAC;AAED,SAAS,SAAS,CAChB,IAAY,EACZ,EAAU,EACV,UAAmB,EACnB,SAAiB;IAEjB,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9D,MAAM,IAAI,cAAc,CAAC,gBAAgB,EAAE,UAAU,EAAE,+BAA+B,CAAC,CAAC;IAC1F,CAAC;IAED,MAAM,KAAK,GAAG,UAAU,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC/C,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,cAAc,CAAC,gBAAgB,EAAE,UAAU,EAAE,yCAAyC,CAAC,CAAC;IACpG,CAAC;IAED,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAChD,IAAI,aAAa,KAAK,IAAI,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACzE,MAAM,IAAI,cAAc,CAAC,gBAAgB,EAAE,UAAU,EAAE,+BAA+B,UAAU,EAAE,CAAC,CAAC;IACtG,CAAC;IACD,IAAI,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,WAAW,EAAE,KAAK,SAAS,EAAE,CAAC;QAC5D,MAAM,IAAI,cAAc,CAAC,gBAAgB,EAAE,UAAU,EAAE,eAAe,SAAS,UAAU,UAAU,EAAE,CAAC,CAAC;IACzG,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,aAAa,EAAE,CAAC;AAChG,CAAC;AAED,yFAAyF;AACzF,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,WAAmB;IACnD,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACvC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;IAEtD,IAAI,CAAC,CAAC,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,cAAc,CAAC,kBAAkB,EAAE,+BAA+B,IAAI,GAAG,CAAC,CAAC;IACvF,CAAC;IAED,IAAI,YAAmC,CAAC;IACxC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;QACtC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;QACxE,YAAY,GAAG,CAAC,MAAM,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAA0B,CAAC;IACnE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,cAAc,CACtB,gBAAgB,EAChB,kBAAkB,UAAU,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EACzF,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC;IACpC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,cAAc,CAAC,gBAAgB,EAAE,6DAA6D,CAAC,CAAC;IAC5G,CAAC;IAED,MAAM,eAAe,GAAG,MAAM,CAAC,YAAY,CAAC;IAC5C,MAAM,YAAY,GAAG,MAAM,CAAC,SAAS,CAAC;IACtC,IAAI,eAAe,KAAK,SAAS,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;QAChE,MAAM,IAAI,cAAc,CAAC,gBAAgB,EAAE,kEAAkE,CAAC,CAAC;IACjH,CAAC;IACD,IAAI,eAAe,KAAK,SAAS,IAAI,CAAC,aAAa,CAAC,eAAe,CAAC,EAAE,CAAC;QACrE,MAAM,IAAI,cAAc,CAAC,gBAAgB,EAAE,qDAAqD,CAAC,CAAC;IACpG,CAAC;IACD,IAAI,YAAY,KAAK,SAAS,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,EAAE,CAAC;QAC/D,MAAM,IAAI,cAAc,CAAC,gBAAgB,EAAE,8CAA8C,CAAC,CAAC;IAC7F,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACxF,MAAM,YAAY,GAAG,IAAI,GAAG,EAA8B,CAAC;IAC3D,MAAM,SAAS,GAAG,IAAI,GAAG,EAA2B,CAAC;IACrD,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAE9B,KAAK,MAAM,CAAC,EAAE,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,eAAe,IAAI,EAAE,CAAC,EAAE,CAAC;QACnE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,cAAc,CACtB,gBAAgB,EAChB,2BAA2B,EAAE,yFAAyF,CACvH,CAAC;QACJ,CAAC;QACD,IAAI,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;YAChB,MAAM,IAAI,cAAc,CAAC,gBAAgB,EAAE,eAAe,EAAE,mCAAmC,CAAC,CAAC;QACnG,CAAC;QAED,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;QACxD,IAAI,CAAC,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC;YAC5C,MAAM,IAAI,cAAc,CAAC,gBAAgB,EAAE,gBAAgB,EAAE,2BAA2B,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC9G,CAAC;QAED,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACZ,YAAY,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAC1D,CAAC;IAED,KAAK,MAAM,CAAC,EAAE,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,IAAI,EAAE,CAAC,EAAE,CAAC;QAChE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,cAAc,CACtB,gBAAgB,EAChB,wBAAwB,EAAE,yFAAyF,CACpH,CAAC;QACJ,CAAC;QACD,IAAI,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;YAChB,MAAM,IAAI,cAAc,CAAC,gBAAgB,EAAE,eAAe,EAAE,mCAAmC,CAAC,CAAC;QACnG,CAAC;QAED,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;QACxD,IAAI,CAAC,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC;YAC5C,MAAM,IAAI,cAAc,CAAC,gBAAgB,EAAE,aAAa,EAAE,2BAA2B,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC3G,CAAC;QAED,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACZ,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,IAAI,YAAY,CAAC,IAAI,KAAK,CAAC,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACpD,MAAM,IAAI,cAAc,CAAC,gBAAgB,EAAE,iEAAiE,CAAC,CAAC;IAChH,CAAC;IACD,IAAI,SAAS,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QAClC,MAAM,IAAI,cAAc,CACtB,gBAAgB,EAChB,qFAAqF,CACtF,CAAC;IACJ,CAAC;IAED,OAAO;QACL,IAAI;QACJ,UAAU;QACV,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7B,YAAY;QACZ,SAAS;KACV,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,6 @@
1
- import type { BlendMode } from "../timeline/schema.js";
1
+ import type { AudioVolumeEnvelope } from "../contracts.js";
2
+ import type { BlendMode, TimelineKeyframes } from "../timeline/schema.js";
3
+ import type { TimelineSceneLayer, TimelineSceneSource } from "../timeline/scene.js";
2
4
  /** Fails early when the installed FFmpeg cannot produce the required output. */
3
5
  export declare function assertFfmpegCapabilities(signal?: AbortSignal, codec?: VideoCodec): Promise<void>;
4
6
  /** Output video codec. */
@@ -72,6 +74,8 @@ export interface MixClip {
72
74
  trimStart: number;
73
75
  trimDuration?: number;
74
76
  volume: number;
77
+ /** Multiplicative equal-power ramps evaluated against absolute timeline frames. */
78
+ volumeEnvelopes?: AudioVolumeEnvelope[];
75
79
  }
76
80
  /** Normalizes any decodable source to the 16 kHz mono PCM WAV that whisper.cpp expects. */
77
81
  export declare function normalizeAudioForTranscription(options: {
@@ -79,6 +83,12 @@ export declare function normalizeAudioForTranscription(options: {
79
83
  outputPath: string;
80
84
  signal?: AbortSignal;
81
85
  }): Promise<void>;
86
+ /** Normalizes generated speech to the 24 kHz mono PCM WAV that Frameyard publishes. */
87
+ export declare function normalizeSpeechAudio(options: {
88
+ inputPath: string;
89
+ outputPath: string;
90
+ signal?: AbortSignal;
91
+ }): Promise<void>;
82
92
  export declare function mixAudioTimeline(options: {
83
93
  clips: MixClip[];
84
94
  fps: number;
@@ -107,7 +117,8 @@ export declare function startVideoEncoder(options: {
107
117
  signal?: AbortSignal;
108
118
  }): Promise<VideoEncoder>;
109
119
  export interface TimelineCompositeLayer {
110
- kind: "composition" | "timeline" | "video" | "image";
120
+ /** How FFmpeg reads the captured artifact. */
121
+ input: "sequence" | "image" | "video";
111
122
  path: string;
112
123
  sourceWidth: number;
113
124
  sourceHeight: number;
@@ -124,7 +135,32 @@ export interface TimelineCompositeLayer {
124
135
  blend: BlendMode;
125
136
  /** Absolute source frame at the segment start, for video inputs. */
126
137
  sourceStartFrame?: number;
138
+ /** Per-channel presentation animation, evaluated in clip-local frames. */
139
+ keyframes?: TimelineKeyframes;
140
+ /** Timeline frame where the clip starts. Defaults to 0. */
141
+ clipStart?: number;
142
+ /** Transition role while the composite range intersects the overlap window. */
143
+ transition?: {
144
+ role: "in" | "out";
145
+ /** Inclusive first timeline frame. */
146
+ start: number;
147
+ /** Exclusive last timeline frame. */
148
+ end: number;
149
+ easing?: string;
150
+ };
127
151
  }
152
+ export interface TimelineCompositeArtifact {
153
+ path: string;
154
+ input: TimelineCompositeLayer["input"];
155
+ /** Absolute source frame at the segment start, for video inputs. */
156
+ sourceStartFrame?: number;
157
+ }
158
+ /**
159
+ * Builds FFmpeg's narrow layer input from a projected scene layer. The mapper
160
+ * owns the scene-to-filter boundary; capture chooses the artifact and its input
161
+ * mode, while the scene owns presentation, keyframes, and transition roles.
162
+ */
163
+ export declare function sceneLayerToCompositeLayer<S extends TimelineSceneSource>(layer: TimelineSceneLayer<S>, artifact: TimelineCompositeArtifact): TimelineCompositeLayer;
128
164
  /** Encode a numbered PNG sequence into a lossless alpha-preserving FFV1 file. */
129
165
  export declare function encodePngSequenceToFfv1(options: {
130
166
  pattern: string;
@@ -142,6 +178,8 @@ export declare function compositeTimelineSegment(options: {
142
178
  /** CSS color, "black", or "transparent" for nested timelines. */
143
179
  background: string;
144
180
  layers: readonly TimelineCompositeLayer[];
181
+ /** Absolute timeline frame of the first output frame. Defaults to 0. */
182
+ frameOffset?: number;
145
183
  /** Segment payload: lossless FFV1 intermediates or a delivery codec. */
146
184
  codec: VideoCodec | "ffv1";
147
185
  /** Encoder for delivery codecs; defaults to `libx264`. */
@@ -180,6 +218,8 @@ export declare function compositeTimelineFrame(options: {
180
218
  fps: number;
181
219
  background: string;
182
220
  layers: readonly TimelineCompositeLayer[];
221
+ /** Absolute timeline frame being captured. Defaults to 0. */
222
+ frameOffset?: number;
183
223
  signal?: AbortSignal;
184
224
  }): Promise<void>;
185
225
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"ffmpeg.d.ts","sourceRoot":"","sources":["../../src/renderer/ffmpeg.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ffmpeg.d.ts","sourceRoot":"","sources":["../../src/renderer/ffmpeg.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,9 @@
1
1
  import { spawn } from "node:child_process";
2
2
  import { writeFile } from "node:fs/promises";
3
3
  import { FrameyardError } from "../errors.js";
4
+ import { evaluatePresentation } from "../timeline/keyframes.js";
5
+ import { transitionProgress } from "../timeline/transitions.js";
6
+ import { keyframeChannelExpression, transitionGainExpression, transitionProgressExpression, } from "./keyframe-expressions.js";
4
7
  const STDERR_LIMIT = 16 * 1024;
5
8
  function captureTail(child) {
6
9
  let tail = "";
@@ -302,8 +305,7 @@ export async function probeMedia(filePath, options = {}) {
302
305
  throw new FrameyardError("FFPROBE_FAILED", `Could not parse ffprobe output for ${filePath}.`, { cause: error });
303
306
  }
304
307
  }
305
- /** Normalizes any decodable source to the 16 kHz mono PCM WAV that whisper.cpp expects. */
306
- export async function normalizeAudioForTranscription(options) {
308
+ async function normalizeAudio(options) {
307
309
  await runCaptured("ffmpeg", [
308
310
  "-hide_banner",
309
311
  "-loglevel",
@@ -318,12 +320,20 @@ export async function normalizeAudioForTranscription(options) {
318
320
  "-ac",
319
321
  "1",
320
322
  "-ar",
321
- "16000",
323
+ String(options.sampleRate),
322
324
  "-c:a",
323
325
  "pcm_s16le",
324
326
  options.outputPath,
325
327
  ], { signal: options.signal });
326
328
  }
329
+ /** Normalizes any decodable source to the 16 kHz mono PCM WAV that whisper.cpp expects. */
330
+ export async function normalizeAudioForTranscription(options) {
331
+ await normalizeAudio({ ...options, sampleRate: 16_000 });
332
+ }
333
+ /** Normalizes generated speech to the 24 kHz mono PCM WAV that Frameyard publishes. */
334
+ export async function normalizeSpeechAudio(options) {
335
+ await normalizeAudio({ ...options, sampleRate: 24_000 });
336
+ }
327
337
  export async function mixAudioTimeline(options) {
328
338
  if (options.clips.length === 0) {
329
339
  throw new FrameyardError("AUDIO_INVALID", "Cannot mix an empty audio timeline.");
@@ -340,10 +350,22 @@ export async function mixAudioTimeline(options) {
340
350
  trim.push(`duration=${formatNumber(clip.trimDuration)}`);
341
351
  }
342
352
  const delayMs = Math.round((clip.startFrame * 1000) / options.fps);
353
+ const gain = clip.volumeEnvelopes?.length
354
+ ? clip.volumeEnvelopes
355
+ .map((envelope) => transitionGainExpression({
356
+ progressExpression: `((${formatNumber(clip.startFrame)}+t*${formatNumber(options.fps)}-${formatNumber(envelope.startFrame)})/${formatNumber(envelope.endFrame - envelope.startFrame)})`,
357
+ ...(envelope.easing !== undefined ? { easing: envelope.easing } : {}),
358
+ role: envelope.role,
359
+ }))
360
+ .join("*")
361
+ : undefined;
362
+ const volume = gain === undefined
363
+ ? `volume=${formatNumber(clip.volume)}`
364
+ : `volume='${formatNumber(clip.volume)}*(${gain})':eval=frame`;
343
365
  const chain = [
344
366
  `atrim=${trim.join(":")}`,
345
367
  "asetpts=PTS-STARTPTS",
346
- `volume=${formatNumber(clip.volume)}`,
368
+ volume,
347
369
  "aresample=48000",
348
370
  "aformat=sample_fmts=fltp:channel_layouts=stereo",
349
371
  "apad",
@@ -492,6 +514,44 @@ export async function startVideoEncoder(options) {
492
514
  abort,
493
515
  };
494
516
  }
517
+ /**
518
+ * Builds FFmpeg's narrow layer input from a projected scene layer. The mapper
519
+ * owns the scene-to-filter boundary; capture chooses the artifact and its input
520
+ * mode, while the scene owns presentation, keyframes, and transition roles.
521
+ */
522
+ export function sceneLayerToCompositeLayer(layer, artifact) {
523
+ const transform = layer.transform;
524
+ const transition = layer.transition;
525
+ return {
526
+ input: artifact.input,
527
+ path: artifact.path,
528
+ sourceWidth: layer.sourceWidth,
529
+ sourceHeight: layer.sourceHeight,
530
+ ...(transform.width !== undefined && transform.height !== undefined
531
+ ? { width: transform.width, height: transform.height }
532
+ : {}),
533
+ fit: transform.fit,
534
+ x: transform.x,
535
+ y: transform.y,
536
+ scale: transform.scale,
537
+ rotation: transform.rotation,
538
+ opacity: transform.opacity,
539
+ blend: layer.blend,
540
+ ...(artifact.sourceStartFrame !== undefined ? { sourceStartFrame: artifact.sourceStartFrame } : {}),
541
+ ...(layer.keyframes !== undefined ? { keyframes: layer.keyframes } : {}),
542
+ clipStart: layer.clip.start,
543
+ ...(transition !== undefined
544
+ ? {
545
+ transition: {
546
+ role: transition.role,
547
+ start: transition.window.start,
548
+ end: transition.window.end,
549
+ ...(transition.window.easing !== undefined ? { easing: transition.window.easing } : {}),
550
+ },
551
+ }
552
+ : {}),
553
+ };
554
+ }
495
555
  function ffmpegBackgroundColor(value) {
496
556
  if (value === "transparent") {
497
557
  return "black@0.0";
@@ -533,25 +593,160 @@ function fitFilter(layer, stageWidth, stageHeight) {
533
593
  const fittedHeight = Math.max(1, Math.round(sourceHeight * scale));
534
594
  return `scale=${fittedWidth}:${fittedHeight},pad=${width}:${height}:(ow-iw)/2:(oh-ih)/2:color=black@0`;
535
595
  }
536
- function layerFilter(layer, stageWidth, stageHeight, fps) {
537
- const filters = [
596
+ function layerTransform(layer) {
597
+ return {
598
+ fit: layer.fit,
599
+ x: layer.x,
600
+ y: layer.y,
601
+ ...(layer.width !== undefined && layer.height !== undefined ? { width: layer.width, height: layer.height } : {}),
602
+ scale: layer.scale,
603
+ rotation: layer.rotation,
604
+ opacity: layer.opacity,
605
+ };
606
+ }
607
+ function hasKeyframe(layer, channel) {
608
+ return layer.keyframes?.[channel] !== undefined;
609
+ }
610
+ /** The incoming layer's animated alpha at an absolute timeline frame. */
611
+ function transitionAlphaAt(layer, frame) {
612
+ if (layer.transition?.role !== "in") {
613
+ return 1;
614
+ }
615
+ return transitionProgress(layer.transition, frame);
616
+ }
617
+ /** False when a keyed or transitioning layer is invisible for every frame of the range. */
618
+ function isLayerVisibleInRange(layer, frameOffset, frames) {
619
+ const animated = hasKeyframe(layer, "opacity") || hasKeyframe(layer, "scale");
620
+ if (!animated && layer.transition?.role !== "in") {
621
+ return layer.opacity > 0 && layer.scale > 0;
622
+ }
623
+ const transform = layerTransform(layer);
624
+ const clipStart = layer.clipStart ?? 0;
625
+ for (let index = 0; index < frames; index += 1) {
626
+ const frame = frameOffset + index;
627
+ const values = evaluatePresentation(transform, layer.keyframes, frame - clipStart);
628
+ if (values.opacity * transitionAlphaAt(layer, frame) > 0 && values.scale > 0) {
629
+ return true;
630
+ }
631
+ }
632
+ return false;
633
+ }
634
+ function baseLayerFilters(layer, stageWidth, stageHeight, fps) {
635
+ return [
538
636
  // Matroska and WebM timestamps can be quantized to milliseconds. Normalize
539
637
  // every timed layer to the project frame rate before overlay framesync so
540
638
  // it does not duplicate or drop frames. Still images are already static.
541
- ...(layer.kind === "image" ? [] : [`fps=${formatNumber(fps)}`]),
639
+ ...(layer.input === "image" ? [] : [`fps=${formatNumber(fps)}`]),
542
640
  fitFilter(layer, stageWidth, stageHeight),
543
641
  "format=rgba",
544
642
  ];
545
- if (layer.scale !== 1) {
546
- filters.push(`scale=iw*${formatNumber(layer.scale)}:ih*${formatNumber(layer.scale)}`);
643
+ }
644
+ /** Dimensions entering the rotate filter for this layer. */
645
+ function rotationInputSize(layer, stageWidth, stageHeight) {
646
+ const width = layer.width ?? stageWidth;
647
+ const height = layer.height ?? stageHeight;
648
+ if (layer.keyframes?.scale !== undefined) {
649
+ // Animated scale is applied after rotation, keeping the rotate input fixed.
650
+ return { width, height };
547
651
  }
548
- if (layer.rotation !== 0) {
549
- filters.push(`rotate=angle=${formatNumber(layer.rotation)}*PI/180:fillcolor=black@0`);
652
+ return {
653
+ width: Math.max(1, Math.ceil(width * layer.scale)),
654
+ height: Math.max(1, Math.ceil(height * layer.scale)),
655
+ };
656
+ }
657
+ function rotatedBounds(width, height, degrees) {
658
+ const radians = (degrees * Math.PI) / 180;
659
+ const cosine = Math.abs(Math.cos(radians));
660
+ const sine = Math.abs(Math.sin(radians));
661
+ // Two extra pixels absorb filter rounding and anti-aliased edge pixels.
662
+ return {
663
+ width: Math.max(1, Math.ceil(width * cosine + height * sine) + 2),
664
+ height: Math.max(1, Math.ceil(width * sine + height * cosine) + 2),
665
+ };
666
+ }
667
+ /**
668
+ * FFmpeg's rotate filter clips to a fixed output size. A keyed rotation uses a
669
+ * square diagonal bound so every segment uses the same size and corners stay
670
+ * visible at any angle. Static rotation uses its exact bounding box.
671
+ */
672
+ function rotationOutputSize(layer, stageWidth, stageHeight) {
673
+ const input = rotationInputSize(layer, stageWidth, stageHeight);
674
+ if (layer.keyframes?.rotation) {
675
+ const diagonal = Math.max(1, Math.ceil(Math.hypot(input.width, input.height)) + 2);
676
+ return { width: diagonal, height: diagonal };
550
677
  }
551
- if (layer.opacity < 1) {
678
+ return rotatedBounds(input.width, input.height, layer.rotation);
679
+ }
680
+ function needsOpacityMask(layer) {
681
+ return hasKeyframe(layer, "opacity") || hasKeyframe(layer, "scale") || layer.transition?.role === "in";
682
+ }
683
+ /**
684
+ * Presentation filters after the optional opacity mask. Animated scale is
685
+ * applied after rotation because uniform scale and rotation commute; rotation
686
+ * then keeps a fixed input size for the rotate filter.
687
+ */
688
+ function presentationLayerFilters(layer, stageWidth, stageHeight, frameOffset) {
689
+ const filters = [];
690
+ const clipStart = layer.clipStart ?? 0;
691
+ const frameOptions = { frameVariable: "n", frameOffset, clipStart };
692
+ const scaleKeys = layer.keyframes?.scale;
693
+ const rotationKeys = layer.keyframes?.rotation;
694
+ const opacityKeys = layer.keyframes?.opacity;
695
+ const addRotation = () => {
696
+ if (rotationKeys || layer.rotation !== 0) {
697
+ const output = rotationOutputSize(layer, stageWidth, stageHeight);
698
+ const outputSize = `ow=${output.width}:oh=${output.height}`;
699
+ if (rotationKeys) {
700
+ const angle = keyframeChannelExpression("rotation", rotationKeys, frameOptions);
701
+ filters.push(`rotate=angle='(${angle})*PI/180':fillcolor=black@0:${outputSize}`);
702
+ }
703
+ else {
704
+ filters.push(`rotate=angle=${formatNumber(layer.rotation)}*PI/180:fillcolor=black@0:${outputSize}`);
705
+ }
706
+ }
707
+ };
708
+ if (scaleKeys) {
709
+ addRotation();
710
+ const scale = keyframeChannelExpression("scale", scaleKeys, frameOptions);
711
+ filters.push(`scale=w='max(1,iw*(${scale}))':h='max(1,ih*(${scale}))':eval=frame`);
712
+ }
713
+ else {
714
+ if (layer.scale !== 1) {
715
+ filters.push(`scale=iw*${formatNumber(layer.scale)}:ih*${formatNumber(layer.scale)}`);
716
+ }
717
+ addRotation();
718
+ }
719
+ // A transitioning layer carries its opacity in the animated mask instead.
720
+ if (!opacityKeys && !scaleKeys && layer.transition?.role !== "in" && layer.opacity < 1) {
552
721
  filters.push(`colorchannelmixer=aa=${formatNumber(layer.opacity)}`);
553
722
  }
554
- return filters.join(",");
723
+ return filters;
724
+ }
725
+ /** Builds the animated alpha mask at the fitted box size. */
726
+ function opacityMaskFilter(options) {
727
+ const { layer, stageWidth, stageHeight, frameOffset, inputIndex, outputLabel } = options;
728
+ const clipStart = layer.clipStart ?? 0;
729
+ const frameOptions = { frameVariable: "N", frameOffset, clipStart };
730
+ const opacityKeys = layer.keyframes?.opacity;
731
+ const scaleKeys = layer.keyframes?.scale;
732
+ const opacity = opacityKeys
733
+ ? keyframeChannelExpression("opacity", opacityKeys, frameOptions)
734
+ : formatNumber(layer.opacity);
735
+ const scale = scaleKeys ? keyframeChannelExpression("scale", scaleKeys, frameOptions) : undefined;
736
+ const visible = scale !== undefined ? `if(gt(${scale},0),1,0)` : "1";
737
+ const transition = layer.transition?.role === "in"
738
+ ? transitionProgressExpression({
739
+ frameVariable: "N",
740
+ frameOffset,
741
+ start: layer.transition.start,
742
+ end: layer.transition.end,
743
+ ...(layer.transition.easing !== undefined ? { easing: layer.transition.easing } : {}),
744
+ })
745
+ : undefined;
746
+ const alpha = `min(1,max(0,(${opacity})*(${visible})${transition !== undefined ? `*(${transition})` : ""}))`;
747
+ const width = layer.width ?? stageWidth;
748
+ const height = layer.height ?? stageHeight;
749
+ return `[${inputIndex}:v]format=rgba,geq=r=0:g=0:b=0:a='255*${alpha}',scale=${width}:${height}:flags=neighbor,format=rgba[${outputLabel}]`;
555
750
  }
556
751
  /** W3C soft-light in 0-255 space; FFmpeg's native mode uses a different formula. */
557
752
  const SOFT_LIGHT_EXPRESSION = "if(lt(B,128), A-(1-2*B/255)*A*(1-A/255), A+(2*B/255-1)*(if(lt(A,64),((16*A/255-12)*A/255+4)*A/255,sqrt(A/255))*255-A))";
@@ -580,8 +775,17 @@ function blendSpec(mode) {
580
775
  sourceFirst: mode === "color-dodge" || mode === "color-burn",
581
776
  };
582
777
  }
583
- function placementFilter(layer) {
584
- return `x=(main_w-overlay_w)/2+${formatNumber(layer.x)}:y=(main_h-overlay_h)/2+${formatNumber(layer.y)}`;
778
+ function placementFilter(layer, frameOffset) {
779
+ const clipStart = layer.clipStart ?? 0;
780
+ const frameOptions = { frameVariable: "n", frameOffset, clipStart };
781
+ const xKeys = layer.keyframes?.x;
782
+ const yKeys = layer.keyframes?.y;
783
+ const x = xKeys ? keyframeChannelExpression("x", xKeys, frameOptions) : formatNumber(layer.x);
784
+ const y = yKeys ? keyframeChannelExpression("y", yKeys, frameOptions) : formatNumber(layer.y);
785
+ if (!xKeys && !yKeys) {
786
+ return `x=(main_w-overlay_w)/2+${x}:y=(main_h-overlay_h)/2+${y}`;
787
+ }
788
+ return `x='(main_w-overlay_w)/2+(${x})':y='(main_h-overlay_h)/2+(${y})':eval=frame`;
585
789
  }
586
790
  /**
587
791
  * Builds the FFmpeg filter graph for one timeline composite. Blend layers are
@@ -605,7 +809,7 @@ function buildCompositeGraph(options) {
605
809
  let current = "base0";
606
810
  let inputIndex = 0;
607
811
  let includedIndex = 0;
608
- const blendedLayers = options.layers.filter((layer) => layer.blend !== "normal" && layer.opacity > 0 && layer.scale > 0);
812
+ const blendedLayers = options.layers.filter((layer) => layer.blend !== "normal" && isLayerVisibleInRange(layer, options.frameOffset, options.frames));
609
813
  const canvasLabels = [];
610
814
  if (blendedLayers.length > 0) {
611
815
  args.push("-f", "lavfi", "-i", `color=c=black@0.0:s=${options.width}x${options.height}:r=${formatNumber(options.fps)}:d=${formatNumber(durationSeconds)}`);
@@ -620,10 +824,19 @@ function buildCompositeGraph(options) {
620
824
  }
621
825
  let canvasIndex = 0;
622
826
  for (const layer of options.layers) {
623
- if (layer.opacity <= 0 || layer.scale <= 0) {
827
+ if (!isLayerVisibleInRange(layer, options.frameOffset, options.frames)) {
624
828
  continue;
625
829
  }
626
- if (layer.kind === "video") {
830
+ const masked = needsOpacityMask(layer);
831
+ let maskInput = 0;
832
+ if (masked) {
833
+ args.push("-f", "lavfi", "-i",
834
+ // FFmpeg 6 rejects a 1x1 yuv420p source (chroma planes round to zero).
835
+ `color=c=black@0.0:s=2x2:r=${formatNumber(options.fps)}:d=${formatNumber(durationSeconds)}`);
836
+ inputIndex += 1;
837
+ maskInput = inputIndex;
838
+ }
839
+ if (layer.input === "video") {
627
840
  const startSeconds = (layer.sourceStartFrame ?? 0) / options.fps;
628
841
  if (options.segment) {
629
842
  args.push("-ss", formatNumber(startSeconds), "-t", formatNumber(durationSeconds), "-i", layer.path, "-an");
@@ -632,7 +845,7 @@ function buildCompositeGraph(options) {
632
845
  args.push("-ss", formatNumber(startSeconds), "-i", layer.path, "-an");
633
846
  }
634
847
  }
635
- else if (layer.kind === "image") {
848
+ else if (layer.input === "image") {
636
849
  if (options.segment) {
637
850
  args.push("-loop", "1", "-framerate", formatNumber(options.fps), "-t", formatNumber(durationSeconds), "-i", layer.path, "-an");
638
851
  }
@@ -645,15 +858,32 @@ function buildCompositeGraph(options) {
645
858
  }
646
859
  inputIndex += 1;
647
860
  includedIndex += 1;
648
- filters.push(`[${inputIndex}:v]${layerFilter(layer, options.width, options.height, options.fps)}[l${includedIndex}]`);
861
+ const layerInput = inputIndex;
862
+ const base = baseLayerFilters(layer, options.width, options.height, options.fps);
863
+ const presentation = presentationLayerFilters(layer, options.width, options.height, options.frameOffset);
864
+ if (masked) {
865
+ filters.push(`[${layerInput}:v]${base.join(",")}[v${includedIndex}]`);
866
+ filters.push(opacityMaskFilter({
867
+ layer,
868
+ stageWidth: options.width,
869
+ stageHeight: options.height,
870
+ frameOffset: options.frameOffset,
871
+ inputIndex: maskInput,
872
+ outputLabel: `km${includedIndex}`,
873
+ }));
874
+ filters.push(`[v${includedIndex}][km${includedIndex}]blend=c0_mode=normal:c1_mode=normal:c2_mode=normal:c3_mode=multiply${presentation.length > 0 ? `,${presentation.join(",")}` : ""}[l${includedIndex}]`);
875
+ }
876
+ else {
877
+ filters.push(`[${layerInput}:v]${[...base, ...presentation].join(",")}[l${includedIndex}]`);
878
+ }
649
879
  if (layer.blend === "normal") {
650
- filters.push(`[${current}][l${includedIndex}]overlay=${placementFilter(layer)}:format=auto[b${includedIndex}]`);
880
+ filters.push(`[${current}][l${includedIndex}]overlay=${placementFilter(layer, options.frameOffset)}:format=auto[b${includedIndex}]`);
651
881
  current = `b${includedIndex}`;
652
882
  continue;
653
883
  }
654
884
  const canvas = canvasLabels[canvasIndex];
655
885
  canvasIndex += 1;
656
- filters.push(`[${canvas}][l${includedIndex}]overlay=${placementFilter(layer)}:format=auto,format=rgba,split=2[pb${includedIndex}][pm${includedIndex}]`);
886
+ filters.push(`[${canvas}][l${includedIndex}]overlay=${placementFilter(layer, options.frameOffset)}:format=auto,format=rgba,split=2[pb${includedIndex}][pm${includedIndex}]`);
657
887
  filters.push(`[${current}]format=rgba,split=3[bc${includedIndex}][bm${includedIndex}][bo${includedIndex}]`);
658
888
  filters.push(`[bm${includedIndex}]alphaextract,format=rgba[mask${includedIndex}]`);
659
889
  const spec = blendSpec(layer.blend);
@@ -692,6 +922,7 @@ export async function compositeTimelineSegment(options) {
692
922
  height: options.height,
693
923
  fps: options.fps,
694
924
  frames: options.frames,
925
+ frameOffset: options.frameOffset ?? 0,
695
926
  background: options.background,
696
927
  layers: options.layers,
697
928
  segment: true,
@@ -766,6 +997,7 @@ export async function compositeTimelineFrame(options) {
766
997
  height: options.height,
767
998
  fps: options.fps,
768
999
  frames: 1,
1000
+ frameOffset: options.frameOffset ?? 0,
769
1001
  background: options.background,
770
1002
  layers: options.layers,
771
1003
  segment: false,