@pixerate/editor 0.253.0 → 0.254.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.
@@ -3,7 +3,7 @@
3
3
  var _chunk4XSBOGMKcjs = require('../chunk-4XSBOGMK.cjs');
4
4
 
5
5
 
6
- var _chunkQKXO6JPPcjs = require('../chunk-QKXO6JPP.cjs');
6
+ var _chunk2OQGPEHHcjs = require('../chunk-2OQGPEHH.cjs');
7
7
 
8
8
 
9
9
 
@@ -28,7 +28,7 @@ var _chunkQKXO6JPPcjs = require('../chunk-QKXO6JPP.cjs');
28
28
 
29
29
 
30
30
 
31
- var _chunkZ3BRH4JKcjs = require('../chunk-Z3BRH4JK.cjs');
31
+ var _chunk557BDWKOcjs = require('../chunk-557BDWKO.cjs');
32
32
 
33
33
 
34
34
  var _chunkPY4GWSE2cjs = require('../chunk-PY4GWSE2.cjs');
@@ -79,7 +79,16 @@ var _chunkPY4GWSE2cjs = require('../chunk-PY4GWSE2.cjs');
79
79
 
80
80
 
81
81
 
82
- var _chunkISIO63Q5cjs = require('../chunk-ISIO63Q5.cjs');
82
+
83
+
84
+
85
+
86
+
87
+
88
+
89
+
90
+
91
+ var _chunkL2JTLW6Bcjs = require('../chunk-L2JTLW6B.cjs');
83
92
  require('../chunk-WOFXZ3XU.cjs');
84
93
  require('../chunk-WKPXOGZZ.cjs');
85
94
 
@@ -87,7 +96,7 @@ require('../chunk-WKPXOGZZ.cjs');
87
96
  var _chunkDWJJI6RTcjs = require('../chunk-DWJJI6RT.cjs');
88
97
 
89
98
  // src/effects/conformance.ts
