@bendyline/squisq-video-react 2.4.11 → 2.4.13

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.
@@ -0,0 +1,452 @@
1
+ import {
2
+ createRnnoiseDenoiserFactory
3
+ } from "./chunk-TL2IMDIZ.js";
4
+
5
+ // src/mediaEdit/mediaEditRenderer.ts
6
+ var inlineDenoiser = createRnnoiseDenoiserFactory(
7
+ () => import("@shiguredo/rnnoise-wasm").then(({ Rnnoise }) => Rnnoise.load())
8
+ );
9
+ async function inlineEngine() {
10
+ return import("./mediaEditEngine-ZLG7D3TB.js");
11
+ }
12
+ function inlineOptions(options) {
13
+ return { ...options, denoiser: options.denoiser ?? inlineDenoiser };
14
+ }
15
+ function defaultWorker() {
16
+ return new Worker(new URL("./workers/mediaEdit.worker.js", import.meta.url), { type: "module" });
17
+ }
18
+ function abortError() {
19
+ return new DOMException("The media-edit job was cancelled.", "AbortError");
20
+ }
21
+ function createMediaEditRenderer(options = {}) {
22
+ let worker;
23
+ let nextId = 1;
24
+ const pending = /* @__PURE__ */ new Map();
25
+ const failAll = (reason) => {
26
+ for (const job of pending.values()) job.reject(reason);
27
+ pending.clear();
28
+ };
29
+ const ensureWorker = () => {
30
+ if (worker !== void 0) return worker;
31
+ try {
32
+ worker = (options.createWorker ?? defaultWorker)();
33
+ } catch {
34
+ worker = null;
35
+ }
36
+ if (worker) {
37
+ worker.onmessage = (event) => {
38
+ const msg = event.data;
39
+ const job = pending.get(msg.id);
40
+ if (!job) return;
41
+ if (msg.type === "progress") {
42
+ job.onProgress?.(msg.fraction);
43
+ return;
44
+ }
45
+ pending.delete(msg.id);
46
+ if (msg.type === "error") job.reject(msg.aborted ? abortError() : new Error(msg.message));
47
+ else job.resolve(msg.result);
48
+ };
49
+ worker.onerror = (event) => {
50
+ event.preventDefault();
51
+ worker?.terminate();
52
+ worker = null;
53
+ const orphans = [...pending.values()];
54
+ pending.clear();
55
+ for (const job of orphans) job.inline().then(job.resolve, job.reject);
56
+ };
57
+ }
58
+ return worker;
59
+ };
60
+ function dispatch(request, jobOptions, inline) {
61
+ const target = ensureWorker();
62
+ if (!target) return inline();
63
+ return new Promise((resolve, reject) => {
64
+ if (jobOptions.signal?.aborted) {
65
+ reject(abortError());
66
+ return;
67
+ }
68
+ pending.set(request.id, {
69
+ resolve,
70
+ reject,
71
+ onProgress: jobOptions.onProgress,
72
+ inline
73
+ });
74
+ jobOptions.signal?.addEventListener(
75
+ "abort",
76
+ () => target.postMessage({ type: "cancel", id: request.id }),
77
+ { once: true }
78
+ );
79
+ target.postMessage(request);
80
+ });
81
+ }
82
+ return {
83
+ render(request, jobOptions = {}) {
84
+ return dispatch(
85
+ { ...request, type: "render", id: nextId++ },
86
+ jobOptions,
87
+ async () => (await inlineEngine()).renderMediaEditAudio(request, inlineOptions(jobOptions))
88
+ );
89
+ },
90
+ analyze(request, jobOptions = {}) {
91
+ return dispatch(
92
+ { ...request, type: "analyze", id: nextId++ },
93
+ jobOptions,
94
+ async () => (await inlineEngine()).analyzeMediaEditAudio(request, inlineOptions(jobOptions))
95
+ );
96
+ },
97
+ preview(request, jobOptions = {}) {
98
+ return dispatch(
99
+ { ...request, type: "preview", id: nextId++ },
100
+ jobOptions,
101
+ async () => (await inlineEngine()).previewMediaEditAudio(request, inlineOptions(jobOptions))
102
+ );
103
+ },
104
+ pauses(request, jobOptions = {}) {
105
+ return dispatch(
106
+ { ...request, type: "pauses", id: nextId++ },
107
+ jobOptions,
108
+ async () => (await inlineEngine()).analyzeMediaEditPauses(request, jobOptions)
109
+ );
110
+ },
111
+ dispose() {
112
+ failAll(abortError());
113
+ worker?.terminate();
114
+ worker = null;
115
+ }
116
+ };
117
+ }
118
+
119
+ // src/mediaEdit/mediaEditRenderManager.ts
120
+ import {
121
+ MEDIA_FX_ORDER,
122
+ MEDIA_RENDER_MANIFEST_VERSION,
123
+ buildMediaRenderIndex,
124
+ collectDocMediaClips,
125
+ mediaClipRenderKey,
126
+ mediaRenderFilePath,
127
+ mediaRenderManifestPath,
128
+ mediaRenderStaleness,
129
+ parseMediaRenderManifest,
130
+ referencedMediaRenderKeys,
131
+ selectMediaRendersForGc,
132
+ serializeMediaFx,
133
+ serializeMediaRenderManifest
134
+ } from "@bendyline/squisq/mediaEdit";
135
+ function sourceSizeOf(sizes, src) {
136
+ const direct = sizes.get(src);
137
+ if (direct != null) return direct;
138
+ for (const [name, size] of sizes) if (name.endsWith(`/${src}`)) return size;
139
+ return null;
140
+ }
141
+ function createMediaEditRenderManager(options) {
142
+ const provider = options.mediaProvider;
143
+ const ownsRenderer = !options.renderer;
144
+ const renderer = options.renderer ?? createMediaEditRenderer();
145
+ const fetchImpl = options.fetch ?? ((input, init) => fetch(input, init));
146
+ const now = options.now ?? (() => /* @__PURE__ */ new Date());
147
+ let index = /* @__PURE__ */ new Map();
148
+ let sourceSizes = /* @__PURE__ */ new Map();
149
+ const manifests = /* @__PURE__ */ new Map();
150
+ const staleKeys = /* @__PURE__ */ new Set();
151
+ const statuses = /* @__PURE__ */ new Map();
152
+ const queue = [];
153
+ const listeners = /* @__PURE__ */ new Set();
154
+ let version = 0;
155
+ let indexVersion = 0;
156
+ let indexLoad = null;
157
+ let running = null;
158
+ let disposed = false;
159
+ let latestDoc = null;
160
+ let lastExtras = [];
161
+ const indexSignature = () => [...index].filter(([key]) => !staleKeys.has(key)).map(([key, entry]) => `${key}=${entry.path}`).sort().join("|");
162
+ const notify = () => {
163
+ version++;
164
+ for (const listener of listeners) listener();
165
+ };
166
+ const loadText = async (path) => {
167
+ try {
168
+ const url = await provider.resolveUrl(path);
169
+ const response = await fetchImpl(url);
170
+ return response.ok ? await response.text() : null;
171
+ } catch {
172
+ return null;
173
+ }
174
+ };
175
+ const manifestFor = async (key) => {
176
+ if (manifests.has(key)) return manifests.get(key) ?? null;
177
+ const entry = index.get(key);
178
+ const manifest = entry?.manifestPath ? parseMediaRenderManifest(await loadText(entry.manifestPath) ?? "") : null;
179
+ manifests.set(key, manifest);
180
+ return manifest;
181
+ };
182
+ const refreshIndex = async () => {
183
+ const entries = await provider.listMedia();
184
+ const before = indexSignature();
185
+ index = buildMediaRenderIndex(entries);
186
+ sourceSizes = new Map(entries.map((e) => [e.name, e.size]));
187
+ staleKeys.clear();
188
+ for (const [key] of index) {
189
+ const manifest = await manifestFor(key);
190
+ if (!manifest) continue;
191
+ const staleness = mediaRenderStaleness(manifest, {
192
+ sourceSize: sourceSizeOf(sourceSizes, manifest.src),
193
+ knownOps: MEDIA_FX_ORDER
194
+ });
195
+ if (staleness) staleKeys.add(key);
196
+ }
197
+ if (indexSignature() !== before) indexVersion++;
198
+ notify();
199
+ };
200
+ const ensureIndex = () => {
201
+ indexLoad ?? (indexLoad = refreshIndex().catch(() => {
202
+ indexLoad = null;
203
+ }));
204
+ return indexLoad;
205
+ };
206
+ const isCurrent = (key) => index.has(key) && !staleKeys.has(key);
207
+ const pump = async () => {
208
+ if (running || disposed) return;
209
+ const job = queue.shift();
210
+ if (!job) return;
211
+ const controller = new AbortController();
212
+ running = { key: job.key, controller };
213
+ statuses.set(job.key, { key: job.key, state: "rendering", progress: 0 });
214
+ notify();
215
+ let lastReported = 0;
216
+ try {
217
+ const source = await loadSource(job.clip.src);
218
+ const result = await renderer.render(
219
+ { source, fx: job.fx },
220
+ {
221
+ signal: controller.signal,
222
+ onProgress: (fraction) => {
223
+ if (fraction - lastReported < 0.01 && fraction < 1) return;
224
+ lastReported = fraction;
225
+ statuses.set(job.key, { key: job.key, state: "rendering", progress: fraction });
226
+ notify();
227
+ }
228
+ }
229
+ );
230
+ const renderPath = await provider.addMedia(
231
+ mediaRenderFilePath(job.clip.src, job.key, result.extension),
232
+ result.bytes,
233
+ result.mimeType
234
+ );
235
+ const manifest = {
236
+ version: MEDIA_RENDER_MANIFEST_VERSION,
237
+ src: job.clip.src,
238
+ key: job.key,
239
+ fx: job.fx,
240
+ ignoredOps: result.ignoredOps,
241
+ file: renderPath,
242
+ mimeType: result.mimeType,
243
+ sourceSize: source.size,
244
+ sourceDuration: result.sourceDuration,
245
+ engine: result.engine,
246
+ createdAt: now().toISOString(),
247
+ analysis: {
248
+ ...result.analysis.integratedLufs != null ? { integratedLufs: result.analysis.integratedLufs } : {},
249
+ appliedGainDb: result.analysis.loudnessGainDb,
250
+ breathCount: result.analysis.breaths.length
251
+ }
252
+ };
253
+ const manifestPath = await provider.addMedia(
254
+ mediaRenderManifestPath(job.clip.src, job.key),
255
+ new TextEncoder().encode(serializeMediaRenderManifest(manifest)),
256
+ "application/json"
257
+ );
258
+ index.set(job.key, {
259
+ key: job.key,
260
+ path: renderPath,
261
+ manifestPath,
262
+ size: result.bytes.byteLength
263
+ });
264
+ manifests.set(job.key, manifest);
265
+ staleKeys.delete(job.key);
266
+ indexVersion++;
267
+ statuses.set(job.key, { key: job.key, state: "ready" });
268
+ } catch (err) {
269
+ const aborted = err instanceof DOMException && err.name === "AbortError";
270
+ if (aborted) statuses.delete(job.key);
271
+ else {
272
+ statuses.set(job.key, {
273
+ key: job.key,
274
+ state: "failed",
275
+ error: err instanceof Error ? err.message : String(err)
276
+ });
277
+ }
278
+ } finally {
279
+ running = null;
280
+ notify();
281
+ void pump();
282
+ }
283
+ };
284
+ const enqueue = (clip, force) => {
285
+ const key = mediaClipRenderKey(clip);
286
+ const fx = clip.edits?.fx;
287
+ if (!key || !fx) return;
288
+ if (!force && (isCurrent(key) || statuses.get(key)?.state === "failed")) return;
289
+ if (running?.key === key || queue.some((job) => job.key === key)) return;
290
+ queue.push({ key, clip, fx: serializeMediaFx({ ops: fx.ops, unknown: [] }) });
291
+ statuses.set(key, { key, state: "queued" });
292
+ };
293
+ async function loadSource(src) {
294
+ const url = await provider.resolveUrl(src);
295
+ const response = await fetchImpl(url);
296
+ if (!response.ok) throw new Error(`Could not read ${src} (${response.status}).`);
297
+ return response.blob();
298
+ }
299
+ const requiredKeys = (doc) => {
300
+ const keys = referencedMediaRenderKeys(doc);
301
+ for (const clip of lastExtras) {
302
+ const key = mediaClipRenderKey(clip);
303
+ if (key) keys.add(key);
304
+ }
305
+ return keys;
306
+ };
307
+ const manager = {
308
+ renderer,
309
+ sync(doc, extraClips) {
310
+ latestDoc = doc;
311
+ const extras = extraClips ?? lastExtras;
312
+ lastExtras = extras;
313
+ void ensureIndex().then(() => {
314
+ if (disposed || latestDoc !== doc) return;
315
+ const clips = [...collectDocMediaClips(doc), ...extras];
316
+ const wanted = new Set(
317
+ clips.map((clip) => mediaClipRenderKey(clip)).filter((key) => key != null)
318
+ );
319
+ for (let i = queue.length - 1; i >= 0; i--) {
320
+ if (!wanted.has(queue[i].key)) {
321
+ statuses.delete(queue[i].key);
322
+ queue.splice(i, 1);
323
+ }
324
+ }
325
+ for (const clip of clips) enqueue(clip, false);
326
+ notify();
327
+ void pump();
328
+ });
329
+ },
330
+ processedAudio(clip) {
331
+ const key = mediaClipRenderKey(clip);
332
+ return key && isCurrent(key) ? index.get(key)?.path : void 0;
333
+ },
334
+ status(clip) {
335
+ const key = mediaClipRenderKey(clip);
336
+ if (!key) return null;
337
+ if (isCurrent(key)) return statuses.get(key) ?? { key, state: "ready" };
338
+ return statuses.get(key) ?? { key, state: "queued" };
339
+ },
340
+ whenReady(doc, signal) {
341
+ manager.sync(doc);
342
+ return new Promise((resolve, reject) => {
343
+ const check = () => {
344
+ if (signal?.aborted) {
345
+ unsubscribe();
346
+ reject(new DOMException("Waiting for renders was cancelled.", "AbortError"));
347
+ return;
348
+ }
349
+ const pending = [...requiredKeys(doc)].some((key) => {
350
+ if (isCurrent(key)) return false;
351
+ return statuses.get(key)?.state !== "failed";
352
+ });
353
+ if (!pending && indexLoad) {
354
+ unsubscribe();
355
+ resolve();
356
+ }
357
+ };
358
+ const unsubscribe = manager.subscribe(check);
359
+ signal?.addEventListener("abort", check, { once: true });
360
+ void ensureIndex().then(check);
361
+ });
362
+ },
363
+ retry(clip) {
364
+ const key = mediaClipRenderKey(clip);
365
+ if (!key) return;
366
+ statuses.delete(key);
367
+ enqueue(clip, true);
368
+ notify();
369
+ void pump();
370
+ },
371
+ loadSource,
372
+ async collectGarbage(doc, at = now()) {
373
+ await refreshIndex();
374
+ const docSources = new Set(
375
+ [...collectDocMediaClips(doc), ...lastExtras].map((clip) => clip.src)
376
+ );
377
+ const busy = /* @__PURE__ */ new Set([...queue.map((job) => job.key), ...running ? [running.key] : []]);
378
+ const candidates = /* @__PURE__ */ new Map();
379
+ const loaded = /* @__PURE__ */ new Map();
380
+ for (const [key, entry] of index) {
381
+ const manifest = await manifestFor(key);
382
+ if (!manifest || !docSources.has(manifest.src) || busy.has(key)) continue;
383
+ candidates.set(key, entry);
384
+ loaded.set(key, manifest);
385
+ }
386
+ const paths = selectMediaRendersForGc(candidates, requiredKeys(doc), loaded, at);
387
+ for (const path of paths) await provider.removeMedia(path);
388
+ if (paths.length > 0) {
389
+ for (const key of candidates.keys()) {
390
+ const entry = index.get(key);
391
+ if (entry && paths.includes(entry.path)) {
392
+ index.delete(key);
393
+ manifests.delete(key);
394
+ }
395
+ }
396
+ indexVersion++;
397
+ notify();
398
+ }
399
+ return paths;
400
+ },
401
+ subscribe(listener) {
402
+ listeners.add(listener);
403
+ return () => listeners.delete(listener);
404
+ },
405
+ getVersion: () => version,
406
+ getIndexVersion: () => indexVersion,
407
+ dispose() {
408
+ disposed = true;
409
+ queue.length = 0;
410
+ running?.controller.abort();
411
+ listeners.clear();
412
+ if (ownsRenderer) renderer.dispose();
413
+ }
414
+ };
415
+ return manager;
416
+ }
417
+
418
+ // src/mediaEdit/useMediaEditRenders.ts
419
+ import { useCallback, useEffect, useSyncExternalStore } from "react";
420
+ var noSubscribe = () => () => {
421
+ };
422
+ var zero = () => 0;
423
+ function useProcessedAudio(manager) {
424
+ const indexVersion = useSyncExternalStore(
425
+ manager ? manager.subscribe : noSubscribe,
426
+ manager ? manager.getIndexVersion : zero,
427
+ zero
428
+ );
429
+ return useCallback((clip) => manager?.processedAudio(clip), [manager, indexVersion]);
430
+ }
431
+ function useMediaEditStatus(manager) {
432
+ const version = useSyncExternalStore(
433
+ manager ? manager.subscribe : noSubscribe,
434
+ manager ? manager.getVersion : zero,
435
+ zero
436
+ );
437
+ return useCallback((clip) => manager?.status(clip) ?? null, [manager, version]);
438
+ }
439
+ function useMediaEditRenders(manager, doc) {
440
+ useEffect(() => {
441
+ if (manager && doc) manager.sync(doc);
442
+ }, [manager, doc]);
443
+ return { processedAudio: useProcessedAudio(manager), status: useMediaEditStatus(manager) };
444
+ }
445
+
446
+ export {
447
+ createMediaEditRenderer,
448
+ createMediaEditRenderManager,
449
+ useProcessedAudio,
450
+ useMediaEditStatus,
451
+ useMediaEditRenders
452
+ };
@@ -0,0 +1,27 @@
1
+ // src/mediaEdit/rnnoiseDenoiser.ts
2
+ var RNNOISE_SAMPLE_RATE = 48e3;
3
+ var RNNOISE_LATENCY = 960;
4
+ var PCM16_SCALE = 32768;
5
+ function createRnnoiseDenoiserFactory(load) {
6
+ let loading = null;
7
+ return async () => {
8
+ loading ?? (loading = load());
9
+ const rnnoise = await loading;
10
+ const state = rnnoise.createDenoiseState();
11
+ return {
12
+ frameSize: rnnoise.frameSize,
13
+ sampleRate: RNNOISE_SAMPLE_RATE,
14
+ latency: RNNOISE_LATENCY,
15
+ processFrame(frame) {
16
+ for (let i = 0; i < frame.length; i++) frame[i] *= PCM16_SCALE;
17
+ state.processFrame(frame);
18
+ for (let i = 0; i < frame.length; i++) frame[i] /= PCM16_SCALE;
19
+ },
20
+ dispose: () => state.destroy()
21
+ };
22
+ };
23
+ }
24
+
25
+ export {
26
+ createRnnoiseDenoiserFactory
27
+ };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  useFrameCapture
3
- } from "./chunk-4NI2QIFE.js";
3
+ } from "./chunk-2C4BEAWT.js";
4
4
  import {
5
5
  EXPORT_AUDIO_CHANNELS,
6
6
  EXPORT_AUDIO_SAMPLE_RATE,
@@ -13,7 +13,7 @@ import {
13
13
  supportsWebCodecs,
14
14
  supportsWebCodecsAac,
15
15
  supportsWebCodecsH264
16
- } from "./chunk-32QCPFXE.js";
16
+ } from "./chunk-GBIYYDMY.js";
17
17
 
