frameyard 0.6.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 (161) hide show
  1. package/CHANGELOG.md +106 -0
  2. package/GLOSSARY.md +40 -16
  3. package/README.md +64 -55
  4. package/dist/assets/process.js.map +1 -1
  5. package/dist/assets/provenance.js.map +1 -1
  6. package/dist/cli.js +255 -59
  7. package/dist/cli.js.map +1 -1
  8. package/dist/composition/attributes.d.ts.map +1 -1
  9. package/dist/composition/descriptor.d.ts +17 -3
  10. package/dist/composition/descriptor.d.ts.map +1 -1
  11. package/dist/composition/descriptor.js +51 -28
  12. package/dist/composition/descriptor.js.map +1 -1
  13. package/dist/composition/diagnostics.js.map +1 -1
  14. package/dist/composition/format.d.ts +12 -0
  15. package/dist/composition/format.d.ts.map +1 -0
  16. package/dist/composition/format.js +28 -0
  17. package/dist/composition/format.js.map +1 -0
  18. package/dist/composition/index.d.ts +2 -1
  19. package/dist/composition/index.d.ts.map +1 -1
  20. package/dist/composition/index.js +1 -0
  21. package/dist/composition/index.js.map +1 -1
  22. package/dist/contracts.d.ts +55 -6
  23. package/dist/contracts.d.ts.map +1 -1
  24. package/dist/contracts.js +3 -0
  25. package/dist/contracts.js.map +1 -1
  26. package/dist/doctor.d.ts.map +1 -1
  27. package/dist/doctor.js +79 -0
  28. package/dist/doctor.js.map +1 -1
  29. package/dist/errors.d.ts +1 -1
  30. package/dist/errors.d.ts.map +1 -1
  31. package/dist/errors.js.map +1 -1
  32. package/dist/html/document-adapter.d.ts +3 -3
  33. package/dist/html/document-adapter.d.ts.map +1 -1
  34. package/dist/html/document-adapter.js +1 -1
  35. package/dist/html/document-adapter.js.map +1 -1
  36. package/dist/html/index.d.ts +1 -1
  37. package/dist/html/index.d.ts.map +1 -1
  38. package/dist/html/parse.d.ts +10 -2
  39. package/dist/html/parse.d.ts.map +1 -1
  40. package/dist/html/parse.js +14 -5
  41. package/dist/html/parse.js.map +1 -1
  42. package/dist/html/validate.d.ts +12 -1
  43. package/dist/html/validate.d.ts.map +1 -1
  44. package/dist/html/validate.js +233 -61
  45. package/dist/html/validate.js.map +1 -1
  46. package/dist/index.d.ts +4 -4
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +2 -2
  49. package/dist/index.js.map +1 -1
  50. package/dist/preview/main.d.ts +2 -2
  51. package/dist/preview/main.d.ts.map +1 -1
  52. package/dist/preview/main.js +47 -19
  53. package/dist/preview/main.js.map +1 -1
  54. package/dist/preview/timeline-data.d.ts +5 -1
  55. package/dist/preview/timeline-data.d.ts.map +1 -1
  56. package/dist/preview/timeline-host.d.ts +2 -0
  57. package/dist/preview/timeline-host.d.ts.map +1 -1
  58. package/dist/preview/timeline-host.js +31 -10
  59. package/dist/preview/timeline-host.js.map +1 -1
  60. package/dist/preview/timeline-main.js +12 -7
  61. package/dist/preview/timeline-main.js.map +1 -1
  62. package/dist/project.d.ts +3 -5
  63. package/dist/project.d.ts.map +1 -1
  64. package/dist/project.js.map +1 -1
  65. package/dist/renderer/browser.d.ts +2 -2
  66. package/dist/renderer/browser.d.ts.map +1 -1
  67. package/dist/renderer/browser.js +10 -4
  68. package/dist/renderer/browser.js.map +1 -1
  69. package/dist/renderer/ffmpeg.d.ts +69 -2
  70. package/dist/renderer/ffmpeg.d.ts.map +1 -1
  71. package/dist/renderer/ffmpeg.js +381 -69
  72. package/dist/renderer/ffmpeg.js.map +1 -1
  73. package/dist/renderer/index.d.ts +66 -5
  74. package/dist/renderer/index.d.ts.map +1 -1
  75. package/dist/renderer/index.js +226 -51
  76. package/dist/renderer/index.js.map +1 -1
  77. package/dist/renderer/timeline.d.ts +41 -4
  78. package/dist/renderer/timeline.d.ts.map +1 -1
  79. package/dist/renderer/timeline.js +242 -39
  80. package/dist/renderer/timeline.js.map +1 -1
  81. package/dist/runtime/host.d.ts.map +1 -1
  82. package/dist/runtime/host.js +155 -31
  83. package/dist/runtime/host.js.map +1 -1
  84. package/dist/runtime/media.d.ts.map +1 -1
  85. package/dist/runtime/media.js +3 -6
  86. package/dist/runtime/media.js.map +1 -1
  87. package/dist/runtime/video.d.ts +13 -0
  88. package/dist/runtime/video.d.ts.map +1 -0
  89. package/dist/runtime/video.js +41 -0
  90. package/dist/runtime/video.js.map +1 -0
  91. package/dist/scaffold.d.ts.map +1 -1
  92. package/dist/scaffold.js +107 -103
  93. package/dist/scaffold.js.map +1 -1
  94. package/dist/server/composition-html.d.ts +13 -7
  95. package/dist/server/composition-html.d.ts.map +1 -1
  96. package/dist/server/composition-html.js +65 -16
  97. package/dist/server/composition-html.js.map +1 -1
  98. package/dist/server/preview-html.js +1 -1
  99. package/dist/server/server.d.ts.map +1 -1
  100. package/dist/server/server.js +26 -6
  101. package/dist/server/server.js.map +1 -1
  102. package/dist/server/timeline-preview-data.d.ts.map +1 -1
  103. package/dist/server/timeline-preview-data.js +11 -0
  104. package/dist/server/timeline-preview-data.js.map +1 -1
  105. package/dist/server/timeline-preview-html.d.ts.map +1 -1
  106. package/dist/server/timeline-preview-html.js +2 -1
  107. package/dist/server/timeline-preview-html.js.map +1 -1
  108. package/dist/timeline/plan.js.map +1 -1
  109. package/dist/timeline/resolve.d.ts +4 -3
  110. package/dist/timeline/resolve.d.ts.map +1 -1
  111. package/dist/timeline/resolve.js +14 -4
  112. package/dist/timeline/resolve.js.map +1 -1
  113. package/dist/timeline/schema.d.ts +7 -0
  114. package/dist/timeline/schema.d.ts.map +1 -1
  115. package/dist/timeline/schema.js +50 -0
  116. package/dist/timeline/schema.js.map +1 -1
  117. package/dist/transcript.js.map +1 -1
  118. package/dist/version.d.ts +1 -1
  119. package/dist/version.js +1 -1
  120. package/docs/adr/0007-make-html-documents-the-composition-unit.md +1 -1
  121. package/docs/adr/0008-share-the-composition-document-grammar.md +1 -1
  122. package/docs/adr/0011-compose-timeline-frames-in-a-live-browser-host.md +1 -1
  123. package/docs/adr/0012-render-timelines-with-segmented-lossless-clip-intermediates.md +1 -1
  124. package/docs/adr/0013-capture-bounded-multi-frame-stills-for-inspection.md +33 -0
  125. package/docs/adr/0014-compose-timeline-clips-with-css-blend-modes.md +37 -0
  126. package/docs/adr/0015-inherit-composition-format-from-the-project.md +28 -0
  127. package/docs/adr/0016-author-compositions-as-html-fragments.md +32 -0
  128. package/docs/adr/0017-render-timeless-compositions-as-stills.md +99 -0
  129. package/docs/migration-0.4.md +3 -1
  130. package/docs/migration-0.8.md +163 -0
  131. package/docs/preview-testing.md +60 -0
  132. package/docs/v0.1-design.md +52 -42
  133. package/examples/blend/README.md +106 -0
  134. package/examples/blend/assets/ink.mp4 +0 -0
  135. package/examples/blend/compositions/aurora.html +55 -0
  136. package/examples/blend/compositions/backdrop.html +74 -0
  137. package/examples/blend/compositions/labels.html +149 -0
  138. package/examples/blend/scripts/make-ink.sh +26 -0
  139. package/examples/blend/timelines/blend.timeline.json +155 -0
  140. package/examples/blend/video.config.js +11 -0
  141. package/examples/demo/compositions/demo.html +243 -251
  142. package/examples/static/README.md +17 -0
  143. package/examples/static/compositions/still.html +37 -0
  144. package/examples/static/timelines/still.timeline.json +13 -0
  145. package/examples/static/video.config.js +9 -0
  146. package/examples/video/compositions/video-mp4.html +349 -357
  147. package/examples/video/compositions/video-overlay.html +337 -345
  148. package/examples/video/compositions/video.html +349 -357
  149. package/examples/webgl/compositions/webgl.html +205 -213
  150. package/package.json +6 -3
  151. package/skills/frameyard/README.md +7 -5
  152. package/skills/frameyard/SKILL.md +17 -13
  153. package/skills/frameyard/references/common-mistakes.md +30 -6
  154. package/skills/frameyard/references/controllers.md +5 -4
  155. package/skills/frameyard/references/deterministic-authoring.md +42 -36
  156. package/skills/frameyard/references/diagnostics.md +11 -3
  157. package/skills/frameyard/references/failure-recovery.md +28 -7
  158. package/skills/frameyard/references/json-results.md +58 -7
  159. package/skills/frameyard/references/subtitles-karaoke.md +2 -2
  160. package/skills/frameyard/references/timelines.md +21 -15
  161. package/skills/frameyard/scripts/frameyard.mjs +20 -3