90
- var codeOf = (e) => _chunkISIO63Q5cjs.isEffectError.call(void 0, e) ? e.code : e instanceof Error ? `untyped ${e.name}: ${e.message}` : String(e);
99
+ var codeOf = (e) => _chunkL2JTLW6Bcjs.isEffectError.call(void 0, e) ? e.code : e instanceof Error ? `untyped ${e.name}: ${e.message}` : String(e);
91
100
  async function rejectsWith(code, run) {
92
101
  try {
93
102
  await run();
@@ -101,21 +110,21 @@ function checkSummary(e, issues) {
101
110
  const at = (message) => issues.push({ effectId: e.id, message });
102
111
  if (!e.id || typeof e.id !== "string") at("summary has no id");
103
112
  if (!e.name) at("summary has no name");
104
- if (!_chunkISIO63Q5cjs.EFFECT_KINDS.includes(e.kind)) at(`kind "${e.kind}" is not one of ${_chunkISIO63Q5cjs.EFFECT_KINDS.join(", ")}`);
113
+ if (!_chunkL2JTLW6Bcjs.EFFECT_KINDS.includes(e.kind)) at(`kind "${e.kind}" is not one of ${_chunkL2JTLW6Bcjs.EFFECT_KINDS.join(", ")}`);
105
114
  if (!e.category) at("summary has no category");
106
115
  if (!Array.isArray(e.uses) || !e.uses.length) at("summary has no uses");
107
- for (const u of _nullishCoalesce(e.uses, () => ( []))) if (!_chunkISIO63Q5cjs.EFFECT_USES.includes(u)) at(`use "${u}" is not one of ${_chunkISIO63Q5cjs.EFFECT_USES.join(", ")}`);
116
+ for (const u of _nullishCoalesce(e.uses, () => ( []))) if (!_chunkL2JTLW6Bcjs.EFFECT_USES.includes(u)) at(`use "${u}" is not one of ${_chunkL2JTLW6Bcjs.EFFECT_USES.join(", ")}`);
108
117
  if (typeof e.transparent !== "boolean") at("transparent is not a boolean");
109
118
  if (typeof e.loop !== "boolean") at("loop is not a boolean");
110
119
  if (e.duration !== void 0 && !(e.duration > 0)) at("duration must be a positive number of ms when present");
111
120
  if (e.backgroundOpacity !== void 0 && (typeof e.backgroundOpacity !== "string" || !e.backgroundOpacity)) at("backgroundOpacity must name a control when present");
112
- for (const a of _nullishCoalesce(e.accepts, () => ( []))) if (!_chunkISIO63Q5cjs.EFFECT_ACCEPTS.includes(a)) at(`accepts "${a}" is not one of ${_chunkISIO63Q5cjs.EFFECT_ACCEPTS.join(", ")}`);
121
+ for (const a of _nullishCoalesce(e.accepts, () => ( []))) if (!_chunkL2JTLW6Bcjs.EFFECT_ACCEPTS.includes(a)) at(`accepts "${a}" is not one of ${_chunkL2JTLW6Bcjs.EFFECT_ACCEPTS.join(", ")}`);
113
122
  if (e.kind === "camera") {
114
123
  if (_optionalChain([e, 'access', _2 => _2.uses, 'optionalAccess', _3 => _3.length]) !== 1 || e.uses[0] !== "camera") at('a camera effect must have exactly the use "camera"');
115
124
  const m = e.camera;
116
125
  if (!m) at("a camera effect needs camera: { role, durationMs }");
117
126
  else {
118
- if (!_chunkISIO63Q5cjs.CAMERA_MOVE_ROLES.includes(m.role)) at(`camera.role "${m.role}" is not one of ${_chunkISIO63Q5cjs.CAMERA_MOVE_ROLES.join(", ")}`);
127
+ if (!_chunkL2JTLW6Bcjs.CAMERA_MOVE_ROLES.includes(m.role)) at(`camera.role "${m.role}" is not one of ${_chunkL2JTLW6Bcjs.CAMERA_MOVE_ROLES.join(", ")}`);
119
128
  if (!(Number.isFinite(m.durationMs) && m.durationMs >= 0)) at("camera.durationMs must be a number of ms \u2265 0");
120
129
  if (m.cut !== void 0 && !(m.cut >= 0 && m.cut <= 1)) at("camera.cut must be 0\u20131 when present");
121
130
  if (e.duration !== void 0 && e.duration !== m.durationMs) at(`duration ${e.duration} differs from camera.durationMs ${m.durationMs}`);
@@ -124,28 +133,32 @@ function checkSummary(e, issues) {
124
133
  if (_optionalChain([e, 'access', _4 => _4.uses, 'optionalAccess', _5 => _5.includes, 'call', _6 => _6("camera")])) at('only camera effects may have the use "camera"');
125
134
  if (e.camera !== void 0) at("only camera effects may have camera");
126
135
  }
136
+ if (e.kind === "timing") {
137
+ if (_optionalChain([e, 'access', _7 => _7.uses, 'optionalAccess', _8 => _8.length]) !== 1 || e.uses[0] !== "timing") at('a timing effect must have exactly the use "timing"');
138
+ if (e.duration !== void 0) at("a timing effect has no duration: its length depends on its footage (timingLength)");
139
+ } else if (_optionalChain([e, 'access', _9 => _9.uses, 'optionalAccess', _10 => _10.includes, 'call', _11 => _11("timing")])) at('only timing effects may have the use "timing"');
127
140
  }
128
141
  function checkDescription(id, d, issues) {
129
142
  const at = (message) => issues.push({ effectId: id, message });
130
143
  if (d.id !== id) at(`describe("${id}") returned id "${d.id}"`);
131
144
  const c = d.controls;
132
145
  if (!c || c.type !== "object") at("controls is not an object schema");
133
- if (_optionalChain([c, 'optionalAccess', _7 => _7.additionalProperties]) !== false) at("controls must set additionalProperties: false");
134
- for (const [name, schema] of Object.entries(_nullishCoalesce(_optionalChain([c, 'optionalAccess', _8 => _8.properties]), () => ( {})))) {
146
+ if (_optionalChain([c, 'optionalAccess', _12 => _12.additionalProperties]) !== false) at("controls must set additionalProperties: false");
147
+ for (const [name, schema] of Object.entries(_nullishCoalesce(_optionalChain([c, 'optionalAccess', _13 => _13.properties]), () => ( {})))) {
135
148
  if (!schema.description || !String(schema.description).trim()) at(`control "${name}" has no description`);
136
149
  if (!(name in (_nullishCoalesce(d.defaults, () => ( {}))))) at(`control "${name}" has no default`);
137
150
  }
138
- for (const name of Object.keys(_nullishCoalesce(d.defaults, () => ( {})))) if (!(name in (_nullishCoalesce(_optionalChain([c, 'optionalAccess', _9 => _9.properties]), () => ( {}))))) at(`default "${name}" is not a control`);
151
+ for (const name of Object.keys(_nullishCoalesce(d.defaults, () => ( {})))) if (!(name in (_nullishCoalesce(_optionalChain([c, 'optionalAccess', _14 => _14.properties]), () => ( {}))))) at(`default "${name}" is not a control`);
139
152
  if (d.backgroundOpacity !== void 0) {
140
- const control = _optionalChain([c, 'optionalAccess', _10 => _10.properties, 'optionalAccess', _11 => _11[d.backgroundOpacity]]);
153
+ const control = _optionalChain([c, 'optionalAccess', _15 => _15.properties, 'optionalAccess', _16 => _16[d.backgroundOpacity]]);
141
154
  if (!control) at(`backgroundOpacity "${d.backgroundOpacity}" is not a control`);
142
155
  else if (control.type !== "number" || control.minimum !== 0 || control.maximum !== 1) at(`backgroundOpacity "${d.backgroundOpacity}" must be a number control from 0 to 1`);
143
156
  }
144
- const paths = _chunkISIO63Q5cjs.pathControlsOf.call(void 0, d);
145
- if (paths.length && !_optionalChain([d, 'access', _12 => _12.accepts, 'optionalAccess', _13 => _13.includes, 'call', _14 => _14("path")])) at(`controls ${paths.map((p) => `"${p}"`).join(", ")} take a path, but accepts does not list "path"`);
146
- if (!paths.length && _optionalChain([d, 'access', _15 => _15.accepts, 'optionalAccess', _16 => _16.includes, 'call', _17 => _17("path")])) at('accepts lists "path", but no control has format "svg-path"');
147
- for (const e of _chunkISIO63Q5cjs.effectValueErrors.call(void 0, d, d.defaults)) at(`default ${e.path}: ${e.message}`);
148
- for (const p of _nullishCoalesce(d.presets, () => ( []))) for (const e of _chunkISIO63Q5cjs.effectValueErrors.call(void 0, d, p.values)) at(`preset "${p.name}" ${e.path}: ${e.message}`);
157
+ const paths = _chunkL2JTLW6Bcjs.pathControlsOf.call(void 0, d);
158
+ if (paths.length && !_optionalChain([d, 'access', _17 => _17.accepts, 'optionalAccess', _18 => _18.includes, 'call', _19 => _19("path")])) at(`controls ${paths.map((p) => `"${p}"`).join(", ")} take a path, but accepts does not list "path"`);
159
+ if (!paths.length && _optionalChain([d, 'access', _20 => _20.accepts, 'optionalAccess', _21 => _21.includes, 'call', _22 => _22("path")])) at('accepts lists "path", but no control has format "svg-path"');
160
+ for (const e of _chunkL2JTLW6Bcjs.effectValueErrors.call(void 0, d, d.defaults)) at(`default ${e.path}: ${e.message}`);
161
+ for (const p of _nullishCoalesce(d.presets, () => ( []))) for (const e of _chunkL2JTLW6Bcjs.effectValueErrors.call(void 0, d, p.values)) at(`preset "${p.name}" ${e.path}: ${e.message}`);
149
162
  for (const input2 of _nullishCoalesce(d.inputs, () => ( []))) {
150
163
  if (!input2.name || !input2.description) at("every input needs a name and a description");
151
164
  if (input2.kind !== "image" && input2.kind !== "audio") at(`input "${input2.name}" has kind "${input2.kind}"`);
@@ -156,7 +169,7 @@ function checkDescription(id, d, issues) {
156
169
  }
157
170
  }
158
171
  function grey(size) {
159
- const p = _chunkISIO63Q5cjs.createEffectPixels.call(void 0, size, size);
172
+ const p = _chunkL2JTLW6Bcjs.createEffectPixels.call(void 0, size, size);
160
173
  p.data.fill(128);
161
174
  return p;
162
175
  }
@@ -167,13 +180,13 @@ async function checkRender(provider, d, size, issues) {
167
180
  try {
168
181
  renderer = await provider.createRenderer(d.id, { width: size, height: size });
169
182
  } catch (e) {
170
- if (!((d.kind === "vector" || d.kind === "camera") && codeOf(e) === "unsupported")) at(`createRenderer failed: ${codeOf(e)}`);
183
+ if (!((d.kind === "vector" || d.kind === "camera" || d.kind === "timing") && codeOf(e) === "unsupported")) at(`createRenderer failed: ${codeOf(e)}`);
171
184
  else if (!(e instanceof Error && e.message.trim())) at("createRenderer refused without saying why");
172
185
  return;
173
186
  }
174
187
  try {
175
188
  const out = await renderer.render({ time: 0, inputs });
176
- if (!_chunkISIO63Q5cjs.isEffectPixels.call(void 0, out)) at("render did not return EffectPixels");
189
+ if (!_chunkL2JTLW6Bcjs.isEffectPixels.call(void 0, out)) at("render did not return EffectPixels");
177
190
  else if (out.width !== size || out.height !== size || out.data.length !== size * size * 4) at(`render returned ${out.width}\xD7${out.height}, not ${size}\xD7${size}`);
178
191
  } catch (e) {
179
192
  at(`render failed: ${codeOf(e)}`);
@@ -203,10 +216,10 @@ async function checkCamera(provider, d, issues) {
203
216
  at("cameraView must be synchronous; it returned a Promise");
204
217
  return;
205
218
  }
206
- if (!_chunkISIO63Q5cjs.isCameraView.call(void 0, view)) at(`cameraView at u ${u} is not a CameraView (zoom > 0, finite scrollX and scrollY): ${JSON.stringify(view)}`);
219
+ if (!_chunkL2JTLW6Bcjs.isCameraView.call(void 0, view)) at(`cameraView at u ${u} is not a CameraView (zoom > 0, finite scrollX and scrollY): ${JSON.stringify(view)}`);
207
220
  else views.push(view);
208
221
  const again = provider.cameraView(d.id, ctx(u));
209
- if (_chunkISIO63Q5cjs.isCameraView.call(void 0, view) && !sameView(view, again)) at(`cameraView is not pure: two calls at u ${u} gave different views`);
222
+ if (_chunkL2JTLW6Bcjs.isCameraView.call(void 0, view) && !sameView(view, again)) at(`cameraView is not pure: two calls at u ${u} gave different views`);
210
223
  } catch (e) {
211
224
  at(`cameraView at u ${u} failed: ${codeOf(e)}`);
212
225
  }
@@ -216,10 +229,10 @@ async function checkCamera(provider, d, issues) {
216
229
  if (provider.sampleCameraMove && views.length === 5) {
217
230
  try {
218
231
  const sample = await provider.sampleCameraMove(d.id, { from: WIDE, to, ms, stage: STAGE, fps: 10 });
219
- const keys = _optionalChain([sample, 'optionalAccess', _18 => _18.keys]);
232
+ const keys = _optionalChain([sample, 'optionalAccess', _23 => _23.keys]);
220
233
  if (!Array.isArray(keys) || keys.length < 2) at("sampleCameraMove returned fewer than two keys");
221
234
  else {
222
- if (keys.some((k, i) => !_chunkISIO63Q5cjs.isCameraView.call(void 0, k.view) || !Number.isFinite(k.t) || i > 0 && k.t < keys[i - 1].t)) at("sampleCameraMove keys must be CameraViews in time order");
235
+ if (keys.some((k, i) => !_chunkL2JTLW6Bcjs.isCameraView.call(void 0, k.view) || !Number.isFinite(k.t) || i > 0 && k.t < keys[i - 1].t)) at("sampleCameraMove keys must be CameraViews in time order");
223
236
  if (keys[0].t !== 0 || keys[keys.length - 1].t !== ms) at(`sampleCameraMove keys must run from 0 to ${ms} ms, got ${keys[0].t} to ${keys[keys.length - 1].t}`);
224
237
  else if (!near(keys[0].view, views[0]) || !near(keys[keys.length - 1].view, views[4])) at("sampleCameraMove disagrees with cameraView at the start or end of the move");
225
238
  if (camera.cut !== void 0 && sample.cut === void 0) at("sampleCameraMove gave no cut for a move that cuts");
@@ -229,20 +242,65 @@ async function checkCamera(provider, d, issues) {
229
242
  }
230
243
  }
231
244
  }
245
+ var FOOTAGE = [{ footage: 3e3 }, { footage: 1e3, fps: 24 }];
246
+ var isPromise = (v) => !!v && typeof v.then === "function";
247
+ async function checkTiming(provider, d, issues) {
248
+ const at = (message) => issues.push({ effectId: d.id, message });
249
+ if (d.inputs.length) at("a timing effect takes no inputs: the host decodes its footage");
250
+ for (const probe of FOOTAGE) {
251
+ const fpsText = probe.fps ? ` at ${probe.fps} fps` : "";
252
+ let length;
253
+ try {
254
+ length = provider.timingLength(d.id, probe.footage);
255
+ if (isPromise(length)) return at("timingLength must be synchronous; it returned a Promise");
256
+ if (!(typeof length === "number" && Number.isFinite(length) && length > 0)) {
257
+ at(`timingLength for ${probe.footage} ms of footage is ${String(length)}; it must be a number of ms > 0`);
258
+ continue;
259
+ }
260
+ if (provider.timingLength(d.id, probe.footage) !== length) at(`timingLength is not pure: two calls for ${probe.footage} ms gave different lengths`);
261
+ } catch (e) {
262
+ at(`timingLength for ${probe.footage} ms of footage failed: ${codeOf(e)}`);
263
+ continue;
264
+ }
265
+ for (const share of [0, 0.25, 0.5, 0.75, 1]) {
266
+ const request2 = { time: share * length, ...probe };
267
+ try {
268
+ const sample = provider.timingSample(d.id, request2);
269
+ if (isPromise(sample)) return at("timingSample must be synchronous; it returned a Promise");
270
+ const problems = _chunkL2JTLW6Bcjs.timingSampleProblems.call(void 0, sample, request2);
271
+ for (const p of problems) at(`timingSample at ${+request2.time.toFixed(3)} ms of ${probe.footage} ms footage${fpsText}: ${p}`);
272
+ if (!problems.length && JSON.stringify(provider.timingSample(d.id, request2)) !== JSON.stringify(sample)) at(`timingSample is not pure: two calls at ${+request2.time.toFixed(3)} ms gave different samples`);
273
+ } catch (e) {
274
+ at(`timingSample at ${+request2.time.toFixed(3)} ms of ${probe.footage} ms footage${fpsText} failed: ${codeOf(e)}`);
275
+ }
276
+ }
277
+ }
278
+ const request = { time: 0, footage: 1e3 };
279
+ const badLength = await rejectsWith("invalid_values", () => provider.timingLength(d.id, 1e3, { __not_a_control__: 1 }));
280
+ if (badLength) at(`timingLength with an unknown control ${badLength}`);
281
+ const badSample = await rejectsWith("invalid_values", () => provider.timingSample(d.id, request, { __not_a_control__: 1 }));
282
+ if (badSample) at(`timingSample with an unknown control ${badSample}`);
283
+ const noFootage = await rejectsWith("unsupported", () => provider.timingLength(d.id, 0));
284
+ if (noFootage) at(`timingLength of 0 ms of footage ${noFootage}`);
285
+ const badFps = await rejectsWith("unsupported", () => provider.timingSample(d.id, { ...request, fps: 0 }));
286
+ if (badFps) at(`timingSample at 0 fps ${badFps}`);
287
+ const badTime = await rejectsWith("unsupported", () => provider.timingSample(d.id, { ...request, time: Number.NaN }));
288
+ if (badTime) at(`timingSample at time NaN ${badTime}`);
289
+ }
232
290
  var wrongValue = (slot) => slot.type === "number" ? "not a number" : slot.type === "text" ? 42 : slot.type === "color" ? "blue" : 42;
233
291
  function checkSlot(templateId, slot, issues) {
234
- const at = (message) => issues.push({ templateId, message: `slot ${JSON.stringify(_optionalChain([slot, 'optionalAccess', _19 => _19.name]))}: ${message}` });
292
+ const at = (message) => issues.push({ templateId, message: `slot ${JSON.stringify(_optionalChain([slot, 'optionalAccess', _24 => _24.name]))}: ${message}` });
235
293
  if (!slot || typeof slot.name !== "string" || !/^[A-Za-z][\w-]*$/.test(slot.name)) return at('needs a name of letters, digits, "-" and "_", starting with a letter');
236
- if (!_chunkISIO63Q5cjs.EFFECT_TEMPLATE_SLOT_TYPES.includes(slot.type)) return at(`type "${slot.type}" is not one of ${_chunkISIO63Q5cjs.EFFECT_TEMPLATE_SLOT_TYPES.join(", ")}`);
294
+ if (!_chunkL2JTLW6Bcjs.EFFECT_TEMPLATE_SLOT_TYPES.includes(slot.type)) return at(`type "${slot.type}" is not one of ${_chunkL2JTLW6Bcjs.EFFECT_TEMPLATE_SLOT_TYPES.join(", ")}`);
237
295
  if (typeof slot.label !== "string" || !slot.label) at("needs a label");
238
- if (_chunkZ3BRH4JKcjs.isSubjectTemplateSlot.call(void 0, slot)) {
296
+ if (_chunk557BDWKOcjs.isSubjectTemplateSlot.call(void 0, slot)) {
239
297
  if (typeof slot.hasDefault !== "boolean") at("a subject slot needs hasDefault (a boolean)");
240
298
  if ("default" in slot) at("a subject slot describes hasDefault, not its default");
241
299
  return;
242
300
  }
243
301
  const fallback = slot.default;
244
302
  if (fallback === void 0) return at("needs a default");
245
- const problem = _chunkZ3BRH4JKcjs.templateValueProblem.call(void 0, slot, fallback);
303
+ const problem = _chunk557BDWKOcjs.templateValueProblem.call(void 0, slot, fallback);
246
304
  if (problem) at(`its default does not fit: ${problem}`);
247
305
  if (slot.type === "number" && slot.min !== void 0 && slot.max !== void 0 && slot.min > slot.max) at("min is above max");
248
306
  }
@@ -276,8 +334,8 @@ async function checkTemplates(provider, list, issues) {
276
334
  slots = d.slots;
277
335
  const names = /* @__PURE__ */ new Set();
278
336
  for (const slot of slots) {
279
- if (names.has(_optionalChain([slot, 'optionalAccess', _20 => _20.name]))) at(`slot "${slot.name}" is declared twice`);
280
- names.add(_optionalChain([slot, 'optionalAccess', _21 => _21.name]));
337
+ if (names.has(_optionalChain([slot, 'optionalAccess', _25 => _25.name]))) at(`slot "${slot.name}" is declared twice`);
338
+ names.add(_optionalChain([slot, 'optionalAccess', _26 => _26.name]));
281
339
  checkSlot(id, slot, issues);
282
340
  }
283
341
  } catch (e) {
@@ -288,11 +346,11 @@ async function checkTemplates(provider, list, issues) {
288
346
  const result = await provider.instantiateTemplate(id);
289
347
  if (!result.ok) at(`instantiateTemplate with the defaults failed: ${result.errors.join(" ")}`);
290
348
  else {
291
- for (const p of _chunkZ3BRH4JKcjs.checkEffectSequence.call(void 0, result.sequence, list)) at(`with the defaults, ${p}`);
292
- if (_optionalChain([result, 'access', _22 => _22.sequence, 'optionalAccess', _23 => _23.shots, 'optionalAccess', _24 => _24.length]) !== summary.shots) at(`listTemplates says ${summary.shots} shots; the sequence has ${_optionalChain([result, 'access', _25 => _25.sequence, 'optionalAccess', _26 => _26.shots, 'optionalAccess', _27 => _27.length])}`);
349
+ for (const p of _chunk557BDWKOcjs.checkEffectSequence.call(void 0, result.sequence, list)) at(`with the defaults, ${p}`);
350
+ if (_optionalChain([result, 'access', _27 => _27.sequence, 'optionalAccess', _28 => _28.shots, 'optionalAccess', _29 => _29.length]) !== summary.shots) at(`listTemplates says ${summary.shots} shots; the sequence has ${_optionalChain([result, 'access', _30 => _30.sequence, 'optionalAccess', _31 => _31.shots, 'optionalAccess', _32 => _32.length])}`);
293
351
  if (!Array.isArray(result.openSlots) || !Array.isArray(result.notes)) at("instantiateTemplate needs openSlots and notes lists");
294
352
  else {
295
- const open = Array.isArray(_optionalChain([result, 'access', _28 => _28.sequence, 'optionalAccess', _29 => _29.shots])) ? _chunkZ3BRH4JKcjs.effectSequenceSlots.call(void 0, result.sequence) : [];
353
+ const open = Array.isArray(_optionalChain([result, 'access', _33 => _33.sequence, 'optionalAccess', _34 => _34.shots])) ? _chunk557BDWKOcjs.effectSequenceSlots.call(void 0, result.sequence) : [];
296
354
  if (open.some((s) => !result.openSlots.includes(s))) at(`openSlots ${JSON.stringify(result.openSlots)} misses slots the sequence leaves open (${open.join(", ")})`);
297
355
  }
298
356
  }
@@ -316,20 +374,22 @@ async function checkEffectProvider(provider, options = {}) {
316
374
  if (!provider.id) top("provider has no id");
317
375
  const caps = provider.capabilities;
318
376
  for (const k of ["supportsWorker", "supportsFloat", "supportsMask", "supportsHostImages", "supportsVector"]) {
319
- if (typeof _optionalChain([caps, 'optionalAccess', _30 => _30[k]]) !== "boolean") top(`capabilities.${k} is not a boolean`);
377
+ if (typeof _optionalChain([caps, 'optionalAccess', _35 => _35[k]]) !== "boolean") top(`capabilities.${k} is not a boolean`);
320
378
  }
321
- if (_optionalChain([caps, 'optionalAccess', _31 => _31.supportsAuthoring]) !== void 0 && typeof caps.supportsAuthoring !== "boolean") top("capabilities.supportsAuthoring is not a boolean");
322
- if (_optionalChain([caps, 'optionalAccess', _32 => _32.supportsVector]) && typeof provider.applyVectorEffect !== "function") top("supportsVector is set but applyVectorEffect is missing");
323
- if (_optionalChain([caps, 'optionalAccess', _33 => _33.supportsAuthoring]) && typeof provider.openAuthoring !== "function") top("supportsAuthoring is set but openAuthoring is missing");
324
- if (_optionalChain([caps, 'optionalAccess', _34 => _34.supportsCamera]) !== void 0 && typeof caps.supportsCamera !== "boolean") top("capabilities.supportsCamera is not a boolean");
325
- if (_optionalChain([caps, 'optionalAccess', _35 => _35.supportsCamera]) && typeof provider.cameraView !== "function") top("supportsCamera is set but cameraView is missing");
379
+ if (_optionalChain([caps, 'optionalAccess', _36 => _36.supportsAuthoring]) !== void 0 && typeof caps.supportsAuthoring !== "boolean") top("capabilities.supportsAuthoring is not a boolean");
380
+ if (_optionalChain([caps, 'optionalAccess', _37 => _37.supportsVector]) && typeof provider.applyVectorEffect !== "function") top("supportsVector is set but applyVectorEffect is missing");
381
+ if (_optionalChain([caps, 'optionalAccess', _38 => _38.supportsAuthoring]) && typeof provider.openAuthoring !== "function") top("supportsAuthoring is set but openAuthoring is missing");
382
+ if (_optionalChain([caps, 'optionalAccess', _39 => _39.supportsCamera]) !== void 0 && typeof caps.supportsCamera !== "boolean") top("capabilities.supportsCamera is not a boolean");
383
+ if (_optionalChain([caps, 'optionalAccess', _40 => _40.supportsCamera]) && typeof provider.cameraView !== "function") top("supportsCamera is set but cameraView is missing");
326
384
  if (provider.sampleCameraMove && typeof provider.cameraView !== "function") top("sampleCameraMove is present but cameraView is missing");
327
- if (_optionalChain([caps, 'optionalAccess', _36 => _36.supportsTemplates]) !== void 0 && typeof caps.supportsTemplates !== "boolean") top("capabilities.supportsTemplates is not a boolean");
385
+ if (_optionalChain([caps, 'optionalAccess', _41 => _41.supportsTiming]) !== void 0 && typeof caps.supportsTiming !== "boolean") top("capabilities.supportsTiming is not a boolean");
386
+ for (const m of ["timingLength", "timingSample"]) if (_optionalChain([caps, 'optionalAccess', _42 => _42.supportsTiming]) && typeof provider[m] !== "function") top(`supportsTiming is set but ${m} is missing`);
387
+ if (_optionalChain([caps, 'optionalAccess', _43 => _43.supportsTemplates]) !== void 0 && typeof caps.supportsTemplates !== "boolean") top("capabilities.supportsTemplates is not a boolean");
328
388
  const templateMethods = ["listTemplates", "describeTemplate", "instantiateTemplate"];
329
- if (_optionalChain([caps, 'optionalAccess', _37 => _37.supportsTemplates])) {
389
+ if (_optionalChain([caps, 'optionalAccess', _44 => _44.supportsTemplates])) {
330
390
  for (const m of templateMethods) if (typeof provider[m] !== "function") top(`supportsTemplates is set but ${m} is missing`);
331
391
  }
332
- if (!_optionalChain([caps, 'optionalAccess', _38 => _38.supportsTemplates]) && templateMethods.some((m) => typeof provider[m] === "function")) top("template methods are present but capabilities.supportsTemplates is not set");
392
+ if (!_optionalChain([caps, 'optionalAccess', _45 => _45.supportsTemplates]) && templateMethods.some((m) => typeof provider[m] === "function")) top("template methods are present but capabilities.supportsTemplates is not set");
333
393
  const list = await provider.list();
334
394
  const ids = /* @__PURE__ */ new Set();
335
395
  for (const e of list) {
@@ -337,10 +397,11 @@ async function checkEffectProvider(provider, options = {}) {
337
397
  ids.add(e.id);
338
398
  checkSummary(e, issues);
339
399
  }
340
- if (!_optionalChain([caps, 'optionalAccess', _39 => _39.supportsCamera]) && list.some((e) => e.kind === "camera")) top("the catalog lists camera effects but capabilities.supportsCamera is not set");
400
+ if (!_optionalChain([caps, 'optionalAccess', _46 => _46.supportsCamera]) && list.some((e) => e.kind === "camera")) top("the catalog lists camera effects but capabilities.supportsCamera is not set");
401
+ if (!_optionalChain([caps, 'optionalAccess', _47 => _47.supportsTiming]) && list.some((e) => e.kind === "timing")) top("the catalog lists timing effects but capabilities.supportsTiming is not set");
341
402
  const all = await provider.search("");
342
403
  if (all.length !== list.length) top(`search("") returned ${all.length} effects, list() ${list.length}`);
343
- const firstUse = _optionalChain([list, 'access', _40 => _40[0], 'optionalAccess', _41 => _41.uses, 'access', _42 => _42[0]]);
404
+ const firstUse = _optionalChain([list, 'access', _48 => _48[0], 'optionalAccess', _49 => _49.uses, 'access', _50 => _50[0]]);
344
405
  if (firstUse) {
345
406
  const filtered = await provider.search("", { use: firstUse });
346
407
  if (filtered.some((e) => !e.uses.includes(firstUse))) top(`search("", { use: "${firstUse}" }) returned effects without that use`);
@@ -349,7 +410,7 @@ async function checkEffectProvider(provider, options = {}) {
349
410
  if (unknown) top(`describe of an unknown id ${unknown}`);
350
411
  const unknownRenderer = await rejectsWith("unknown_effect", () => provider.createRenderer("__no_such_effect__", { width: 4, height: 4 }));
351
412
  if (unknownRenderer) top(`createRenderer of an unknown id ${unknownRenderer}`);
352
- if (_optionalChain([caps, 'optionalAccess', _43 => _43.supportsCamera]) && provider.cameraView) {
413
+ if (_optionalChain([caps, 'optionalAccess', _51 => _51.supportsCamera]) && provider.cameraView) {
353
414
  const probe = { from: WIDE, to: CLOSE, u: 0.5, ms: 1e3, stage: STAGE };
354
415
  const unknownCamera = await rejectsWith("unknown_effect", () => provider.cameraView("__no_such_effect__", probe));
355
416
  if (unknownCamera) top(`cameraView of an unknown id ${unknownCamera}`);
@@ -357,6 +418,21 @@ async function checkEffectProvider(provider, options = {}) {
357
418
  const wrongKind = notCamera && await rejectsWith("unsupported", () => provider.cameraView(notCamera.id, probe));
358
419
  if (wrongKind) issues.push({ effectId: notCamera.id, message: `cameraView of a ${notCamera.kind} effect ${wrongKind}` });
359
420
  }
421
+ const timing = _optionalChain([caps, 'optionalAccess', _52 => _52.supportsTiming]) && provider.timingLength && provider.timingSample;
422
+ if (timing) {
423
+ const request = { time: 0, footage: 1e3 };
424
+ const unknownLength = await rejectsWith("unknown_effect", () => provider.timingLength("__no_such_effect__", 1e3));
425
+ if (unknownLength) top(`timingLength of an unknown id ${unknownLength}`);
426
+ const unknownSample = await rejectsWith("unknown_effect", () => provider.timingSample("__no_such_effect__", request));
427
+ if (unknownSample) top(`timingSample of an unknown id ${unknownSample}`);
428
+ const notTiming = list.find((e) => e.kind !== "timing");
429
+ if (notTiming) {
430
+ const wrongLength = await rejectsWith("unsupported", () => provider.timingLength(notTiming.id, 1e3));
431
+ if (wrongLength) issues.push({ effectId: notTiming.id, message: `timingLength of a ${notTiming.kind} effect ${wrongLength}` });
432
+ const wrongSample = await rejectsWith("unsupported", () => provider.timingSample(notTiming.id, request));
433
+ if (wrongSample) issues.push({ effectId: notTiming.id, message: `timingSample of a ${notTiming.kind} effect ${wrongSample}` });
434
+ }
435
+ }
360
436
  const size = _nullishCoalesce(options.size, () => ( 8));
361
437
  for (const id of _nullishCoalesce(options.ids, () => ( [...ids]))) {
362
438
  let d;
@@ -369,6 +445,7 @@ async function checkEffectProvider(provider, options = {}) {
369
445
  checkDescription(id, d, issues);
370
446
  if (options.render !== false && d.kind !== "motion") await checkRender(provider, d, size, issues);
371
447
  if (d.kind === "camera" && d.camera && caps.supportsCamera && provider.cameraView) await checkCamera(provider, d, issues);
448
+ if (d.kind === "timing" && timing) await checkTiming(provider, d, issues);
372
449
  if ((d.kind === "vector" || d.kind === "motion") && caps.supportsVector && provider.applyVectorEffect) {
373
450
  try {
374
451
  const m = await provider.applyVectorEffect(id, '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10"><rect id="r" width="10" height="10"/></svg>');
@@ -381,9 +458,9 @@ async function checkEffectProvider(provider, options = {}) {
381
458
  if (bad) issues.push({ effectId: id, message: `applyVectorEffect with an unknown control ${bad}` });
382
459
  }
383
460
  }
384
- if (_optionalChain([caps, 'optionalAccess', _44 => _44.supportsAuthoring]) && options.authoring !== false && typeof provider.openAuthoring === "function") {
461
+ if (_optionalChain([caps, 'optionalAccess', _53 => _53.supportsAuthoring]) && options.authoring !== false && typeof provider.openAuthoring === "function") {
385
462
  const targetEffect = (await Promise.all((_nullishCoalesce(options.ids, () => ( [...ids]))).map((id) => provider.describe(id)))).find(
386
- (d) => d.kind !== "motion" && d.kind !== "vector" && d.kind !== "camera"
463
+ (d) => d.kind !== "motion" && d.kind !== "vector" && d.kind !== "camera" && d.kind !== "timing"
387
464
  );
388
465
  if (targetEffect) {
389
466
  try {
@@ -432,7 +509,7 @@ async function checkEffectProvider(provider, options = {}) {
432
509
  }
433
510
  }
434
511
  }
435
- if (_optionalChain([caps, 'optionalAccess', _45 => _45.supportsTemplates]) && options.templates !== false && templateMethods.every((m) => typeof provider[m] === "function")) await checkTemplates(provider, list, issues);
512
+ if (_optionalChain([caps, 'optionalAccess', _54 => _54.supportsTemplates]) && options.templates !== false && templateMethods.every((m) => typeof provider[m] === "function")) await checkTemplates(provider, list, issues);
436
513
  return issues;
437
514
  }
438
515
 
@@ -510,7 +587,7 @@ function fill(t, values) {
510
587
  const slots = new Map(t.slots.map((s) => [s.name, s]));
511
588
  const valueOf = (name) => {
512
589
  const s = slots.get(name);
513
- return _nullishCoalesce(values[name], () => ( (_chunkZ3BRH4JKcjs.isSubjectTemplateSlot.call(void 0, s) ? s.subjectDefault : s.default)));
590
+ return _nullishCoalesce(values[name], () => ( (_chunk557BDWKOcjs.isSubjectTemplateSlot.call(void 0, s) ? s.subjectDefault : s.default)));
514
591
  };
515
592
  const walk = (v, key) => {
516
593
  if (typeof v === "string") {
@@ -533,20 +610,20 @@ function fakeTemplateMethods() {
533
610
  const byId = new Map(TEMPLATES.map((t) => [t.summary.id, t]));
534
611
  const get = (id) => {
535
612
  const t = byId.get(id);
536
- if (!t) throw new (0, _chunkISIO63Q5cjs.UnknownTemplateError)(id, "the fake provider");
613
+ if (!t) throw new (0, _chunkL2JTLW6Bcjs.UnknownTemplateError)(id, "the fake provider");
537
614
  return t;
538
615
  };
539
616
  return {
540
- listTemplates: (options) => _chunkZ3BRH4JKcjs.searchTemplateSummaries.call(void 0, TEMPLATES.map((t) => t.summary), options).map((s) => structuredClone(s)),
617
+ listTemplates: (options) => _chunk557BDWKOcjs.searchTemplateSummaries.call(void 0, TEMPLATES.map((t) => t.summary), options).map((s) => structuredClone(s)),
541
618
  describeTemplate: (id) => structuredClone(describeOf(get(id))),
542
619
  instantiateTemplate(id, values = {}, options = {}) {
543
620
  const t = get(id);
544
- const errors = _chunkZ3BRH4JKcjs.checkTemplateValues.call(void 0, describeOf(t).slots, values);
545
- if (options.name !== void 0 && (typeof options.name !== "string" || !_chunkZ3BRH4JKcjs.EFFECT_SEQUENCE_NAME.test(options.name))) errors.push(`The sequence name is lowercase words and dashes (like "${t.summary.id.replace(/^fake\./, "")}").`);
621
+ const errors = _chunk557BDWKOcjs.checkTemplateValues.call(void 0, describeOf(t).slots, values);
622
+ if (options.name !== void 0 && (typeof options.name !== "string" || !_chunk557BDWKOcjs.EFFECT_SEQUENCE_NAME.test(options.name))) errors.push(`The sequence name is lowercase words and dashes (like "${t.summary.id.replace(/^fake\./, "")}").`);
546
623
  if (errors.length) return { ok: false, errors };
547
624
  const sequence = fill(t, values);
548
625
  if (options.name) sequence.name = options.name;
549
- return { ok: true, sequence, openSlots: _chunkZ3BRH4JKcjs.effectSequenceSlots.call(void 0, sequence), notes: [] };
626
+ return { ok: true, sequence, openSlots: _chunk557BDWKOcjs.effectSequenceSlots.call(void 0, sequence), notes: [] };
550
627
  }
551
628
  };
552
629
  }
@@ -862,21 +939,94 @@ var CAMERA_DESCRIPTIONS = [
862
939
  inputs: []
863
940
  }
864
941
  ];
942
+ var TIMING_DESCRIPTIONS = [
943
+ {
944
+ id: "fake.speed",
945
+ name: "Speed change",
946
+ kind: "timing",
947
+ category: "timing",
948
+ uses: ["timing"],
949
+ description: "Footage played slower or faster throughout; slowed frames blend the two either side, sped-up ones average the frames they pass over.",
950
+ tags: ["retime", "slow motion", "time-lapse"],
951
+ transparent: false,
952
+ loop: false,
953
+ controls: {
954
+ type: "object",
955
+ additionalProperties: false,
956
+ properties: {
957
+ speed: { type: "number", minimum: 0.1, maximum: 8, description: "Playback speed as a multiple of real time, 0.1\u20138 (0.5 is half speed). Default 0.5." },
958
+ smooth: { type: "boolean", description: "Blend frames: in-betweens when slowed, motion blur when sped up. Default true." }
959
+ }
960
+ },
961
+ defaults: { speed: 0.5, smooth: true },
962
+ presets: [
963
+ { name: "Slow motion", values: { speed: 0.25 } },
964
+ { name: "Double speed", values: { speed: 2 } }
965
+ ],
966
+ inputs: []
967
+ },
968
+ {
969
+ id: "fake.freeze",
970
+ name: "Freeze frame",
971
+ kind: "timing",
972
+ category: "timing",
973
+ uses: ["timing"],
974
+ description: "Footage that stops on one frame, holds it, then plays on from where it stopped.",
975
+ tags: ["retime", "freeze", "hold"],
976
+ transparent: false,
977
+ loop: false,
978
+ controls: {
979
+ type: "object",
980
+ additionalProperties: false,
981
+ properties: {
982
+ at: { type: "number", minimum: 0, maximum: 1, description: "Where it freezes, as a share of the footage, 0\u20131. Default 0.5." },
983
+ hold: { type: "number", minimum: 0, maximum: 1e4, description: "How long it holds (ms). Default 1000." }
984
+ }
985
+ },
986
+ defaults: { at: 0.5, hold: 1e3 },
987
+ presets: [{ name: "Opening still", values: { at: 0, hold: 2e3 } }],
988
+ inputs: []
989
+ },
990
+ {
991
+ id: "fake.echo",
992
+ name: "Frame echo",
993
+ kind: "timing",
994
+ category: "timing",
995
+ uses: ["timing"],
996
+ description: "Each frame with fading copies of the frames just before it, so moving things leave a trail.",
997
+ tags: ["retime", "echo", "trail"],
998
+ transparent: false,
999
+ loop: false,
1000
+ controls: {
1001
+ type: "object",
1002
+ additionalProperties: false,
1003
+ properties: {
1004
+ echoes: { type: "integer", minimum: 1, maximum: 8, description: "Copies of earlier frames, 1\u20138. Default 3." },
1005
+ spacing: { type: "number", minimum: 10, maximum: 500, description: "Footage time between copies (ms). Default 100." },
1006
+ decay: { type: "number", minimum: 0.1, maximum: 0.95, description: "Each copy's weight as a share of the one after it, 0.1\u20130.95. Default 0.5." },
1007
+ lighten: { type: "boolean", description: "Keep the brightest of the copies (light trails) instead of averaging them. Default false." }
1008
+ }
1009
+ },
1010
+ defaults: { echoes: 3, spacing: 100, decay: 0.5, lighten: false },
1011
+ presets: [{ name: "Light trails", values: { echoes: 6, spacing: 50, decay: 0.8, lighten: true } }],
1012
+ inputs: []
1013
+ }
1014
+ ];
865
1015
  var summaryOf = ({ controls: _c, defaults: _d, presets: _p, inputs: _i, ...summary }) => summary;
866
1016
  var hexToRgb = (hex) => [1, 3, 5].map((i) => parseInt(hex.slice(i, i + 2), 16));
867
1017
  var smooth = (t) => t * t * (3 - 2 * t);
868
1018
  var clamp01 = (v) => v < 0 ? 0 : v > 1 ? 1 : v;
869
1019
  function input(request, name, id, width, height) {
870
- const src = _optionalChain([request, 'access', _46 => _46.inputs, 'optionalAccess', _47 => _47[name]]);
871
- if (!src) throw new (0, _chunkISIO63Q5cjs.EffectUnsupportedError)(`Effect "${id}" needs an input named "${name}".`, id);
872
- if (!_chunkISIO63Q5cjs.isEffectPixels.call(void 0, src)) throw new (0, _chunkISIO63Q5cjs.EffectUnsupportedError)(`The fake provider only takes EffectPixels inputs ("${name}").`, id);
1020
+ const src = _optionalChain([request, 'access', _55 => _55.inputs, 'optionalAccess', _56 => _56[name]]);
1021
+ if (!src) throw new (0, _chunkL2JTLW6Bcjs.EffectUnsupportedError)(`Effect "${id}" needs an input named "${name}".`, id);
1022
+ if (!_chunkL2JTLW6Bcjs.isEffectPixels.call(void 0, src)) throw new (0, _chunkL2JTLW6Bcjs.EffectUnsupportedError)(`The fake provider only takes EffectPixels inputs ("${name}").`, id);
873
1023
  if (src.width !== width || src.height !== height) {
874
- throw new (0, _chunkISIO63Q5cjs.EffectUnsupportedError)(`Input "${name}" is ${src.width}\xD7${src.height}; the renderer is ${width}\xD7${height}.`, id);
1024
+ throw new (0, _chunkL2JTLW6Bcjs.EffectUnsupportedError)(`Input "${name}" is ${src.width}\xD7${src.height}; the renderer is ${width}\xD7${height}.`, id);
875
1025
  }
876
1026
  return src;
877
1027
  }
878
1028
  function renderPixels(d, v, request, width, height) {
879
- const out = _chunkISIO63Q5cjs.createEffectPixels.call(void 0, width, height);
1029
+ const out = _chunkL2JTLW6Bcjs.createEffectPixels.call(void 0, width, height);
880
1030
  const o = out.data;
881
1031
  switch (d.id) {
882
1032
  case "fake.invert": {
@@ -965,7 +1115,7 @@ function renderPixels(d, v, request, width, height) {
965
1115
  break;
966
1116
  }
967
1117
  default:
968
- throw new (0, _chunkISIO63Q5cjs.EffectUnsupportedError)(`"${d.id}" is a ${d.kind} effect; use applyVectorEffect.`, d.id);
1118
+ throw new (0, _chunkL2JTLW6Bcjs.EffectUnsupportedError)(`"${d.id}" is a ${d.kind} effect; use applyVectorEffect.`, d.id);
969
1119
  }
970
1120
  return out;
971
1121
  }
@@ -995,22 +1145,69 @@ function cameraViewOf(d, ctx, v) {
995
1145
  case "fake.drift":
996
1146
  return viewAt(x0, y0, from.zoom * lerp(1, v.scale, smooth(u)), ctx);
997
1147
  default:
998
- throw new (0, _chunkISIO63Q5cjs.EffectUnsupportedError)(`"${d.id}" is a ${d.kind} effect, not a camera move.`, d.id);
1148
+ throw new (0, _chunkL2JTLW6Bcjs.EffectUnsupportedError)(`"${d.id}" is a ${d.kind} effect, not a camera move.`, d.id);
1149
+ }
1150
+ }
1151
+ function timingLengthOf(d, footage, v) {
1152
+ switch (d.id) {
1153
+ case "fake.speed":
1154
+ return footage / v.speed;
1155
+ case "fake.freeze":
1156
+ return footage + v.hold;
1157
+ case "fake.echo":
1158
+ return footage;
1159
+ default:
1160
+ throw new (0, _chunkL2JTLW6Bcjs.EffectUnsupportedError)(`"${d.id}" is a ${d.kind} effect, not a timing effect.`, d.id);
1161
+ }
1162
+ }
1163
+ function timingFramesOf(d, request, v) {
1164
+ const { time, fps } = request;
1165
+ const frameMs = 1e3 / fps;
1166
+ switch (d.id) {
1167
+ case "fake.speed": {
1168
+ const speed = v.speed;
1169
+ const s = time * speed;
1170
+ if (!v.smooth) return { frames: [{ time: s, weight: 1 }] };
1171
+ if (speed <= 1) {
1172
+ const i = s / frameMs;
1173
+ const f = Math.floor(i + 1e-6);
1174
+ const frac = Math.max(0, i - f);
1175
+ return { frames: [{ time: f * frameMs, weight: 1 - frac }, { time: (f + 1) * frameMs, weight: frac }] };
1176
+ }
1177
+ const n = Math.ceil(speed);
1178
+ return { frames: Array.from({ length: n }, (_, k) => ({ time: s + k * speed * frameMs / n, weight: 1 })) };
1179
+ }
1180
+ case "fake.freeze": {
1181
+ const at = Math.floor(v.at * request.footage / frameMs + 1e-6) * frameMs;
1182
+ const hold = v.hold;
1183
+ return { frames: [{ time: time < at ? time : time < at + hold ? at : time - hold, weight: 1 }] };
1184
+ }
1185
+ case "fake.echo": {
1186
+ const frames = [];
1187
+ for (let k = 0; k <= v.echoes; k++) {
1188
+ const t = time - k * v.spacing;
1189
+ if (t < 0) break;
1190
+ frames.push({ time: t, weight: Math.pow(v.decay, k) });
1191
+ }
1192
+ return { frames, lighten: v.lighten };
1193
+ }
1194
+ default:
1195
+ throw new (0, _chunkL2JTLW6Bcjs.EffectUnsupportedError)(`"${d.id}" is a ${d.kind} effect, not a timing effect.`, d.id);
999
1196
  }
1000
1197
  }
1001
1198
  function toFloat(p) {
1002
1199
  const f = new Float32Array(p.data.length);
1003
1200
  for (let i = 0; i < f.length; i += 4) {
1004
- f[i] = _chunkISIO63Q5cjs.srgbToLinear.call(void 0, p.data[i] / 255);
1005
- f[i + 1] = _chunkISIO63Q5cjs.srgbToLinear.call(void 0, p.data[i + 1] / 255);
1006
- f[i + 2] = _chunkISIO63Q5cjs.srgbToLinear.call(void 0, p.data[i + 2] / 255);
1201
+ f[i] = _chunkL2JTLW6Bcjs.srgbToLinear.call(void 0, p.data[i] / 255);
1202
+ f[i + 1] = _chunkL2JTLW6Bcjs.srgbToLinear.call(void 0, p.data[i + 1] / 255);
1203
+ f[i + 2] = _chunkL2JTLW6Bcjs.srgbToLinear.call(void 0, p.data[i + 2] / 255);
1007
1204
  f[i + 3] = p.data[i + 3] / 255;
1008
1205
  }
1009
- return _chunkISIO63Q5cjs.encodeEffectFloat.call(void 0, { ...p, float: f });
1206
+ return _chunkL2JTLW6Bcjs.encodeEffectFloat.call(void 0, { ...p, float: f });
1010
1207
  }
1011
1208
  function maskResult(out, mask, source, id) {
1012
- if (!_chunkISIO63Q5cjs.isEffectPixels.call(void 0, mask) || mask.width !== out.width || mask.height !== out.height) {
1013
- throw new (0, _chunkISIO63Q5cjs.EffectUnsupportedError)("The mask must be EffectPixels the size of the renderer.", id);
1209
+ if (!_chunkL2JTLW6Bcjs.isEffectPixels.call(void 0, mask) || mask.width !== out.width || mask.height !== out.height) {
1210
+ throw new (0, _chunkL2JTLW6Bcjs.EffectUnsupportedError)("The mask must be EffectPixels the size of the renderer.", id);
1014
1211
  }
1015
1212
  const o = out.data;
1016
1213
  for (let i = 0; i < o.length; i += 4) {
@@ -1029,40 +1226,61 @@ function createFakeEffectProvider(options = {}) {
1029
1226
  supportsVector: true,
1030
1227
  supportsAuthoring,
1031
1228
  ...options.camera ? { supportsCamera: true } : {},
1229
+ ...options.timing ? { supportsTiming: true } : {},
1032
1230
  ...options.templates ? { supportsTemplates: true } : {},
1033
1231
  maxSize: 8192,
1034
1232
  ...options.capabilities
1035
1233
  };
1036
- const all = options.camera ? [...DESCRIPTIONS, ...CAMERA_DESCRIPTIONS] : DESCRIPTIONS;
1234
+ const all = [...DESCRIPTIONS, ...options.camera ? CAMERA_DESCRIPTIONS : [], ...options.timing ? TIMING_DESCRIPTIONS : []];
1037
1235
  const byId = new Map(all.map((d) => [d.id, d]));
1038
1236
  const get = (id) => {
1039
1237
  const d = byId.get(id);
1040
- if (!d) throw new (0, _chunkISIO63Q5cjs.UnknownEffectError)(id, "the fake provider");
1238
+ if (!d) throw new (0, _chunkL2JTLW6Bcjs.UnknownEffectError)(id, "the fake provider");
1041
1239
  return d;
1042
1240
  };
1043
1241
  const summaries = all.map(summaryOf);
1044
1242
  const camera = (id, ctx, values) => {
1045
1243
  const d = get(id);
1046
- if (d.kind !== "camera") throw new (0, _chunkISIO63Q5cjs.EffectUnsupportedError)(`"${id}" is a ${d.kind} effect, not a camera move.`, id);
1047
- if (!(ctx.u >= 0 && ctx.u <= 1)) throw new (0, _chunkISIO63Q5cjs.EffectUnsupportedError)(`u must be 0\u20131 through the move, got ${ctx.u}.`, id);
1048
- return cameraViewOf(d, ctx, _chunkISIO63Q5cjs.resolveEffectValues.call(void 0, d, values));
1244
+ if (d.kind !== "camera") throw new (0, _chunkL2JTLW6Bcjs.EffectUnsupportedError)(`"${id}" is a ${d.kind} effect, not a camera move.`, id);
1245
+ if (!(ctx.u >= 0 && ctx.u <= 1)) throw new (0, _chunkL2JTLW6Bcjs.EffectUnsupportedError)(`u must be 0\u20131 through the move, got ${ctx.u}.`, id);
1246
+ return cameraViewOf(d, ctx, _chunkL2JTLW6Bcjs.resolveEffectValues.call(void 0, d, values));
1247
+ };
1248
+ const timingEffect = (id) => {
1249
+ const d = get(id);
1250
+ if (d.kind !== "timing") {
1251
+ const ids = TIMING_DESCRIPTIONS.map((t) => `"${t.id}"`).join(", ");
1252
+ throw new (0, _chunkL2JTLW6Bcjs.EffectUnsupportedError)(`"${id}" is a ${d.kind} effect, not a timing effect; the timing effects are ${ids}.`, id);
1253
+ }
1254
+ return d;
1255
+ };
1256
+ const timingLength = (id, footageMs, values) => {
1257
+ const d = timingEffect(id);
1258
+ _chunkL2JTLW6Bcjs.checkTimingFootage.call(void 0, footageMs, id);
1259
+ return timingLengthOf(d, footageMs, _chunkL2JTLW6Bcjs.resolveEffectValues.call(void 0, d, values));
1260
+ };
1261
+ const timingSample = (id, request, values) => {
1262
+ const d = timingEffect(id);
1263
+ const fps = _chunkL2JTLW6Bcjs.checkTimingRequest.call(void 0, request, id);
1264
+ const raw = timingFramesOf(d, { time: request.time, footage: request.footage, fps }, _chunkL2JTLW6Bcjs.resolveEffectValues.call(void 0, d, values));
1265
+ return _chunkL2JTLW6Bcjs.normaliseTimingSample.call(void 0, raw.frames, { ...request, fps }, raw.lighten ? "lighten" : "average");
1049
1266
  };
1050
1267
  const provider = {
1051
1268
  id: "fake",
1052
1269
  name: "Fake effects",
1053
1270
  version: "1",
1054
1271
  capabilities,
1055
- list: (o) => _chunkISIO63Q5cjs.searchEffectSummaries.call(void 0, summaries, "", o),
1056
- search: (q, o) => _chunkISIO63Q5cjs.searchEffectSummaries.call(void 0, summaries, q, o),
1272
+ list: (o) => _chunkL2JTLW6Bcjs.searchEffectSummaries.call(void 0, summaries, "", o),
1273
+ search: (q, o) => _chunkL2JTLW6Bcjs.searchEffectSummaries.call(void 0, summaries, q, o),
1057
1274
  describe: (id) => structuredClone(get(id)),
1058
1275
  createRenderer(id, ro) {
1059
1276
  const d = get(id);
1060
- if (d.kind === "camera") throw new (0, _chunkISIO63Q5cjs.EffectUnsupportedError)(`"${id}" is a camera move: it moves a scene's camera and draws no pixels. Use cameraView.`, id);
1061
- if (d.kind !== "shader") throw new (0, _chunkISIO63Q5cjs.EffectUnsupportedError)(`"${id}" is a ${d.kind} effect; use applyVectorEffect.`, id);
1277
+ if (d.kind === "camera") throw new (0, _chunkL2JTLW6Bcjs.EffectUnsupportedError)(`"${id}" is a camera move: it moves a scene's camera and draws no pixels. Use cameraView.`, id);
1278
+ if (d.kind === "timing") throw new (0, _chunkL2JTLW6Bcjs.EffectUnsupportedError)(`"${id}" is a timing effect: it retimes video footage and draws no pixels of its own. Use timingSample and blend the footage frames it names.`, id);
1279
+ if (d.kind !== "shader") throw new (0, _chunkL2JTLW6Bcjs.EffectUnsupportedError)(`"${id}" is a ${d.kind} effect; use applyVectorEffect.`, id);
1062
1280
  const { width, height } = ro;
1063
1281
  const depth = _nullishCoalesce(ro.depth, () => ( 8));
1064
1282
  if (!(width > 0 && height > 0) || width > capabilities.maxSize || height > capabilities.maxSize) {
1065
- throw new (0, _chunkISIO63Q5cjs.EffectUnsupportedError)(`Renderer size ${width}\xD7${height} is outside 1\u2013${capabilities.maxSize}.`, id);
1283
+ throw new (0, _chunkL2JTLW6Bcjs.EffectUnsupportedError)(`Renderer size ${width}\xD7${height} is outside 1\u2013${capabilities.maxSize}.`, id);
1066
1284
  }
1067
1285
  let disposed = false;
1068
1286
  return {
@@ -1071,16 +1289,16 @@ function createFakeEffectProvider(options = {}) {
1071
1289
  height,
1072
1290
  depth,
1073
1291
  async render(request) {
1074
- if (disposed) throw new (0, _chunkISIO63Q5cjs.EffectDisposedError)(id);
1292
+ if (disposed) throw new (0, _chunkL2JTLW6Bcjs.EffectDisposedError)(id);
1075
1293
  if (!Number.isFinite(request.time) || request.time < 0) {
1076
- throw new (0, _chunkISIO63Q5cjs.EffectUnsupportedError)(`time must be a finite number of ms \u2265 0, got ${request.time}.`, id);
1294
+ throw new (0, _chunkL2JTLW6Bcjs.EffectUnsupportedError)(`time must be a finite number of ms \u2265 0, got ${request.time}.`, id);
1077
1295
  }
1078
- const values = _chunkISIO63Q5cjs.resolveEffectValues.call(void 0, d, request.values);
1079
- _optionalChain([options, 'access', _48 => _48.onRender, 'optionalCall', _49 => _49(id, request)]);
1296
+ const values = _chunkL2JTLW6Bcjs.resolveEffectValues.call(void 0, d, request.values);
1297
+ _optionalChain([options, 'access', _57 => _57.onRender, 'optionalCall', _58 => _58(id, request)]);
1080
1298
  const out = renderPixels(d, values, request, width, height);
1081
1299
  if (request.mask) {
1082
- if (!capabilities.supportsMask) throw new (0, _chunkISIO63Q5cjs.EffectUnsupportedError)("This provider does not take masks.", id);
1083
- const source = d.uses.includes("filter") ? _optionalChain([request, 'access', _50 => _50.inputs, 'optionalAccess', _51 => _51.source]) : void 0;
1300
+ if (!capabilities.supportsMask) throw new (0, _chunkL2JTLW6Bcjs.EffectUnsupportedError)("This provider does not take masks.", id);
1301
+ const source = d.uses.includes("filter") ? _optionalChain([request, 'access', _59 => _59.inputs, 'optionalAccess', _60 => _60.source]) : void 0;
1084
1302
  maskResult(out, request.mask, source, id);
1085
1303
  }
1086
1304
  return depth > 8 && capabilities.supportsFloat ? toFloat(out) : out;
@@ -1091,14 +1309,14 @@ function createFakeEffectProvider(options = {}) {
1091
1309
  };
1092
1310
  },
1093
1311
  pathFromText(text, opts) {
1094
- if (typeof text !== "string" || !text.trim()) throw new (0, _chunkISIO63Q5cjs.EffectUnsupportedError)("There are no words to write; pass some text.");
1095
- if (_optionalChain([opts, 'optionalAccess', _52 => _52.font]) !== void 0 && opts.font !== "zig") throw new (0, _chunkISIO63Q5cjs.EffectUnsupportedError)(`The fake provider has no font "${opts.font}"; its only font is "zig".`);
1312
+ if (typeof text !== "string" || !text.trim()) throw new (0, _chunkL2JTLW6Bcjs.EffectUnsupportedError)("There are no words to write; pass some text.");
1313
+ if (_optionalChain([opts, 'optionalAccess', _61 => _61.font]) !== void 0 && opts.font !== "zig") throw new (0, _chunkL2JTLW6Bcjs.EffectUnsupportedError)(`The fake provider has no font "${opts.font}"; its only font is "zig".`);
1096
1314
  return [...text].map((_, i) => `M${i * 10} 10 L${i * 10 + 3} 0 L${i * 10 + 6} 10`).join(" ");
1097
1315
  },
1098
1316
  applyVectorEffect(id, target, values) {
1099
1317
  const d = get(id);
1100
- if (d.kind !== "motion" && d.kind !== "vector") throw new (0, _chunkISIO63Q5cjs.EffectUnsupportedError)(`"${id}" is a ${d.kind} effect, not a vector one.`, id);
1101
- const v = _chunkISIO63Q5cjs.resolveEffectValues.call(void 0, d, values);
1318
+ if (d.kind !== "motion" && d.kind !== "vector") throw new (0, _chunkL2JTLW6Bcjs.EffectUnsupportedError)(`"${id}" is a ${d.kind} effect, not a vector one.`, id);
1319
+ const v = _chunkL2JTLW6Bcjs.resolveEffectValues.call(void 0, d, values);
1102
1320
  if (d.id === "fake.route") {
1103
1321
  const pts = Array.isArray(v.path) && v.path.length >= 4 ? v.path : typeof v.path === "string" && pathNumbers(v.path).length >= 4 ? pathNumbers(v.path) : [0, 20, 25, 0, 50, 20, 75, 40, 100, 20];
1104
1322
  const xs = pts.filter((_, i) => i % 2 === 0);
@@ -1132,12 +1350,13 @@ function createFakeEffectProvider(options = {}) {
1132
1350
  sampleCameraMove: (id, request) => {
1133
1351
  const d = get(id);
1134
1352
  const { from, to, ms, stage, fps, values } = request;
1135
- return _chunkISIO63Q5cjs.sampleCameraViews.call(void 0, (u) => camera(id, { from, to, u, ms, stage }, values), { ms, fps, cut: _optionalChain([d, 'access', _53 => _53.camera, 'optionalAccess', _54 => _54.cut]) });
1353
+ return _chunkL2JTLW6Bcjs.sampleCameraViews.call(void 0, (u) => camera(id, { from, to, u, ms, stage }, values), { ms, fps, cut: _optionalChain([d, 'access', _62 => _62.camera, 'optionalAccess', _63 => _63.cut]) });
1136
1354
  }
1137
1355
  } : {},
1356
+ ...options.timing ? { timingLength, timingSample } : {},
1138
1357
  ...options.templates ? fakeTemplateMethods() : {},
1139
1358
  ...supportsAuthoring ? {
1140
- openAuthoring: (from) => _chunkQKXO6JPPcjs.createEffectAuthoringSession.call(void 0, from, { provider })
1359
+ openAuthoring: (from) => _chunk2OQGPEHHcjs.createEffectAuthoringSession.call(void 0, from, { provider })
1141
1360
  } : {}
1142
1361
  };
1143
1362
  return provider;
@@ -1152,7 +1371,8 @@ var EFFECT_USE_LABELS = {
1152
1371
  title: "Title",
1153
1372
  motion: "Motion",
1154
1373
  interactive: "Interactive",
1155
- camera: "Camera"
1374
+ camera: "Camera",
1375
+ timing: "Timing"
1156
1376
  };
1157
1377
  var HEX2 = /^#[0-9a-f]{6}([0-9a-f]{2})?$/i;
1158
1378
  var typeOf = (s) => Array.isArray(s.type) ? s.type.find((t) => t !== "null") : s.type;
@@ -1173,7 +1393,7 @@ function jsonTypeOf(value) {
1173
1393
  function effectControlField(name, schema, fallback, options = {}) {
1174
1394
  const base = { id: name, ...schema.title ? { label: schema.title } : {}, ...schema.description ? { description: schema.description } : {} };
1175
1395
  const def = _nullishCoalesce(schema.default, () => ( fallback));
1176
- const type = _nullishCoalesce(typeOf(schema), () => ( typeOf(_nullishCoalesce(_optionalChain([schema, 'access', _55 => _55.anyOf, 'optionalAccess', _56 => _56.find, 'call', _57 => _57((s) => typeOf(s) === jsonTypeOf(def))]), () => ( {})))));
1396
+ const type = _nullishCoalesce(typeOf(schema), () => ( typeOf(_nullishCoalesce(_optionalChain([schema, 'access', _64 => _64.anyOf, 'optionalAccess', _65 => _65.find, 'call', _66 => _66((s) => typeOf(s) === jsonTypeOf(def))]), () => ( {})))));
1177
1397
  if (Array.isArray(schema.enum) && schema.enum.length) {
1178
1398
  const options2 = schema.enum.filter((v) => typeof v === "string" || typeof v === "number");
1179
1399
  return { ...base, type: "choice", options: options2, default: typeof def === "string" || typeof def === "number" ? def : options2[0], control: options2.length <= 4 ? "segmented" : "select" };
@@ -1187,7 +1407,7 @@ function effectControlField(name, schema, fallback, options = {}) {
1187
1407
  if (isEffectFontControl(schema)) {
1188
1408
  const fonts = _nullishCoalesce(options.fonts, () => ( _chunk4XSBOGMKcjs.SYSTEM_FONT_CATALOG));
1189
1409
  const opts = fonts.map((f) => ({ value: f.family, label: f.family, description: f.category }));
1190
- const current = typeof def === "string" && def ? def : _nullishCoalesce(_optionalChain([opts, 'access', _58 => _58[0], 'optionalAccess', _59 => _59.value]), () => ( "sans-serif"));
1410
+ const current = typeof def === "string" && def ? def : _nullishCoalesce(_optionalChain([opts, 'access', _67 => _67[0], 'optionalAccess', _68 => _68.value]), () => ( "sans-serif"));
1191
1411
  if (!opts.some((o) => o.value.toLowerCase() === current.toLowerCase())) opts.unshift({ value: current, label: current, description: "current" });
1192
1412
  return { ...base, type: "choice", options: opts, default: opts.find((o) => o.value.toLowerCase() === current.toLowerCase()).value, control: "select" };
1193
1413
  }
@@ -1196,7 +1416,7 @@ function effectControlField(name, schema, fallback, options = {}) {
1196
1416
  return { ...base, type: "text", default: typeof def === "string" ? def : "", ...schema.maxLength ? { maxLength: schema.maxLength } : {} };
1197
1417
  }
1198
1418
  if (type === "array" && Array.isArray(def) && def.length >= 2 && def.length <= 4 && def.every((n) => typeof n === "number")) {
1199
- const items = _nullishCoalesce(_nullishCoalesce(schema.items, () => ( _optionalChain([schema, 'access', _60 => _60.anyOf, 'optionalAccess', _61 => _61.find, 'call', _62 => _62((s) => typeOf(s) === "array"), 'optionalAccess', _63 => _63.items]))), () => ( {}));
1419
+ const items = _nullishCoalesce(_nullishCoalesce(schema.items, () => ( _optionalChain([schema, 'access', _69 => _69.anyOf, 'optionalAccess', _70 => _70.find, 'call', _71 => _71((s) => typeOf(s) === "array"), 'optionalAccess', _72 => _72.items]))), () => ( {}));
1200
1420
  return { ...base, type: "vector", size: def.length, default: [...def], ...items.minimum !== void 0 ? { min: items.minimum } : {}, ...items.maximum !== void 0 ? { max: items.maximum } : {} };
1201
1421
  }
1202
1422
  return null;
@@ -1218,7 +1438,7 @@ var effectFieldValue = (field, value) => {
1218
1438
  return value === void 0 || value === null || typeof value === "object" && !Array.isArray(value) ? field.default : value;
1219
1439
  };
1220
1440
  function effectSamplePicture(width, height, variant = 0) {
1221
- const p = _chunkISIO63Q5cjs.createEffectPixels.call(void 0, width, height);
1441
+ const p = _chunkL2JTLW6Bcjs.createEffectPixels.call(void 0, width, height);
1222
1442
  for (let y = 0, i = 0; y < height; y++) {
1223
1443
  for (let x = 0; x < width; x++, i += 4) {
1224
1444
  const u = x / Math.max(1, width - 1);
@@ -1309,11 +1529,11 @@ var EASING_SCHEMA = {
1309
1529
  };
1310
1530
  var NO_SESSION = "No effect authoring session is currently open. Open an effect using EffectProvider.openAuthoring() or in an authoring editor before calling effect authoring tools.";
1311
1531
  function createEffectAuthoringToolProvider(host, options) {
1312
- const id = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _64 => _64.id]), () => ( "effect-authoring"));
1313
- const namespace = _optionalChain([options, 'optionalAccess', _65 => _65.namespace]);
1314
- const title = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _66 => _66.title]), () => ( "Effect authoring"));
1315
- const description = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _67 => _67.description]), () => ( "Author shaders and procedural effects, inspect parameters, adjust values, and manage keyframe animations."));
1316
- const skill = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _68 => _68.skill]), () => ( "pixerate-effect-authoring"));
1532
+ const id = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _73 => _73.id]), () => ( "effect-authoring"));
1533
+ const namespace = _optionalChain([options, 'optionalAccess', _74 => _74.namespace]);
1534
+ const title = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _75 => _75.title]), () => ( "Effect authoring"));
1535
+ const description = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _76 => _76.description]), () => ( "Author shaders and procedural effects, inspect parameters, adjust values, and manage keyframe animations."));
1536
+ const skill = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _77 => _77.skill]), () => ( "pixerate-effect-authoring"));
1317
1537
  const requireSession = () => {
1318
1538
  const s = host.session();
1319
1539
  if (!s) throw new Error(NO_SESSION);
@@ -1334,7 +1554,7 @@ function createEffectAuthoringToolProvider(host, options) {
1334
1554
  sourceLanguage: state.sourceLanguage,
1335
1555
  controls: effectParameterFields(state.description),
1336
1556
  values: state.values,
1337
- presets: _nullishCoalesce(_optionalChain([state, 'access', _69 => _69.description, 'access', _70 => _70.presets, 'optionalAccess', _71 => _71.map, 'call', _72 => _72((p) => p.name)]), () => ( [])),
1557
+ presets: _nullishCoalesce(_optionalChain([state, 'access', _78 => _78.description, 'access', _79 => _79.presets, 'optionalAccess', _80 => _80.map, 'call', _81 => _81((p) => p.name)]), () => ( [])),
1338
1558
  tracks: Object.entries(state.tracks).map(([control, track]) => ({
1339
1559
  control,
1340
1560
  keyframes: track.length
@@ -1641,7 +1861,7 @@ function createEffectAuthoringToolProvider(host, options) {
1641
1861
  const tools = [
1642
1862
  describeTool,
1643
1863
  getSourceTool,
1644
- ..._optionalChain([session, 'optionalAccess', _73 => _73.setSource]) ? [setSourceTool] : [],
1864
+ ..._optionalChain([session, 'optionalAccess', _82 => _82.setSource]) ? [setSourceTool] : [],
1645
1865
  setValuesTool,
1646
1866
  resetValuesTool,
1647
1867
  applyPresetTool,
@@ -1745,4 +1965,13 @@ function createEffectAuthoringToolProvider(host, options) {
1745
1965
 
1746
1966
 
1747
1967
 
1748
- exports.CAMERA_MOVE_MAX_MS = _chunkISIO63Q5cjs.CAMERA_MOVE_MAX_MS; exports.CAMERA_MOVE_ROLES = _chunkISIO63Q5cjs.CAMERA_MOVE_ROLES; exports.EFFECT_ACCEPTS = _chunkISIO63Q5cjs.EFFECT_ACCEPTS; exports.EFFECT_ERROR_CODES = _chunkISIO63Q5cjs.EFFECT_ERROR_CODES; exports.EFFECT_KINDS = _chunkISIO63Q5cjs.EFFECT_KINDS; exports.EFFECT_LAYER_ROLES = _chunkISIO63Q5cjs.EFFECT_LAYER_ROLES; exports.EFFECT_LAYER_USES = _chunkZ3BRH4JKcjs.EFFECT_LAYER_USES; exports.EFFECT_PATH_FORMAT = _chunkISIO63Q5cjs.EFFECT_PATH_FORMAT; exports.EFFECT_SEQUENCE_NAME = _chunkZ3BRH4JKcjs.EFFECT_SEQUENCE_NAME; exports.EFFECT_SUBJECT_KINDS = _chunkISIO63Q5cjs.EFFECT_SUBJECT_KINDS; exports.EFFECT_TEMPLATE_SLOT_TYPES = _chunkISIO63Q5cjs.EFFECT_TEMPLATE_SLOT_TYPES; exports.EFFECT_TRANSITION_MS = _chunkISIO63Q5cjs.EFFECT_TRANSITION_MS; exports.EFFECT_USES = _chunkISIO63Q5cjs.EFFECT_USES; exports.EFFECT_USE_LABELS = EFFECT_USE_LABELS; exports.EffectControlError = _chunkISIO63Q5cjs.EffectControlError; exports.EffectDisposedError = _chunkISIO63Q5cjs.EffectDisposedError; exports.EffectError = _chunkISIO63Q5cjs.EffectError; exports.EffectRendererPool = _chunkPY4GWSE2cjs.EffectRendererPool; exports.EffectUnsupportedError = _chunkISIO63Q5cjs.EffectUnsupportedError; exports.EffectsSlot = _chunkISIO63Q5cjs.EffectsSlot; exports.NoEffectsProviderError = _chunkISIO63Q5cjs.NoEffectsProviderError; exports.UnknownEffectError = _chunkISIO63Q5cjs.UnknownEffectError; exports.UnknownTemplateError = _chunkISIO63Q5cjs.UnknownTemplateError; exports.applyEffectMask = _chunkISIO63Q5cjs.applyEffectMask; exports.cameraBoxOfView = _chunkISIO63Q5cjs.cameraBoxOfView; exports.cameraMoveField = _chunkISIO63Q5cjs.cameraMoveField; exports.cameraMoveIdList = _chunkISIO63Q5cjs.cameraMoveIdList; exports.cameraMoveParts = _chunkISIO63Q5cjs.cameraMoveParts; exports.cameraMovesFor = _chunkISIO63Q5cjs.cameraMovesFor; exports.cameraViewOfBox = _chunkISIO63Q5cjs.cameraViewOfBox; exports.checkEffectProvider = checkEffectProvider; exports.checkEffectSequence = _chunkZ3BRH4JKcjs.checkEffectSequence; exports.checkTemplateValues = _chunkZ3BRH4JKcjs.checkTemplateValues; exports.countEffectTags = _chunkISIO63Q5cjs.countEffectTags; exports.createEffectAuthoringSession = _chunkQKXO6JPPcjs.createEffectAuthoringSession; exports.createEffectAuthoringToolProvider = createEffectAuthoringToolProvider; exports.createEffectPixels = _chunkISIO63Q5cjs.createEffectPixels; exports.createEffectToolProvider = _chunkISIO63Q5cjs.createEffectToolProvider; exports.createFakeEffectProvider = createFakeEffectProvider; exports.effectControlField = effectControlField; exports.effectFieldValue = effectFieldValue; exports.effectFontFamilies = effectFontFamilies; exports.effectLayerInput = _chunkZ3BRH4JKcjs.effectLayerInput; exports.effectLayerOffered = _chunkZ3BRH4JKcjs.effectLayerOffered; exports.effectLayerRole = _chunkZ3BRH4JKcjs.effectLayerRole; exports.effectLayerSpan = _chunkZ3BRH4JKcjs.effectLayerSpan; exports.effectOffered = _chunkISIO63Q5cjs.effectOffered; exports.effectParameterFields = effectParameterFields; exports.effectSampleInputs = effectSampleInputs; exports.effectSamplePicture = effectSamplePicture; exports.effectSequenceEffects = _chunkZ3BRH4JKcjs.effectSequenceEffects; exports.effectSequenceSlots = _chunkZ3BRH4JKcjs.effectSequenceSlots; exports.effectSequenceTiming = _chunkZ3BRH4JKcjs.effectSequenceTiming; exports.effectSubjectKind = _chunkZ3BRH4JKcjs.effectSubjectKind; exports.effectSubjectProblem = _chunkZ3BRH4JKcjs.effectSubjectProblem; exports.effectTemplateTools = _chunkZ3BRH4JKcjs.effectTemplateTools; exports.effectValueErrors = _chunkISIO63Q5cjs.effectValueErrors; exports.encodeEffectFloat = _chunkISIO63Q5cjs.encodeEffectFloat; exports.fillEffectTemplate = _chunkZ3BRH4JKcjs.fillEffectTemplate; exports.groupEffectsByCategory = groupEffectsByCategory; exports.hasEffectTags = _chunkISIO63Q5cjs.hasEffectTags; exports.isCameraView = _chunkISIO63Q5cjs.isCameraView; exports.isEffectError = _chunkISIO63Q5cjs.isEffectError; exports.isEffectFontControl = isEffectFontControl; exports.isEffectPixels = _chunkISIO63Q5cjs.isEffectPixels; exports.isSubjectTemplateSlot = _chunkZ3BRH4JKcjs.isSubjectTemplateSlot; exports.layerImageInput = _chunkISIO63Q5cjs.layerImageInput; exports.linearToSrgb = _chunkISIO63Q5cjs.linearToSrgb; exports.normaliseEffectTag = _chunkISIO63Q5cjs.normaliseEffectTag; exports.pathControlsOf = _chunkISIO63Q5cjs.pathControlsOf; exports.renderEffectThumbnail = renderEffectThumbnail; exports.resolveCameraMoveSpec = _chunkISIO63Q5cjs.resolveCameraMoveSpec; exports.resolveEffectValues = _chunkISIO63Q5cjs.resolveEffectValues; exports.sampleCameraViews = _chunkISIO63Q5cjs.sampleCameraViews; exports.sampleEffectCameraMove = _chunkISIO63Q5cjs.sampleEffectCameraMove; exports.searchEffectSummaries = _chunkISIO63Q5cjs.searchEffectSummaries; exports.searchTemplateSummaries = _chunkZ3BRH4JKcjs.searchTemplateSummaries; exports.srgbToLinear = _chunkISIO63Q5cjs.srgbToLinear; exports.templateDefaultValues = _chunkZ3BRH4JKcjs.templateDefaultValues; exports.templateSlotSchema = _chunkZ3BRH4JKcjs.templateSlotSchema; exports.templateSlotSummary = _chunkZ3BRH4JKcjs.templateSlotSummary; exports.templateSlotTakes = _chunkZ3BRH4JKcjs.templateSlotTakes; exports.templateValueProblem = _chunkZ3BRH4JKcjs.templateValueProblem; exports.templateValuesSchema = _chunkZ3BRH4JKcjs.templateValuesSchema;
1968
+
1969
+
1970
+
1971
+
1972
+
1973
+
1974
+
1975
+
1976
+
1977
+ exports.CAMERA_MOVE_MAX_MS = _chunkL2JTLW6Bcjs.CAMERA_MOVE_MAX_MS; exports.CAMERA_MOVE_ROLES = _chunkL2JTLW6Bcjs.CAMERA_MOVE_ROLES; exports.EFFECT_ACCEPTS = _chunkL2JTLW6Bcjs.EFFECT_ACCEPTS; exports.EFFECT_ERROR_CODES = _chunkL2JTLW6Bcjs.EFFECT_ERROR_CODES; exports.EFFECT_KINDS = _chunkL2JTLW6Bcjs.EFFECT_KINDS; exports.EFFECT_LAYER_ROLES = _chunkL2JTLW6Bcjs.EFFECT_LAYER_ROLES; exports.EFFECT_LAYER_USES = _chunk557BDWKOcjs.EFFECT_LAYER_USES; exports.EFFECT_PATH_FORMAT = _chunkL2JTLW6Bcjs.EFFECT_PATH_FORMAT; exports.EFFECT_SEQUENCE_NAME = _chunk557BDWKOcjs.EFFECT_SEQUENCE_NAME; exports.EFFECT_SUBJECT_KINDS = _chunkL2JTLW6Bcjs.EFFECT_SUBJECT_KINDS; exports.EFFECT_TEMPLATE_SLOT_TYPES = _chunkL2JTLW6Bcjs.EFFECT_TEMPLATE_SLOT_TYPES; exports.EFFECT_TRANSITION_MS = _chunkL2JTLW6Bcjs.EFFECT_TRANSITION_MS; exports.EFFECT_USES = _chunkL2JTLW6Bcjs.EFFECT_USES; exports.EFFECT_USE_LABELS = EFFECT_USE_LABELS; exports.EffectControlError = _chunkL2JTLW6Bcjs.EffectControlError; exports.EffectDisposedError = _chunkL2JTLW6Bcjs.EffectDisposedError; exports.EffectError = _chunkL2JTLW6Bcjs.EffectError; exports.EffectRendererPool = _chunkPY4GWSE2cjs.EffectRendererPool; exports.EffectUnsupportedError = _chunkL2JTLW6Bcjs.EffectUnsupportedError; exports.EffectsSlot = _chunkL2JTLW6Bcjs.EffectsSlot; exports.NoEffectsProviderError = _chunkL2JTLW6Bcjs.NoEffectsProviderError; exports.TIMING_BLENDS = _chunkL2JTLW6Bcjs.TIMING_BLENDS; exports.TIMING_DEFAULT_FPS = _chunkL2JTLW6Bcjs.TIMING_DEFAULT_FPS; exports.TIMING_MAX_FPS = _chunkL2JTLW6Bcjs.TIMING_MAX_FPS; exports.TIMING_MAX_FRAMES = _chunkL2JTLW6Bcjs.TIMING_MAX_FRAMES; exports.UnknownEffectError = _chunkL2JTLW6Bcjs.UnknownEffectError; exports.UnknownTemplateError = _chunkL2JTLW6Bcjs.UnknownTemplateError; exports.applyEffectMask = _chunkL2JTLW6Bcjs.applyEffectMask; exports.blendTimingFrames = _chunkL2JTLW6Bcjs.blendTimingFrames; exports.cameraBoxOfView = _chunkL2JTLW6Bcjs.cameraBoxOfView; exports.cameraMoveField = _chunkL2JTLW6Bcjs.cameraMoveField; exports.cameraMoveIdList = _chunkL2JTLW6Bcjs.cameraMoveIdList; exports.cameraMoveParts = _chunkL2JTLW6Bcjs.cameraMoveParts; exports.cameraMovesFor = _chunkL2JTLW6Bcjs.cameraMovesFor; exports.cameraViewOfBox = _chunkL2JTLW6Bcjs.cameraViewOfBox; exports.checkEffectProvider = checkEffectProvider; exports.checkEffectSequence = _chunk557BDWKOcjs.checkEffectSequence; exports.checkTemplateValues = _chunk557BDWKOcjs.checkTemplateValues; exports.checkTimingFootage = _chunkL2JTLW6Bcjs.checkTimingFootage; exports.checkTimingRequest = _chunkL2JTLW6Bcjs.checkTimingRequest; exports.countEffectTags = _chunkL2JTLW6Bcjs.countEffectTags; exports.createEffectAuthoringSession = _chunk2OQGPEHHcjs.createEffectAuthoringSession; exports.createEffectAuthoringToolProvider = createEffectAuthoringToolProvider; exports.createEffectPixels = _chunkL2JTLW6Bcjs.createEffectPixels; exports.createEffectToolProvider = _chunkL2JTLW6Bcjs.createEffectToolProvider; exports.createFakeEffectProvider = createFakeEffectProvider; exports.effectControlField = effectControlField; exports.effectFieldValue = effectFieldValue; exports.effectFontFamilies = effectFontFamilies; exports.effectLayerInput = _chunk557BDWKOcjs.effectLayerInput; exports.effectLayerOffered = _chunk557BDWKOcjs.effectLayerOffered; exports.effectLayerRole = _chunk557BDWKOcjs.effectLayerRole; exports.effectLayerSpan = _chunk557BDWKOcjs.effectLayerSpan; exports.effectOffered = _chunkL2JTLW6Bcjs.effectOffered; exports.effectParameterFields = effectParameterFields; exports.effectSampleInputs = effectSampleInputs; exports.effectSamplePicture = effectSamplePicture; exports.effectSequenceEffects = _chunk557BDWKOcjs.effectSequenceEffects; exports.effectSequenceSlots = _chunk557BDWKOcjs.effectSequenceSlots; exports.effectSequenceTiming = _chunk557BDWKOcjs.effectSequenceTiming; exports.effectSubjectKind = _chunk557BDWKOcjs.effectSubjectKind; exports.effectSubjectProblem = _chunk557BDWKOcjs.effectSubjectProblem; exports.effectTemplateTools = _chunk557BDWKOcjs.effectTemplateTools; exports.effectValueErrors = _chunkL2JTLW6Bcjs.effectValueErrors; exports.encodeEffectFloat = _chunkL2JTLW6Bcjs.encodeEffectFloat; exports.fillEffectTemplate = _chunk557BDWKOcjs.fillEffectTemplate; exports.groupEffectsByCategory = groupEffectsByCategory; exports.hasEffectTags = _chunkL2JTLW6Bcjs.hasEffectTags; exports.isCameraView = _chunkL2JTLW6Bcjs.isCameraView; exports.isEffectError = _chunkL2JTLW6Bcjs.isEffectError; exports.isEffectFontControl = isEffectFontControl; exports.isEffectPixels = _chunkL2JTLW6Bcjs.isEffectPixels; exports.isSubjectTemplateSlot = _chunk557BDWKOcjs.isSubjectTemplateSlot; exports.layerImageInput = _chunkL2JTLW6Bcjs.layerImageInput; exports.linearToSrgb = _chunkL2JTLW6Bcjs.linearToSrgb; exports.normaliseEffectTag = _chunkL2JTLW6Bcjs.normaliseEffectTag; exports.normaliseTimingSample = _chunkL2JTLW6Bcjs.normaliseTimingSample; exports.pathControlsOf = _chunkL2JTLW6Bcjs.pathControlsOf; exports.renderEffectThumbnail = renderEffectThumbnail; exports.resolveCameraMoveSpec = _chunkL2JTLW6Bcjs.resolveCameraMoveSpec; exports.resolveEffectValues = _chunkL2JTLW6Bcjs.resolveEffectValues; exports.sampleCameraViews = _chunkL2JTLW6Bcjs.sampleCameraViews; exports.sampleEffectCameraMove = _chunkL2JTLW6Bcjs.sampleEffectCameraMove; exports.searchEffectSummaries = _chunkL2JTLW6Bcjs.searchEffectSummaries; exports.searchTemplateSummaries = _chunk557BDWKOcjs.searchTemplateSummaries; exports.srgbToLinear = _chunkL2JTLW6Bcjs.srgbToLinear; exports.templateDefaultValues = _chunk557BDWKOcjs.templateDefaultValues; exports.templateSlotSchema = _chunk557BDWKOcjs.templateSlotSchema; exports.templateSlotSummary = _chunk557BDWKOcjs.templateSlotSummary; exports.templateSlotTakes = _chunk557BDWKOcjs.templateSlotTakes; exports.templateValueProblem = _chunk557BDWKOcjs.templateValueProblem; exports.templateValuesSchema = _chunk557BDWKOcjs.templateValuesSchema; exports.timingSampleProblems = _chunkL2JTLW6Bcjs.timingSampleProblems;