18
18
  // src/hooks/useVideoExport.ts
19
19
  import { useState, useRef, useCallback, useEffect } from "react";
@@ -677,7 +677,9 @@ function useVideoExport(options = {}) {
677
677
  document
678
678
  ).catch(() => false);
679
679
  const audioBitrate = (QUALITY_PRESETS[quality] ?? QUALITY_PRESETS.normal).audioBitrate;
680
- const timeline = effectiveOutputFormat === "mp4" && audioPolicy !== "omit" ? computeAudioTimeline(doc, coverPlan.audioOffset) : [];
680
+ const timeline = effectiveOutputFormat === "mp4" && audioPolicy !== "omit" ? config.processedAudio ? computeAudioTimeline(doc, coverPlan.audioOffset, {
681
+ processedAudio: config.processedAudio
682
+ }) : computeAudioTimeline(doc, coverPlan.audioOffset) : [];
681
683
  const aacSupported = timeline.length > 0 ? await supportsWebCodecsAac(EXPORT_AUDIO_SAMPLE_RATE, EXPORT_AUDIO_CHANNELS) : false;
682
684
  const tierDecision = selectAudioTier({
683
685
  hasClips: timeline.length > 0,
@@ -1,7 +1,9 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { Doc, MediaProvider } from '@bendyline/squisq/schemas';
3
- import { b as VideoExportConfig, f as VideoOutputFormat } from '../useVideoExport-B2eVCvTX.js';
3
+ import { e as MediaEditRenderManager } from '../mediaEditRenderManager-W_o6RRhT.js';
4
+ import { b as VideoExportConfig, f as VideoOutputFormat } from '../useVideoExport-DsNDpjmO.js';
4
5
  export { CoverImageExportFormat, CoverImageExportModal, CoverImageExportModalProps, coverImageFilename, validateCoverImageDimensions } from '../cover-image/index.js';
6
+ import '@bendyline/squisq/mediaEdit';
5
7
  import '@bendyline/squisq/markdown';
6
8
  import '@bendyline/squisq/doc';
7
9
  import '@bendyline/squisq-video';
@@ -24,6 +26,11 @@ interface VideoExportModalProps {
24
26
  images?: Map<string, ArrayBuffer>;
25
27
  /** Pre-collected audio map */
26
28
  audio?: Map<string, ArrayBuffer>;
29
+ /**
30
+ * Processed-audio renders for media-edit recipes. Export waits for pending
31
+ * renders, then mixes each edited clip's render instead of its original.
32
+ */
33
+ mediaEditRenders?: MediaEditRenderManager | null;
27
34
  /**
28
35
  * Seeds the modal's initial format, motion, quality, FPS, orientation, and
29
36
  * caption selections. It is merged (as a base) into the config passed to the
@@ -59,7 +66,7 @@ interface VideoExportPalette {
59
66
  success: string;
60
67
  danger: string;
61
68
  }
62
- declare function VideoExportModal({ doc, playerScript, mediaProvider, images, audio, defaultConfig, colorScheme, uiPalette, saveOutput, saveActionLabel, onClose, }: VideoExportModalProps): react_jsx_runtime.JSX.Element;
69
+ declare function VideoExportModal({ doc, playerScript, mediaProvider, images, audio, mediaEditRenders, defaultConfig, colorScheme, uiPalette, saveOutput, saveActionLabel, onClose, }: VideoExportModalProps): react_jsx_runtime.JSX.Element;
63
70
 
64
71
  interface VideoExportButtonProps {
65
72
  /** The document to export */
@@ -1,16 +1,17 @@
1
1
  import {
2
2
  VideoExportButton,
3
3
  VideoExportModal
4
- } from "../chunk-JGSJQZGU.js";
4
+ } from "../chunk-RO52S6GO.js";
5
5
  import {
6
6
  CoverImageExportModal,
7
7
  coverImageFilename,
8
8
  validateCoverImageDimensions
9
- } from "../chunk-BRE3IRIM.js";
9
+ } from "../chunk-M5AK4MMV.js";
10
10
  import "../chunk-3NJDHK62.js";
11
- import "../chunk-BGS2NEYC.js";
12
- import "../chunk-4NI2QIFE.js";
13
- import "../chunk-32QCPFXE.js";
11
+ import "../chunk-TUIVBMAK.js";
12
+ import "../chunk-2C4BEAWT.js";
13
+ import "../chunk-4GFZ3GUE.js";
14
+ import "../chunk-GBIYYDMY.js";
14
15
  import "../chunk-5MFQMJ5Z.js";
15
16
  export {
16
17
  CoverImageExportModal,
@@ -2,9 +2,10 @@ import {
2
2
  CoverImageExportModal,
3
3
  coverImageFilename,
4
4
  validateCoverImageDimensions
5
- } from "../chunk-BRE3IRIM.js";
5
+ } from "../chunk-M5AK4MMV.js";
6
6
  import "../chunk-3NJDHK62.js";
7
- import "../chunk-4NI2QIFE.js";
7
+ import "../chunk-2C4BEAWT.js";
8
+ import "../chunk-4GFZ3GUE.js";
8
9
  export {
9
10
  CoverImageExportModal,
10
11
  coverImageFilename,
@@ -7,7 +7,8 @@ import {
7
7
  } from "../chunk-3NJDHK62.js";
8
8
  import {
9
9
  useFrameCapture
10
- } from "../chunk-4NI2QIFE.js";
10
+ } from "../chunk-2C4BEAWT.js";
11
+ import "../chunk-4GFZ3GUE.js";
11
12
 
12
13
  // src/DashboardImageExportModal.tsx
13
14
  import { useCallback, useId, useMemo, useRef, useState } from "react";
@@ -3,7 +3,7 @@ import {
3
3
  supportsWebCodecs,
4
4
  supportsWebCodecsAac,
5
5
  supportsWebCodecsH264
6
- } from "../chunk-32QCPFXE.js";
6
+ } from "../chunk-GBIYYDMY.js";
7
7
  import "../chunk-5MFQMJ5Z.js";