@@ -1,253 +1,245 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <script type="application/json" data-fy="props">
6
- {
7
- "title": "Frameyard",
8
- "subtitle": "Deterministic video, authored with the web platform.",
9
- "accent": "#b8f36b"
10
- }
11
- </script>
12
- <style>
13
- @keyframes orbit {
14
- from {
15
- transform: rotate(0deg) translateX(210px) rotate(0deg);
16
- }
17
- to {
18
- transform: rotate(360deg) translateX(210px) rotate(-360deg);
19
- }
20
- }
21
- @keyframes breathe {
22
- 0%,
23
- 100% {
24
- opacity: 0.35;
25
- transform: scale(1);
26
- }
27
- 50% {
28
- opacity: 0.7;
29
- transform: scale(1.12);
30
- }
31
- }
32
- @keyframes title-in {
33
- from {
34
- opacity: 0;
35
- transform: translateY(46px);
36
- }
37
- to {
38
- opacity: 1;
39
- transform: translateY(0);
40
- }
41
- }
42
- @keyframes subtitle-in {
43
- from {
44
- opacity: 0;
45
- transform: translateY(26px);
46
- }
47
- to {
48
- opacity: 1;
49
- transform: translateY(0);
50
- }
51
- }
52
- @keyframes scene-out {
53
- from {
54
- opacity: 1;
55
- }
56
- to {
57
- opacity: 0;
58
- }
59
- }
60
- html,
61
- body,
62
- fy-composition {
63
- background: #080a0d;
64
- }
65
- #scene {
66
- position: relative;
67
- width: 100%;
68
- height: 100%;
69
- overflow: hidden;
70
- background: #080a0d;
71
- color: #eef2f7;
72
- font-family: Inter, ui-sans-serif, system-ui, sans-serif;
73
- animation: scene-out 1s linear both;
74
- }
75
- #field {
76
- position: absolute;
77
- inset: 0;
78
- width: 100%;
79
- height: 100%;
80
- }
81
- #orb {
82
- position: absolute;
83
- top: 46%;
84
- left: 38%;
85
- width: 460px;
86
- height: 460px;
87
- margin: -230px 0 0 -230px;
88
- border-radius: 50%;
89
- background: var(--fy-prop-accent);
90
- filter: blur(110px);
91
- opacity: 0.28;
92
- animation: orbit 30s linear infinite;
93
- }
94
- #glow {
95
- position: absolute;
96
- top: 8%;
97
- right: 6%;
98
- width: 280px;
99
- height: 280px;
100
- border-radius: 50%;
101
- background: var(--fy-prop-accent);
102
- filter: blur(90px);
103
- animation: breathe 9s ease-in-out infinite;
104
- }
105
- #rail {
106
- position: absolute;
107
- top: 92px;
108
- left: 160px;
109
- right: 160px;
110
- height: 1px;
111
- background: rgba(255, 255, 255, 0.14);
112
- }
113
- #eyebrow {
114
- position: absolute;
115
- top: 64px;
116
- left: 160px;
117
- font:
118
- 600 14px/1 ui-monospace,
119
- monospace;
120
- letter-spacing: 0.28em;
121
- text-transform: uppercase;
122
- color: var(--fy-prop-accent);
123
- }
124
- #meta {
125
- position: absolute;
126
- top: 64px;
127
- right: 160px;
128
- font:
129
- 500 14px/1 ui-monospace,
130
- monospace;
131
- letter-spacing: 0.12em;
132
- color: #788595;
133
- }
134
- #copy {
135
- position: absolute;
136
- left: 160px;
137
- top: 236px;
138
- width: 1320px;
139
- }
140
- #title {
141
- margin: 0;
142
- font-size: 156px;
143
- line-height: 0.92;
144
- letter-spacing: -0.055em;
145
- font-weight: 680;
146
- opacity: 0;
147
- animation: title-in 1s cubic-bezier(0.215, 0.61, 0.355, 1) both;
148
- }
149
- #subtitle {
150
- margin: 34px 0 0;
151
- max-width: 820px;
152
- font-size: 31px;
153
- line-height: 1.45;
154
- color: #96a2b2;
155
- font-weight: 420;
156
- opacity: 0;
157
- animation: subtitle-in 1s cubic-bezier(0.215, 0.61, 0.355, 1) both;
158
- }
159
- #signal {
160
- position: absolute;
161
- left: 0;
162
- bottom: 0;
163
- width: 1920px;
164
- height: 1080px;
165
- overflow: visible;
166
- }
167
- #caption {
168
- position: absolute;
169
- left: 160px;
170
- bottom: 92px;
171
- font:
172
- 500 13px/1 ui-monospace,
173
- monospace;
174
- letter-spacing: 0.16em;
175
- color: #7e8b9b;
176
- }
177
- #caption strong {
178
- color: var(--fy-prop-accent);
179
- font-weight: 600;
180
- }
181
- #progress-track {
182
- position: absolute;
183
- left: 160px;
184
- right: 160px;
185
- bottom: 72px;
186
- height: 2px;
187
- background: rgba(255, 255, 255, 0.1);
188
- }
189
- #progress {
190
- position: absolute;
191
- inset: 0 auto 0 0;
192
- width: calc(var(--fy-progress) * 100%);
193
- background: var(--fy-prop-accent);
194
- box-shadow: 0 0 18px var(--fy-prop-accent);
195
- }
196
- #vignette {
197
- position: absolute;
198
- inset: 0;
199
- background: radial-gradient(ellipse at center, transparent 48%, rgba(0, 0, 0, 0.42) 100%);
200
- pointer-events: none;
201
- }
202
- </style>
203
- </head>
204
- <body>
205
- <fy-composition width="1920" height="1080" fps="30" duration-in-frames="900">
206
- <div id="scene" data-fy-anim-start="824" data-fy-anim-duration="70" data-fy-anim-easing="linear">
207
- <canvas id="field" width="1920" height="1080"></canvas>
208
- <div id="orb"></div>
209
- <div id="glow"></div>
210
- <div id="vignette"></div>
211
- <div id="rail"></div>
212
- <div id="eyebrow">Frameyard / Field Notes</div>
213
- <div id="meta">1920×1080 · 30 FPS · 30.00 S</div>
214
- <div id="copy">
215
- <h1
216
- id="title"
217
- data-fy-text="title"
218
- data-fy-anim-start="0"
219
- data-fy-anim-duration="52"
220
- data-fy-anim-easing="cubic-bezier(0.215, 0.61, 0.355, 1)"
221
- ></h1>
222
- <p
223
- id="subtitle"
224
- data-fy-text="subtitle"
225
- data-fy-anim-start="26"
226
- data-fy-anim-duration="62"
227
- data-fy-anim-easing="cubic-bezier(0.215, 0.61, 0.355, 1)"
228
- ></p>
229
- </div>
230
- <svg id="signal" viewBox="0 0 1920 1080" fill="none" aria-hidden="true">
231
- <path
232
- id="signal-path"
233
- stroke="var(--fy-prop-accent)"
234
- stroke-width="3"
235
- stroke-linecap="round"
236
- stroke-linejoin="round"
237
- opacity=".82"
238
- ></path>
239
- <g id="signal-bars"></g>
240
- </svg>
241
- <div id="caption">FRAME <strong id="frame">000</strong> / 899 · SEEK-SAFE CANVAS + SVG + CSS</div>
242
- <div id="progress-track"><div id="progress"></div></div>
243
- </div>
1
+ <script type="application/json" data-fy="props">
2
+ {
3
+ "title": "Frameyard",
4
+ "subtitle": "Deterministic video, authored with the web platform.",
5
+ "accent": "#b8f36b"
6
+ }
7
+ </script>
8
+ <style>
9
+ @keyframes orbit {
10
+ from {
11
+ transform: rotate(0deg) translateX(210px) rotate(0deg);
12
+ }
13
+ to {
14
+ transform: rotate(360deg) translateX(210px) rotate(-360deg);
15
+ }
16
+ }
17
+ @keyframes breathe {
18
+ 0%,
19
+ 100% {
20
+ opacity: 0.35;
21
+ transform: scale(1);
22
+ }
23
+ 50% {
24
+ opacity: 0.7;
25
+ transform: scale(1.12);
26
+ }
27
+ }
28
+ @keyframes title-in {
29
+ from {
30
+ opacity: 0;
31
+ transform: translateY(46px);
32
+ }
33
+ to {
34
+ opacity: 1;
35
+ transform: translateY(0);
36
+ }
37
+ }
38
+ @keyframes subtitle-in {
39
+ from {
40
+ opacity: 0;
41
+ transform: translateY(26px);
42
+ }
43
+ to {
44
+ opacity: 1;
45
+ transform: translateY(0);
46
+ }
47
+ }
48
+ @keyframes scene-out {
49
+ from {
50
+ opacity: 1;
51
+ }
52
+ to {
53
+ opacity: 0;
54
+ }
55
+ }
56
+ html,
57
+ body,
58
+ fy-composition {
59
+ background: #080a0d;
60
+ }
61
+ #scene {
62
+ position: relative;
63
+ width: 100%;
64
+ height: 100%;
65
+ overflow: hidden;
66
+ background: #080a0d;
67
+ color: #eef2f7;
68
+ font-family: Inter, ui-sans-serif, system-ui, sans-serif;
69
+ animation: scene-out 1s linear both;
70
+ }
71
+ #field {
72
+ position: absolute;
73
+ inset: 0;
74
+ width: 100%;
75
+ height: 100%;
76
+ }
77
+ #orb {
78
+ position: absolute;
79
+ top: 46%;
80
+ left: 38%;
81
+ width: 460px;
82
+ height: 460px;
83
+ margin: -230px 0 0 -230px;
84
+ border-radius: 50%;
85
+ background: var(--fy-prop-accent);
86
+ filter: blur(110px);
87
+ opacity: 0.28;
88
+ animation: orbit 30s linear infinite;
89
+ }
90
+ #glow {
91
+ position: absolute;
92
+ top: 8%;
93
+ right: 6%;
94
+ width: 280px;
95
+ height: 280px;
96
+ border-radius: 50%;
97
+ background: var(--fy-prop-accent);
98
+ filter: blur(90px);
99
+ animation: breathe 9s ease-in-out infinite;
100
+ }
101
+ #rail {
102
+ position: absolute;
103
+ top: 92px;
104
+ left: 160px;
105
+ right: 160px;
106
+ height: 1px;
107
+ background: rgba(255, 255, 255, 0.14);
108
+ }
109
+ #eyebrow {
110
+ position: absolute;
111
+ top: 64px;
112
+ left: 160px;
113
+ font:
114
+ 600 14px/1 ui-monospace,
115
+ monospace;
116
+ letter-spacing: 0.28em;
117
+ text-transform: uppercase;
118
+ color: var(--fy-prop-accent);
119
+ }
120
+ #meta {
121
+ position: absolute;
122
+ top: 64px;
123
+ right: 160px;
124
+ font:
125
+ 500 14px/1 ui-monospace,
126
+ monospace;
127
+ letter-spacing: 0.12em;
128
+ color: #788595;
129
+ }
130
+ #copy {
131
+ position: absolute;
132
+ left: 160px;
133
+ top: 236px;
134
+ width: 1320px;
135
+ }
136
+ #title {
137
+ margin: 0;
138
+ font-size: 156px;
139
+ line-height: 0.92;
140
+ letter-spacing: -0.055em;
141
+ font-weight: 680;
142
+ opacity: 0;
143
+ animation: title-in 1s cubic-bezier(0.215, 0.61, 0.355, 1) both;
144
+ }
145
+ #subtitle {
146
+ margin: 34px 0 0;
147
+ max-width: 820px;
148
+ font-size: 31px;
149
+ line-height: 1.45;
150
+ color: #96a2b2;
151
+ font-weight: 420;
152
+ opacity: 0;
153
+ animation: subtitle-in 1s cubic-bezier(0.215, 0.61, 0.355, 1) both;
154
+ }
155
+ #signal {
156
+ position: absolute;
157
+ left: 0;
158
+ bottom: 0;
159
+ width: 1920px;
160
+ height: 1080px;
161
+ overflow: visible;
162
+ }
163
+ #caption {
164
+ position: absolute;
165
+ left: 160px;
166
+ bottom: 92px;
167
+ font:
168
+ 500 13px/1 ui-monospace,
169
+ monospace;
170
+ letter-spacing: 0.16em;
171
+ color: #7e8b9b;
172
+ }
173
+ #caption strong {
174
+ color: var(--fy-prop-accent);
175
+ font-weight: 600;
176
+ }
177
+ #progress-track {
178
+ position: absolute;
179
+ left: 160px;
180
+ right: 160px;
181
+ bottom: 72px;
182
+ height: 2px;
183
+ background: rgba(255, 255, 255, 0.1);
184
+ }
185
+ #progress {
186
+ position: absolute;
187
+ inset: 0 auto 0 0;
188
+ width: calc(var(--fy-progress) * 100%);
189
+ background: var(--fy-prop-accent);
190
+ box-shadow: 0 0 18px var(--fy-prop-accent);
191
+ }
192
+ #vignette {
193
+ position: absolute;
194
+ inset: 0;
195
+ background: radial-gradient(ellipse at center, transparent 48%, rgba(0, 0, 0, 0.42) 100%);
196
+ pointer-events: none;
197
+ }
198
+ </style>
199
+ <fy-composition width="1920" height="1080" fps="30" duration-in-frames="900">
200
+ <div id="scene" data-fy-anim-start="824" data-fy-anim-duration="70" data-fy-anim-easing="linear">
201
+ <canvas id="field" width="1920" height="1080"></canvas>
202
+ <div id="orb"></div>
203
+ <div id="glow"></div>
204
+ <div id="vignette"></div>
205
+ <div id="rail"></div>
206
+ <div id="eyebrow">Frameyard / Field Notes</div>
207
+ <div id="meta">1920×1080 · 30 FPS · 30.00 S</div>
208
+ <div id="copy">
209
+ <h1
210
+ id="title"
211
+ data-fy-text="title"
212
+ data-fy-anim-start="0"
213
+ data-fy-anim-duration="52"
214
+ data-fy-anim-easing="cubic-bezier(0.215, 0.61, 0.355, 1)"
215
+ ></h1>
216
+ <p
217
+ id="subtitle"
218
+ data-fy-text="subtitle"
219
+ data-fy-anim-start="26"
220
+ data-fy-anim-duration="62"
221
+ data-fy-anim-easing="cubic-bezier(0.215, 0.61, 0.355, 1)"
222
+ ></p>
223
+ </div>
224
+ <svg id="signal" viewBox="0 0 1920 1080" fill="none" aria-hidden="true">
225
+ <path
226
+ id="signal-path"
227
+ stroke="var(--fy-prop-accent)"
228
+ stroke-width="3"
229
+ stroke-linecap="round"
230
+ stroke-linejoin="round"
231
+ opacity=".82"
232
+ ></path>
233
+ <g id="signal-bars"></g>
234
+ </svg>
235
+ <div id="caption">FRAME <strong id="frame">000</strong> / 899 · SEEK-SAFE CANVAS + SVG + CSS</div>
236
+ <div id="progress-track"><div id="progress"></div></div>
237
+ </div>
244
238
 
