frameyard 0.7.0 → 0.8.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 (138) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/GLOSSARY.md +40 -16
  3. package/README.md +54 -48
  4. package/dist/cli.js +23 -16
  5. package/dist/cli.js.map +1 -1
  6. package/dist/composition/descriptor.d.ts +17 -3
  7. package/dist/composition/descriptor.d.ts.map +1 -1
  8. package/dist/composition/descriptor.js +51 -28
  9. package/dist/composition/descriptor.js.map +1 -1
  10. package/dist/composition/format.d.ts +12 -0
  11. package/dist/composition/format.d.ts.map +1 -0
  12. package/dist/composition/format.js +28 -0
  13. package/dist/composition/format.js.map +1 -0
  14. package/dist/composition/index.d.ts +2 -1
  15. package/dist/composition/index.d.ts.map +1 -1
  16. package/dist/composition/index.js +1 -0
  17. package/dist/composition/index.js.map +1 -1
  18. package/dist/contracts.d.ts +55 -6
  19. package/dist/contracts.d.ts.map +1 -1
  20. package/dist/contracts.js +3 -0
  21. package/dist/contracts.js.map +1 -1
  22. package/dist/errors.d.ts +1 -1
  23. package/dist/errors.d.ts.map +1 -1
  24. package/dist/errors.js.map +1 -1
  25. package/dist/html/document-adapter.d.ts +3 -3
  26. package/dist/html/document-adapter.d.ts.map +1 -1
  27. package/dist/html/document-adapter.js +1 -1
  28. package/dist/html/document-adapter.js.map +1 -1
  29. package/dist/html/index.d.ts +1 -1
  30. package/dist/html/index.d.ts.map +1 -1
  31. package/dist/html/parse.d.ts +10 -2
  32. package/dist/html/parse.d.ts.map +1 -1
  33. package/dist/html/parse.js +14 -5
  34. package/dist/html/parse.js.map +1 -1
  35. package/dist/html/validate.d.ts +12 -1
  36. package/dist/html/validate.d.ts.map +1 -1
  37. package/dist/html/validate.js +233 -61
  38. package/dist/html/validate.js.map +1 -1
  39. package/dist/index.d.ts +4 -4
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +2 -2
  42. package/dist/index.js.map +1 -1
  43. package/dist/preview/main.d.ts +2 -2
  44. package/dist/preview/main.d.ts.map +1 -1
  45. package/dist/preview/main.js +35 -14
  46. package/dist/preview/main.js.map +1 -1
  47. package/dist/preview/timeline-data.d.ts +5 -1
  48. package/dist/preview/timeline-data.d.ts.map +1 -1
  49. package/dist/preview/timeline-host.d.ts.map +1 -1
  50. package/dist/preview/timeline-host.js +10 -0
  51. package/dist/preview/timeline-host.js.map +1 -1
  52. package/dist/preview/timeline-main.js +3 -2
  53. package/dist/preview/timeline-main.js.map +1 -1
  54. package/dist/project.d.ts +3 -5
  55. package/dist/project.d.ts.map +1 -1
  56. package/dist/project.js.map +1 -1
  57. package/dist/renderer/browser.d.ts +2 -2
  58. package/dist/renderer/browser.d.ts.map +1 -1
  59. package/dist/renderer/browser.js +10 -4
  60. package/dist/renderer/browser.js.map +1 -1
  61. package/dist/renderer/ffmpeg.d.ts +3 -0
  62. package/dist/renderer/ffmpeg.d.ts.map +1 -1
  63. package/dist/renderer/ffmpeg.js +122 -56
  64. package/dist/renderer/ffmpeg.js.map +1 -1
  65. package/dist/renderer/index.d.ts +40 -4
  66. package/dist/renderer/index.d.ts.map +1 -1
  67. package/dist/renderer/index.js +99 -24
  68. package/dist/renderer/index.js.map +1 -1
  69. package/dist/renderer/timeline.d.ts.map +1 -1
  70. package/dist/renderer/timeline.js +89 -0
  71. package/dist/renderer/timeline.js.map +1 -1
  72. package/dist/runtime/host.d.ts.map +1 -1
  73. package/dist/runtime/host.js +155 -31
  74. package/dist/runtime/host.js.map +1 -1
  75. package/dist/scaffold.d.ts.map +1 -1
  76. package/dist/scaffold.js +104 -101
  77. package/dist/scaffold.js.map +1 -1
  78. package/dist/server/composition-html.d.ts +13 -7
  79. package/dist/server/composition-html.d.ts.map +1 -1
  80. package/dist/server/composition-html.js +65 -16
  81. package/dist/server/composition-html.js.map +1 -1
  82. package/dist/server/server.d.ts.map +1 -1
  83. package/dist/server/server.js +26 -6
  84. package/dist/server/server.js.map +1 -1
  85. package/dist/server/timeline-preview-data.d.ts.map +1 -1
  86. package/dist/server/timeline-preview-data.js +11 -0
  87. package/dist/server/timeline-preview-data.js.map +1 -1
  88. package/dist/server/timeline-preview-html.d.ts.map +1 -1
  89. package/dist/server/timeline-preview-html.js +2 -1
  90. package/dist/server/timeline-preview-html.js.map +1 -1
  91. package/dist/timeline/resolve.d.ts +4 -3
  92. package/dist/timeline/resolve.d.ts.map +1 -1
  93. package/dist/timeline/resolve.js +14 -4
  94. package/dist/timeline/resolve.js.map +1 -1
  95. package/dist/timeline/schema.d.ts +7 -0
  96. package/dist/timeline/schema.d.ts.map +1 -1
  97. package/dist/timeline/schema.js +50 -0
  98. package/dist/timeline/schema.js.map +1 -1
  99. package/dist/version.d.ts +1 -1
  100. package/dist/version.js +1 -1
  101. package/docs/adr/0007-make-html-documents-the-composition-unit.md +1 -1
  102. package/docs/adr/0008-share-the-composition-document-grammar.md +1 -1
  103. package/docs/adr/0011-compose-timeline-frames-in-a-live-browser-host.md +1 -1
  104. package/docs/adr/0012-render-timelines-with-segmented-lossless-clip-intermediates.md +1 -1
  105. package/docs/adr/0014-compose-timeline-clips-with-css-blend-modes.md +37 -0
  106. package/docs/adr/0015-inherit-composition-format-from-the-project.md +28 -0
  107. package/docs/adr/0016-author-compositions-as-html-fragments.md +32 -0
  108. package/docs/adr/0017-render-timeless-compositions-as-stills.md +99 -0
  109. package/docs/migration-0.4.md +3 -1
  110. package/docs/migration-0.8.md +163 -0
  111. package/docs/preview-testing.md +7 -0
  112. package/docs/v0.1-design.md +42 -34
  113. package/examples/blend/README.md +106 -0
  114. package/examples/blend/assets/ink.mp4 +0 -0
  115. package/examples/blend/compositions/aurora.html +55 -0
  116. package/examples/blend/compositions/backdrop.html +74 -0
  117. package/examples/blend/compositions/labels.html +149 -0
  118. package/examples/blend/scripts/make-ink.sh +26 -0
  119. package/examples/blend/timelines/blend.timeline.json +155 -0
  120. package/examples/blend/video.config.js +11 -0
  121. package/examples/demo/compositions/demo.html +243 -251
  122. package/examples/static/README.md +17 -0
  123. package/examples/static/compositions/still.html +37 -0
  124. package/examples/static/timelines/still.timeline.json +13 -0
  125. package/examples/static/video.config.js +9 -0
  126. package/examples/video/compositions/video-mp4.html +349 -357
  127. package/examples/video/compositions/video-overlay.html +337 -345
  128. package/examples/video/compositions/video.html +349 -357
  129. package/examples/webgl/compositions/webgl.html +205 -213
  130. package/package.json +2 -1
  131. package/skills/frameyard/SKILL.md +15 -13
  132. package/skills/frameyard/references/common-mistakes.md +29 -6
  133. package/skills/frameyard/references/controllers.md +5 -4
  134. package/skills/frameyard/references/deterministic-authoring.md +41 -36
  135. package/skills/frameyard/references/diagnostics.md +11 -3
  136. package/skills/frameyard/references/failure-recovery.md +25 -5
  137. package/skills/frameyard/references/json-results.md +46 -4
  138. package/skills/frameyard/references/timelines.md +16 -12