8
8
  export {
9
9
  createEncoder,
@@ -1,4 +1,4 @@
1
- export { D as DEFAULT_VIDEO_COVER_PRE_ROLL_SECONDS, R as ResolvedVideoExportCover, U as UseVideoExportOptions, V as VideoAudioPolicy, a as VideoCoverFramePlan, b as VideoExportConfig, c as VideoExportFramePreview, d as VideoExportResult, e as VideoExportState, f as VideoOutputFormat, r as resolveVideoCoverFramePlan, g as resolveVideoExportCover, u as useVideoExport } from '../useVideoExport-B2eVCvTX.js';
1
+ export { D as DEFAULT_VIDEO_COVER_PRE_ROLL_SECONDS, R as ResolvedVideoExportCover, U as UseVideoExportOptions, V as VideoAudioPolicy, a as VideoCoverFramePlan, b as VideoExportConfig, c as VideoExportFramePreview, d as VideoExportResult, e as VideoExportState, f as VideoOutputFormat, r as resolveVideoCoverFramePlan, g as resolveVideoExportCover, u as useVideoExport } from '../useVideoExport-DsNDpjmO.js';
2
2
  import * as _bendyline_squisq_doc from '@bendyline/squisq/doc';
3
3
  import { Doc, MediaProvider } from '@bendyline/squisq/schemas';
4
4
  import { RenderHtmlOptions } from '@bendyline/squisq-video';
@@ -3,11 +3,12 @@ import {
3
3
  resolveVideoCoverFramePlan,
4
4
  resolveVideoExportCover,
5
5
  useVideoExport
6
- } from "../chunk-BGS2NEYC.js";
6
+ } from "../chunk-TUIVBMAK.js";
7
7
  import {
8
8
  useFrameCapture
9
- } from "../chunk-4NI2QIFE.js";
10
- import "../chunk-32QCPFXE.js";
9
+ } from "../chunk-2C4BEAWT.js";
10
+ import "../chunk-4GFZ3GUE.js";
11
+ import "../chunk-GBIYYDMY.js";
11
12
  import "../chunk-5MFQMJ5Z.js";