245
- <audio src="assets/chime.wav" data-fy-start="18" data-fy-volume="0.5"></audio>
246
- <audio src="assets/chime.wav" data-fy-start="300" data-fy-volume="0.38"></audio>
247
- <audio src="assets/chime.wav" data-fy-start="600" data-fy-volume="0.42"></audio>
248
- <audio src="assets/chime.wav" data-fy-start="840" data-fy-volume="0.55"></audio>
249
- </fy-composition>
239
+ <audio src="assets/chime.wav" data-fy-start="18" data-fy-volume="0.5"></audio>
240
+ <audio src="assets/chime.wav" data-fy-start="300" data-fy-volume="0.38"></audio>
241
+ <audio src="assets/chime.wav" data-fy-start="600" data-fy-volume="0.42"></audio>
242
+ <audio src="assets/chime.wav" data-fy-start="840" data-fy-volume="0.55"></audio>
243
+ </fy-composition>
250
244
 
251
- <script type="text/fy-controller" src="./demo.controller.js"></script>
252
- </body>
253
- </html>
245
+ <script type="text/fy-controller" src="./demo.controller.js"></script>
@@ -0,0 +1,17 @@
1
+ # Static composition example
2
+
3
+ `compositions/still.html` declares neither `duration-in-frames` nor `fps`, so
4
+ Frameyard treats it as a static composition. The project `format` supplies the
5
+ 1280×720 dimensions. Rendering the composition writes a single PNG; the
6
+ timeline uses the same composition as an image layer for 90 frames.
7
+
8
+ ```sh
9
+ node dist/cli.js check still --project examples/static
10
+ node dist/cli.js render still --project examples/static --out examples/static/out/still.png
11
+ node dist/cli.js check still-timeline --project examples/static
12
+ node dist/cli.js render still-timeline --project examples/static --out examples/static/out/still-timeline.mp4
13
+ ```
14
+
15
+ `render still` defaults to `out/still.png`. Static compositions render to PNG;
16
+ `--container`, `--codec`, `--encoder`, and `--concurrency` are not valid for
17
+ them. Use the timeline when you need a video, audio, or a duration.
@@ -0,0 +1,37 @@
1
+ <style>
2
+ html,
3
+ body {
4
+ margin: 0;
5
+ width: 100%;
6
+ height: 100%;
7
+ background: radial-gradient(circle at 50% 40%, #1b3b4a 0%, #08161d 70%);
8
+ }
9
+ .card {
10
+ position: absolute;
11
+ inset: 0;
12
+ display: grid;
13
+ place-items: center;
14
+ color: #b8f36b;
15
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
16
+ text-align: center;
17
+ }
18
+ .card h1 {
19
+ margin: 0;
20
+ font-size: 72px;
21
+ letter-spacing: 0.08em;
22
+ text-transform: uppercase;
23
+ }
24
+ .card p {
25
+ margin: 16px 0 0;
26
+ color: #e6f4ea;
27
+ font-size: 22px;
28
+ }
29
+ </style>
30
+ <fy-composition>
31
+ <div class="card">
32
+ <div>
33
+ <h1>Static</h1>
34
+ <p>No duration, no frame rate, one capture.</p>
35
+ </div>
36
+ </div>
37
+ </fy-composition>
@@ -0,0 +1,13 @@
1
+ {
2
+ "version": 1,
3
+ "tracks": [{ "id": "v1", "kind": "video" }],
4
+ "clips": [
5
+ {
6
+ "id": "still",
7
+ "track": "v1",
8
+ "source": { "kind": "composition", "id": "still" },
9
+ "start": 0,
10
+ "duration": 90
11
+ }
12
+ ]
13
+ }
@@ -0,0 +1,9 @@
1
+ export default {
2
+ format: { width: 1280, height: 720, fps: 30 },
3
+ compositions: {
4
+ still: "./compositions/still.html",
5
+ },
6
+ timelines: {
7
+ "still-timeline": "./timelines/still.timeline.json",
8
+ },
9
+ };