@@ -0,0 +1,106 @@
1
+ # Frameyard blend example
2
+
3
+ A 12-second, 1920×1080, 30 fps timeline that demonstrates every supported CSS
4
+ blend mode on composition and video clips. Four video tracks build one frame:
5
+
6
+ - `v1` **backdrop** — a static opaque HTML composition with a grid, concentric
7
+ rings, and a dark vignette. It omits the time metadata and all dimensions, so
8
+ it inherits the project format and is captured once at the timeline's size.
9
+ - `v2` **aurora** — a static transparent HTML composition with three blurred
10
+ color blobs. It declares its dimensions but no time metadata, so it is also
11
+ captured once. Its clip uses `blend: "screen"` for the full 12 seconds.
12
+ - `v3` **ink** — a local 1280×720 H.264 clip scaled to fill the project frame.
13
+ Twelve touching clips play one second each, cycling through all 12 supported
14
+ modes in timeline order.
15
+ - `v4` **labels** — an animated transparent HTML composition in normal mode. It
16
+ lists the modes and their time ranges, and draws a progress bar from the
17
+ `--fy-progress` frame-state variable, so it is evaluated per frame.
18
+
19
+ The mode sequence on `v3` is:
20
+
21
+ | Time | Mode |
22
+ | --- | --- |
23
+ | 0–1 s | `normal` |
24
+ | 1–2 s | `multiply` |
25
+ | 2–3 s | `screen` |
26
+ | 3–4 s | `overlay` |
27
+ | 4–5 s | `darken` |
28
+ | 5–6 s | `lighten` |
29
+ | 6–7 s | `color-dodge` |
30
+ | 7–8 s | `color-burn` |
31
+ | 8–9 s | `hard-light` |
32
+ | 9–10 s | `soft-light` |
33
+ | 10–11 s | `difference` |
34
+ | 11–12 s | `exclusion` |
35
+
36
+ The aurora is transparent, so its `screen` blends only where its blobs have
37
+ alpha. The video is opaque, so its whole scaled frame participates in the blend.
38
+ The labels layer stays in `normal` mode so the copy remains readable.
39
+
40
+ Blend modes are static per clip. The example uses consecutive clips on `v3` to
41
+ show every mode in one timeline; it does not animate `blend` itself. `hue`,
42
+ `saturation`, `color`, and `luminosity` are rejected because they need
43
+ cross-channel math and are not part of the supported set.
44
+
45
+ `backdrop` and `aurora` are static compositions: they declare no
46
+ `duration-in-frames` or `fps`, are captured once, and the same image is reused
47
+ for every timeline frame. `labels` remains animated because its progress bar
48
+ reads `--fy-progress`; making it static would freeze the bar.
49
+
50
+ Preview composites with Chromium `mix-blend-mode`; production uses FFmpeg's
51
+ `blend` filter plus an alpha mask. The preview stage stacks by track order and
52
+ is isolated from the preview chrome. Small scaling, alpha, and color differences
53
+ between preview and the final encode are expected.
54
+
55
+ ## Files
56
+
57
+ ```text
58
+ examples/blend/
59
+ compositions/backdrop.html opaque base composition
60
+ compositions/aurora.html transparent screen layer
61
+ compositions/labels.html transparent mode list and progress layer
62
+ timelines/blend.timeline.json
63
+ assets/ink.mp4 procedural 12-second source clip
64
+ scripts/make-ink.sh regenerate assets/ink.mp4
65
+ video.config.js
66
+ ```
67
+
68
+ The timeline lives in `timelines/blend.timeline.json`; the project format and
69
+ entries are fixed in `video.config.js`. `backdrop.html` is a static composition
70
+ that omits all dimensions and time metadata, so it inherits the project's
71
+ 1920×1080 size. `aurora.html` is a static composition that declares its
72
+ dimensions but no time metadata. `labels.html` is an animated composition and
73
+ keeps its `fps` and `duration-in-frames`.
74
+
75
+ ## Commands
76
+
77
+ From the repository root:
78
+
79
+ ```sh
80
+ pnpm build
81
+ node dist/cli.js check blend-timeline --project examples/blend
82
+ node dist/cli.js still blend-timeline --frame 15,45,75,105,135,165,195,225,255,285,315,345 --project examples/blend --out blend-stills
83
+ node dist/cli.js still blend-timeline --frame 285 --project examples/blend --out blend-soft-light.png
84
+ node dist/cli.js render blend-timeline --project examples/blend
85
+ node dist/cli.js dev --project examples/blend
86
+ ```
87
+
88
+ The batch still captures one representative frame per mode into `blend-stills/`
89
+ using the same clip capture and composite path as the render. `render` writes
90
+ `out/blend-timeline.mp4` inside the project by default; use `--out <file.mp4>`
91
+ to choose another path. `dev` lists the compositions and the timeline in the
92
+ preview.
93
+
94
+ ## Source clip
95
+
96
+ `assets/ink.mp4` is a 12-second, 1280×720, 30 fps rotating gradient with a
97
+ silent AAC track, generated by FFmpeg. Regenerate it with:
98
+
99
+ ```sh
100
+ bash examples/blend/scripts/make-ink.sh
101
+ ```
102
+
103
+ Pass an output path as the first argument to write elsewhere. Replace
104
+ `assets/ink.mp4` with any local, seekable MP4 or WebM that is at least 12 seconds
105
+ long; remote URLs and live streams are not supported. If you use a different
106
+ length, update the clip durations and source in-points in the timeline.
Binary file
@@ -0,0 +1,55 @@
1
+ <style>
2
+ html,
3
+ body,
4
+ fy-composition {
5
+ margin: 0;
6
+ width: 100%;
7
+ height: 100%;
8
+ background: transparent;
9
+ }
10
+ fy-composition {
11
+ display: block;
12
+ overflow: hidden;
13
+ }
14
+ .scene {
15
+ position: relative;
16
+ width: 100%;
17
+ height: 100%;
18
+ overflow: hidden;
19
+ isolation: isolate;
20
+ }
21
+ .blob {
22
+ position: absolute;
23
+ border-radius: 50%;
24
+ filter: blur(78px);
25
+ opacity: 0.9;
26
+ }
27
+ .pink {
28
+ left: 6%;
29
+ top: -18%;
30
+ width: 980px;
31
+ height: 980px;
32
+ background: radial-gradient(circle, rgba(255, 64, 164, 0.92), rgba(255, 64, 164, 0) 68%);
33
+ }
34
+ .blue {
35
+ right: -12%;
36
+ top: 4%;
37
+ width: 1180px;
38
+ height: 1180px;
39
+ background: radial-gradient(circle, rgba(46, 146, 255, 0.88), rgba(46, 146, 255, 0) 68%);
40
+ }
41
+ .amber {
42
+ left: 30%;
43
+ bottom: -30%;
44
+ width: 900px;
45
+ height: 900px;
46
+ background: radial-gradient(circle, rgba(255, 186, 72, 0.7), rgba(255, 186, 72, 0) 70%);
47
+ }
48
+ </style>
49
+ <fy-composition width="1920" height="1080">
50
+ <div class="scene">
51
+ <div class="blob pink"></div>
52
+ <div class="blob blue"></div>
53
+ <div class="blob amber"></div>
54
+ </div>
55
+ </fy-composition>
@@ -0,0 +1,74 @@
1
+ <style>
2
+ html,
3
+ body {
4
+ margin: 0;
5
+ width: 100%;
6
+ height: 100%;
7
+ background: #05070d;
8
+ }
9
+ fy-composition {
10
+ display: block;
11
+ width: 100%;
12
+ height: 100%;
13
+ overflow: hidden;
14
+ }
15
+ .scene {
16
+ position: relative;
17
+ width: 100%;
18
+ height: 100%;
19
+ overflow: hidden;
20
+ background:
21
+ radial-gradient(1200px 760px at 72% 34%, rgba(42, 104, 220, 0.5), transparent 62%),
22
+ radial-gradient(860px 620px at 18% 82%, rgba(255, 76, 140, 0.14), transparent 64%),
23
+ linear-gradient(145deg, #060a12 0%, #0b1424 52%, #05070d 100%);
24
+ }
25
+ .grid {
26
+ position: absolute;
27
+ inset: -1px;
28
+ background-image:
29
+ linear-gradient(rgba(150, 190, 255, 0.075) 1px, transparent 1px),
30
+ linear-gradient(90deg, rgba(150, 190, 255, 0.075) 1px, transparent 1px);
31
+ background-size: 72px 72px;
32
+ }
33
+ .fade {
34
+ position: absolute;
35
+ inset: 0;
36
+ background:
37
+ radial-gradient(ellipse at 58% 38%, transparent 18%, rgba(5, 7, 13, 0.55) 62%, rgba(5, 7, 13, 0.92) 100%),
38
+ linear-gradient(90deg, rgba(5, 7, 13, 0.5), transparent 38%, transparent 74%, rgba(5, 7, 13, 0.55));
39
+ }
40
+ .ring {
41
+ position: absolute;
42
+ left: 58%;
43
+ top: 44%;
44
+ width: 1060px;
45
+ height: 1060px;
46
+ border: 1px solid rgba(160, 205, 255, 0.18);
47
+ border-radius: 50%;
48
+ box-shadow:
49
+ 0 0 140px rgba(54, 118, 255, 0.16) inset,
50
+ 0 0 90px rgba(54, 118, 255, 0.08);
51
+ transform: translate(-50%, -50%);
52
+ }
53
+ .ring::before,
54
+ .ring::after {
55
+ content: "";
56
+ position: absolute;
57
+ border: 1px solid rgba(255, 118, 190, 0.13);
58
+ border-radius: 50%;
59
+ }
60
+ .ring::before {
61
+ inset: 138px;
62
+ }
63
+ .ring::after {
64
+ inset: 286px;
65
+ border-color: rgba(255, 179, 71, 0.12);
66
+ }
67
+ </style>
68
+ <fy-composition>
69
+ <div class="scene">
70
+ <div class="grid"></div>
71
+ <div class="ring"></div>
72
+ <div class="fade"></div>
73
+ </div>
74
+ </fy-composition>
@@ -0,0 +1,149 @@
1
+ <style>
2
+ html,
3
+ body,
4
+ fy-composition {
5
+ margin: 0;
6
+ width: 100%;
7
+ height: 100%;
8
+ background: transparent;
9
+ }
10
+ fy-composition {
11
+ display: block;
12
+ overflow: hidden;
13
+ }
14
+ .scene {
15
+ position: relative;
16
+ width: 100%;
17
+ height: 100%;
18
+ overflow: hidden;
19
+ color: #eef4ff;
20
+ font-family: Inter, "Helvetica Neue", ui-sans-serif, system-ui, sans-serif;
21
+ }
22
+ .panel {
23
+ position: absolute;
24
+ left: 92px;
25
+ top: 96px;
26
+ width: 920px;
27
+ padding: 44px 46px 40px;
28
+ border: 1px solid rgba(160, 205, 255, 0.24);
29
+ border-radius: 22px;
30
+ background: linear-gradient(135deg, rgba(6, 12, 24, 0.91), rgba(6, 12, 24, 0.64));
31
+ box-shadow: 0 38px 110px rgba(0, 0, 0, 0.38);
32
+ }
33
+ .kicker {
34
+ color: #7fd6ff;
35
+ font-family: ui-monospace, "SFMono-Regular", "Cascadia Code", monospace;
36
+ font-size: 13px;
37
+ font-weight: 650;
38
+ letter-spacing: 0.22em;
39
+ text-transform: uppercase;
40
+ }
41
+ h1 {
42
+ margin: 18px 0 14px;
43
+ font-size: 78px;
44
+ font-weight: 680;
45
+ letter-spacing: -0.045em;
46
+ line-height: 0.95;
47
+ }
48
+ h1 span {
49
+ color: #ffb347;
50
+ }
51
+ .subtitle {
52
+ margin: 0;
53
+ max-width: 780px;
54
+ color: #a9b8d0;
55
+ font-size: 20px;
56
+ line-height: 1.4;
57
+ }
58
+ .modes {
59
+ display: grid;
60
+ grid-template-columns: repeat(4, minmax(0, 1fr));
61
+ gap: 14px 18px;
62
+ margin-top: 28px;
63
+ }
64
+ .modes div {
65
+ padding-top: 9px;
66
+ border-top: 2px solid rgba(127, 214, 255, 0.5);
67
+ }
68
+ .modes div:nth-child(4n + 2) {
69
+ border-top-color: rgba(255, 179, 71, 0.5);
70
+ }
71
+ .modes div:nth-child(4n + 3) {
72
+ border-top-color: rgba(255, 100, 180, 0.5);
73
+ }
74
+ .modes div:nth-child(4n + 4) {
75
+ border-top-color: rgba(160, 190, 255, 0.5);
76
+ }
77
+ .modes b {
78
+ display: block;
79
+ margin-bottom: 5px;
80
+ color: #eef4ff;
81
+ font-family: ui-monospace, "SFMono-Regular", "Cascadia Code", monospace;
82
+ font-size: 15px;
83
+ font-weight: 600;
84
+ letter-spacing: -0.01em;
85
+ }
86
+ .modes span {
87
+ display: block;
88
+ color: #7f90a8;
89
+ font-family: ui-monospace, "SFMono-Regular", "Cascadia Code", monospace;
90
+ font-size: 11px;
91
+ }
92
+ .foot {
93
+ margin-top: 26px;
94
+ color: #73839a;
95
+ font-family: ui-monospace, "SFMono-Regular", "Cascadia Code", monospace;
96
+ font-size: 12px;
97
+ line-height: 1.55;
98
+ letter-spacing: 0.03em;
99
+ }
100
+ .progress {
101
+ position: absolute;
102
+ left: 142px;
103
+ bottom: 92px;
104
+ width: 820px;
105
+ height: 3px;
106
+ overflow: hidden;
107
+ border-radius: 99px;
108
+ background: rgba(220, 235, 255, 0.16);
109
+ }
110
+ .progress::after {
111
+ content: "";
112
+ display: block;
113
+ width: calc(var(--fy-progress) * 100%);
114
+ height: 100%;
115
+ border-radius: inherit;
116
+ background: linear-gradient(90deg, #7fd6ff, #ffb347);
117
+ }
118
+ </style>
119
+ <fy-composition width="1920" height="1080" fps="30" duration-in-frames="360">
120
+ <div class="scene">
121
+ <div class="panel">
122
+ <div class="kicker">Frameyard / Blend lab</div>
123
+ <h1>12 modes.<br /><span>One timeline.</span></h1>
124
+ <p class="subtitle">
125
+ A composition stays on screen while the video clip cycles through every supported CSS blend mode, one second
126
+ each.
127
+ </p>
128
+ <div class="modes">
129
+ <div><b>normal</b><span>0–1s</span></div>
130
+ <div><b>multiply</b><span>1–2s</span></div>
131
+ <div><b>screen</b><span>2–3s</span></div>
132
+ <div><b>overlay</b><span>3–4s</span></div>
133
+ <div><b>darken</b><span>4–5s</span></div>
134
+ <div><b>lighten</b><span>5–6s</span></div>
135
+ <div><b>color-dodge</b><span>6–7s</span></div>
136
+ <div><b>color-burn</b><span>7–8s</span></div>
137
+ <div><b>hard-light</b><span>8–9s</span></div>
138
+ <div><b>soft-light</b><span>9–10s</span></div>
139
+ <div><b>difference</b><span>10–11s</span></div>
140
+ <div><b>exclusion</b><span>11–12s</span></div>
141
+ </div>
142
+ <div class="foot">
143
+ v2 · composition · screen · 0–12s<br />
144
+ v3 · video · 12 modes · 1s each · Preview uses CSS; render uses FFmpeg + alpha mask
145
+ </div>
146
+ </div>
147
+ <div class="progress"></div>
148
+ </div>
149
+ </fy-composition>
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
5
+ out="${1:-$root/assets/ink.mp4}"
6
+ mkdir -p "$(dirname "$out")"
7
+
8
+ ffmpeg -y -v error \
9
+ -f lavfi \
10
+ -i "gradients=size=1280x720:rate=30:c0=0x0b1020:c1=0x1b4dff:c2=0xff2d7a:c3=0xffb347:n=4:type=spiral:speed=0.08:duration=12" \
11
+ -f lavfi \
12
+ -i "anullsrc=channel_layout=stereo:sample_rate=48000" \
13
+ -t 12 \
14
+ -map 0:v:0 \
15
+ -map 1:a:0 \
16
+ -c:v libx264 \
17
+ -preset medium \
18
+ -crf 20 \
19
+ -pix_fmt yuv420p \
20
+ -g 30 \
21
+ -c:a aac \
22
+ -b:a 96k \
23
+ -shortest \
24
+ "$out"
25
+
26
+ printf 'Wrote %s\n' "$out"
@@ -0,0 +1,155 @@
1
+ {
2
+ "version": 1,
3
+ "name": "Blend lab: every supported mode on a video clip",
4
+ "background": "#05070d",
5
+ "tracks": [
6
+ { "id": "v1", "kind": "video", "name": "Backdrop" },
7
+ { "id": "v2", "kind": "video", "name": "Aurora · screen" },
8
+ { "id": "v3", "kind": "video", "name": "Video · 12 modes, one per second" },
9
+ { "id": "v4", "kind": "video", "name": "Labels" }
10
+ ],
11
+ "clips": [
12
+ {
13
+ "id": "backdrop",
14
+ "track": "v1",
15
+ "source": { "kind": "composition", "id": "backdrop" },
16
+ "start": 0,
17
+ "duration": 360
18
+ },
19
+ {
20
+ "id": "aurora",
21
+ "track": "v2",
22
+ "source": { "kind": "composition", "id": "aurora" },
23
+ "start": 0,
24
+ "duration": 360,
25
+ "blend": "screen"
26
+ },
27
+ {
28
+ "id": "ink-normal",
29
+ "track": "v3",
30
+ "source": { "kind": "video", "src": "assets/ink.mp4" },
31
+ "start": 0,
32
+ "duration": 30,
33
+ "sourceIn": 0,
34
+ "blend": "normal",
35
+ "audio": { "muted": true }
36
+ },
37
+ {
38
+ "id": "ink-multiply",
39
+ "track": "v3",
40
+ "source": { "kind": "video", "src": "assets/ink.mp4" },
41
+ "start": 30,
42
+ "duration": 30,
43
+ "sourceIn": 30,
44
+ "blend": "multiply",
45
+ "audio": { "muted": true }
46
+ },
47
+ {
48
+ "id": "ink-screen",
49
+ "track": "v3",
50
+ "source": { "kind": "video", "src": "assets/ink.mp4" },
51
+ "start": 60,
52
+ "duration": 30,
53
+ "sourceIn": 60,
54
+ "blend": "screen",
55
+ "audio": { "muted": true }
56
+ },
57
+ {
58
+ "id": "ink-overlay",
59
+ "track": "v3",
60
+ "source": { "kind": "video", "src": "assets/ink.mp4" },
61
+ "start": 90,
62
+ "duration": 30,
63
+ "sourceIn": 90,
64
+ "blend": "overlay",
65
+ "audio": { "muted": true }
66
+ },
67
+ {
68
+ "id": "ink-darken",
69
+ "track": "v3",
70
+ "source": { "kind": "video", "src": "assets/ink.mp4" },
71
+ "start": 120,
72
+ "duration": 30,
73
+ "sourceIn": 120,
74
+ "blend": "darken",
75
+ "audio": { "muted": true }
76
+ },
77
+ {
78
+ "id": "ink-lighten",
79
+ "track": "v3",
80
+ "source": { "kind": "video", "src": "assets/ink.mp4" },
81
+ "start": 150,
82
+ "duration": 30,
83
+ "sourceIn": 150,
84
+ "blend": "lighten",
85
+ "audio": { "muted": true }
86
+ },
87
+ {
88
+ "id": "ink-color-dodge",
89
+ "track": "v3",
90
+ "source": { "kind": "video", "src": "assets/ink.mp4" },
91
+ "start": 180,
92
+ "duration": 30,
93
+ "sourceIn": 180,
94
+ "blend": "color-dodge",
95
+ "audio": { "muted": true }
96
+ },
97
+ {
98
+ "id": "ink-color-burn",
99
+ "track": "v3",
100
+ "source": { "kind": "video", "src": "assets/ink.mp4" },
101
+ "start": 210,
102
+ "duration": 30,
103
+ "sourceIn": 210,
104
+ "blend": "color-burn",
105
+ "audio": { "muted": true }
106
+ },
107
+ {
108
+ "id": "ink-hard-light",
109
+ "track": "v3",
110
+ "source": { "kind": "video", "src": "assets/ink.mp4" },
111
+ "start": 240,
112
+ "duration": 30,
113
+ "sourceIn": 240,
114
+ "blend": "hard-light",
115
+ "audio": { "muted": true }
116
+ },
117
+ {
118
+ "id": "ink-soft-light",
119
+ "track": "v3",
120
+ "source": { "kind": "video", "src": "assets/ink.mp4" },
121
+ "start": 270,
122
+ "duration": 30,
123
+ "sourceIn": 270,
124
+ "blend": "soft-light",
125
+ "audio": { "muted": true }
126
+ },
127
+ {
128
+ "id": "ink-difference",
129
+ "track": "v3",
130
+ "source": { "kind": "video", "src": "assets/ink.mp4" },
131
+ "start": 300,
132
+ "duration": 30,
133
+ "sourceIn": 300,
134
+ "blend": "difference",
135
+ "audio": { "muted": true }
136
+ },
137
+ {
138
+ "id": "ink-exclusion",
139
+ "track": "v3",
140
+ "source": { "kind": "video", "src": "assets/ink.mp4" },
141
+ "start": 330,
142
+ "duration": 30,
143
+ "sourceIn": 330,
144
+ "blend": "exclusion",
145
+ "audio": { "muted": true }
146
+ },
147
+ {
148
+ "id": "labels",
149
+ "track": "v4",
150
+ "source": { "kind": "composition", "id": "labels" },
151
+ "start": 0,
152
+ "duration": 360
153
+ }
154
+ ]
155
+ }
@@ -0,0 +1,11 @@
1
+ export default {
2
+ format: { width: 1920, height: 1080, fps: 30 },
3
+ compositions: {
4
+ backdrop: "./compositions/backdrop.html",
5
+ aurora: "./compositions/aurora.html",
6
+ labels: "./compositions/labels.html",
7
+ },
8
+ timelines: {
9
+ "blend-timeline": "./timelines/blend.timeline.json",
10
+ },
11
+ };