12
13
  export {
13
14
  DEFAULT_VIDEO_COVER_PRE_ROLL_SECONDS,
package/dist/index.d.ts CHANGED
@@ -1,13 +1,16 @@
1
1
  export { VideoExportButton, VideoExportButtonProps, VideoExportModal, VideoExportModalProps, VideoExportPalette } from './components/index.js';
2
2
  export { CoverImageExportFormat, CoverImageExportModal, CoverImageExportModalProps, coverImageFilename, validateCoverImageDimensions } from './cover-image/index.js';
3
- export { D as DEFAULT_VIDEO_COVER_PRE_ROLL_SECONDS, R as ResolvedVideoExportCover, U as UseVideoExportOptions, V as VideoAudioPolicy, a as VideoCoverFramePlan, b as VideoExportConfig, c as VideoExportFramePreview, d as VideoExportResult, e as VideoExportState, f as VideoOutputFormat, r as resolveVideoCoverFramePlan, g as resolveVideoExportCover, u as useVideoExport } from './useVideoExport-B2eVCvTX.js';
3
+ export { D as DEFAULT_VIDEO_COVER_PRE_ROLL_SECONDS, R as ResolvedVideoExportCover, U as UseVideoExportOptions, V as VideoAudioPolicy, a as VideoCoverFramePlan, b as VideoExportConfig, c as VideoExportFramePreview, d as VideoExportResult, e as VideoExportState, f as VideoOutputFormat, r as resolveVideoCoverFramePlan, g as resolveVideoExportCover, u as useVideoExport } from './useVideoExport-DsNDpjmO.js';
4
4
  export { FrameCaptureHandle, FrameCaptureOptions, FrameCaptureRenderOptions, useFrameCapture } from './hooks/index.js';
5
5
  export { E as EncoderConfig, a as EncoderFrameSource, M as MainThreadEncoder, c as createEncoder, s as supportsWebCodecs, b as supportsWebCodecsH264 } from './mainThreadEncoder-BVCLjlfj.js';
6
6
  export { FfmpegWasmLoadConfig } from '@bendyline/squisq-video';
7
7
  export { supportsWebCodecsAac } from './encoder/index.js';
8
+ export { M as MediaEditJobOptions, a as MediaEditPausesRequest, b as MediaEditPausesResult, c as MediaEditPreviewRequest, d as MediaEditPreviewResult, e as MediaEditRenderManager, f as MediaEditRenderManagerOptions, g as MediaEditRenderRequest, h as MediaEditRenderResult, i as MediaEditRenderState, j as MediaEditRenderStatus, k as MediaEditRenderer, l as MediaEditRendererOptions, m as createMediaEditRenderManager, n as createMediaEditRenderer } from './mediaEditRenderManager-W_o6RRhT.js';
9
+ export { MediaEditRendersView, useMediaEditRenders, useMediaEditStatus, useProcessedAudio } from './media-edit/index.js';
8
10
  import 'react/jsx-runtime';
9
11
  import '@bendyline/squisq/schemas';
10
12
  import '@bendyline/squisq/doc';
11
13
  import './imageExportShared-B6nqWtE-.js';
12
14
  import '@bendyline/squisq/markdown';
13
15
  import '@bendyline/squisq-react';
16
+ import '@bendyline/squisq/mediaEdit';