@hanifhan1f/vidstack-react 1.12.26 → 1.12.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dev/chunks/vidstack-BalWqr4j.js +1422 -0
  2. package/dev/chunks/vidstack-CKsUl4ll.js +1384 -0
  3. package/dev/chunks/vidstack-CqNX679o.js +669 -0
  4. package/dev/chunks/vidstack-D3ZXOE4d.js +643 -0
  5. package/dev/chunks/vidstack-DjqYvkVp.js +84 -0
  6. package/dev/chunks/vidstack-DqaqkU4T.js +9 -0
  7. package/dev/chunks/vidstack-FuCbl228.js +226 -0
  8. package/dev/chunks/vidstack-PREbBNMG.js +125 -0
  9. package/dev/chunks/vidstack-gqKBE4xH.js +376 -0
  10. package/dev/player/vidstack-default-components.js +9 -8
  11. package/dev/player/vidstack-default-icons.js +1 -1
  12. package/dev/player/vidstack-default-layout.js +9 -8
  13. package/dev/player/vidstack-plyr-layout.js +77 -63
  14. package/dev/player/vidstack-remotion.js +6 -6
  15. package/dev/vidstack.js +22 -133
  16. package/package.json +1 -1
  17. package/prod/chunks/vidstack-BCBskRpc.js +664 -0
  18. package/prod/chunks/vidstack-BZVrgeRF.js +9 -0
  19. package/prod/chunks/vidstack-CKapDFwB.js +376 -0
  20. package/prod/chunks/vidstack-CYK75vJF.js +1382 -0
  21. package/prod/chunks/vidstack-CtxjO6HG.js +84 -0
  22. package/prod/chunks/vidstack-D91K36KQ.js +206 -0
  23. package/prod/chunks/vidstack-DJThTSEm.js +125 -0
  24. package/prod/chunks/vidstack-DXSNXDnS.js +1384 -0
  25. package/prod/chunks/vidstack-DdiGCJVp.js +504 -0
  26. package/prod/player/vidstack-default-components.js +9 -8
  27. package/prod/player/vidstack-default-icons.js +1 -1
  28. package/prod/player/vidstack-default-layout.js +9 -8
  29. package/prod/player/vidstack-plyr-layout.js +77 -63
  30. package/prod/player/vidstack-remotion.js +6 -6
  31. package/prod/vidstack.js +22 -204
  32. package/server/chunks/vidstack-B4rJ1ZKK.js +376 -0
  33. package/server/chunks/vidstack-BTdEfKqV.js +84 -0
  34. package/server/chunks/vidstack-D4t_SZbb.js +1416 -0
  35. package/server/chunks/vidstack-DOIUveQF.js +504 -0
  36. package/server/chunks/vidstack-DbNoKLjz.js +664 -0
  37. package/server/chunks/vidstack-DeS67_gx.js +9 -0
  38. package/server/chunks/vidstack-DiHlnSws.js +1384 -0
  39. package/server/chunks/vidstack-DnoqxmOs.js +125 -0
  40. package/server/chunks/vidstack-SkX-mSrw.js +206 -0
  41. package/server/player/vidstack-default-components.js +9 -8
  42. package/server/player/vidstack-default-icons.js +1 -1
  43. package/server/player/vidstack-default-layout.js +9 -8
  44. package/server/player/vidstack-plyr-layout.js +77 -63
  45. package/server/player/vidstack-remotion.js +6 -6
  46. package/server/vidstack.js +22 -204
@@ -0,0 +1,643 @@
1
+ "use client"
2
+
3
+ import * as React from 'react';
4
+ import { createDisposalBin, listenEvent, isNumber, isUndefined, isNull, isNil, createScope, signal, peek, effect, tick, isFunction, useSignal, deferredPromise } from './vidstack-BalWqr4j.js';
5
+ import { Composition, Internals } from 'remotion';
6
+ import { TimeRange } from 'vidstack';
7
+ import { RemotionLayoutEngine, REMOTION_PROVIDER_ID, RemotionContextProvider, ErrorBoundary } from '../player/vidstack-remotion.js';
8
+ import { isRemotionSrc } from './vidstack-FuCbl228.js';
9
+ import { NoReactInternals } from 'remotion/no-react';
10
+ import './vidstack-DqaqkU4T.js';
11
+
12
+ class RemotionPlaybackEngine {
13
+ #src;
14
+ #onFrameChange;
15
+ #onEnd;
16
+ #disposal = createDisposalBin();
17
+ #frame = 0;
18
+ #framesAdvanced = 0;
19
+ #playbackRate = 1;
20
+ #playing = false;
21
+ #rafId = -1;
22
+ #timerId = -1;
23
+ #startedAt = 0;
24
+ #isRunningInBackground = false;
25
+ get frame() {
26
+ return this.#frame;
27
+ }
28
+ set frame(frame) {
29
+ this.#frame = frame;
30
+ this.#onFrameChange(frame);
31
+ }
32
+ constructor(src, onFrameChange, onEnd) {
33
+ this.#src = src;
34
+ this.#onFrameChange = onFrameChange;
35
+ this.#onEnd = onEnd;
36
+ this.#frame = src.initialFrame ?? 0;
37
+ this.#disposal.add(
38
+ listenEvent(document, "visibilitychange", this.#onVisibilityChange.bind(this))
39
+ );
40
+ }
41
+ play() {
42
+ this.#framesAdvanced = 0;
43
+ this.#playing = true;
44
+ this.#startedAt = performance.now();
45
+ this.#tick();
46
+ }
47
+ stop() {
48
+ this.#playing = false;
49
+ if (this.#rafId >= 0) {
50
+ cancelAnimationFrame(this.#rafId);
51
+ this.#rafId = -1;
52
+ }
53
+ if (this.#timerId >= 0) {
54
+ clearTimeout(this.#timerId);
55
+ this.#timerId = -1;
56
+ }
57
+ }
58
+ setPlaybackRate(rate) {
59
+ this.#playbackRate = rate;
60
+ }
61
+ destroy() {
62
+ this.#disposal.empty();
63
+ this.stop();
64
+ }
65
+ #update() {
66
+ const { nextFrame, framesToAdvance, ended } = this.#calculateNextFrame();
67
+ this.#framesAdvanced += framesToAdvance;
68
+ if (nextFrame !== this.#frame) {
69
+ this.#onFrameChange(nextFrame);
70
+ this.#frame = nextFrame;
71
+ }
72
+ if (ended) {
73
+ this.#frame = this.#src.outFrame;
74
+ this.stop();
75
+ this.#onEnd();
76
+ }
77
+ }
78
+ #tick = () => {
79
+ this.#update();
80
+ if (this.#playing) {
81
+ this.#queueNextFrame(this.#tick);
82
+ }
83
+ };
84
+ #queueNextFrame(callback) {
85
+ if (this.#isRunningInBackground) {
86
+ this.#timerId = window.setTimeout(callback, 1e3 / this.#src.fps);
87
+ } else {
88
+ this.#rafId = requestAnimationFrame(callback);
89
+ }
90
+ }
91
+ #calculateNextFrame() {
92
+ const round = this.#playbackRate < 0 ? Math.ceil : Math.floor, time = performance.now() - this.#startedAt, framesToAdvance = round(time * this.#playbackRate / (1e3 / this.#src.fps)) - this.#framesAdvanced, nextFrame = framesToAdvance + this.#frame, isCurrentFrameOutOfBounds = this.#frame > this.#src.outFrame || this.#frame < this.#src.inFrame, isNextFrameOutOfBounds = nextFrame > this.#src.outFrame || nextFrame < this.#src.inFrame, ended = isNextFrameOutOfBounds && !isCurrentFrameOutOfBounds;
93
+ if (this.#playbackRate > 0 && !ended) {
94
+ if (isNextFrameOutOfBounds) {
95
+ return {
96
+ nextFrame: this.#src.inFrame,
97
+ framesToAdvance,
98
+ ended
99
+ };
100
+ }
101
+ return { nextFrame, framesToAdvance, ended };
102
+ }
103
+ if (isNextFrameOutOfBounds) {
104
+ return {
105
+ nextFrame: this.#src.outFrame,
106
+ framesToAdvance,
107
+ ended
108
+ };
109
+ }
110
+ return { nextFrame, framesToAdvance, ended };
111
+ }
112
+ #onVisibilityChange() {
113
+ this.#isRunningInBackground = document.visibilityState === "hidden";
114
+ if (this.#playing) {
115
+ this.stop();
116
+ this.play();
117
+ }
118
+ }
119
+ }
120
+
121
+ function validateRemotionResource({
122
+ src,
123
+ compositionWidth: width,
124
+ compositionHeight: height,
125
+ fps,
126
+ durationInFrames,
127
+ initialFrame,
128
+ inFrame,
129
+ outFrame,
130
+ numberOfSharedAudioTags
131
+ }) {
132
+ validateComponent(src);
133
+ validateInitialFrame(initialFrame, durationInFrames);
134
+ validateDimension(width, "compositionWidth", "of the remotion source");
135
+ validateDimension(height, "compositionHeight", "of the remotion source");
136
+ validateDurationInFrames(durationInFrames, {
137
+ component: "of the remotion source",
138
+ allowFloats: false
139
+ });
140
+ validateFps(fps, "of the remotion source", false);
141
+ validateInOutFrames(inFrame, outFrame, durationInFrames);
142
+ validateSharedNumberOfAudioTags(numberOfSharedAudioTags);
143
+ }
144
+ const validateFps = NoReactInternals.validateFps;
145
+ const validateDimension = NoReactInternals.validateDimension;
146
+ const validateDurationInFrames = NoReactInternals.validateDurationInFrames;
147
+ function validateInitialFrame(initialFrame, frames) {
148
+ if (!isNumber(frames)) {
149
+ throw new Error(
150
+ `[vidstack] \`durationInFrames\` must be a number, but is ${JSON.stringify(frames)}`
151
+ );
152
+ }
153
+ if (isUndefined(initialFrame)) {
154
+ return;
155
+ }
156
+ if (!isNumber(initialFrame)) {
157
+ throw new Error(
158
+ `[vidstack] \`initialFrame\` must be a number, but is ${JSON.stringify(initialFrame)}`
159
+ );
160
+ }
161
+ if (Number.isNaN(initialFrame)) {
162
+ throw new Error(`[vidstack] \`initialFrame\` must be a number, but is NaN`);
163
+ }
164
+ if (!Number.isFinite(initialFrame)) {
165
+ throw new Error(`[vidstack] \`initialFrame\` must be a number, but is Infinity`);
166
+ }
167
+ if (initialFrame % 1 !== 0) {
168
+ throw new Error(
169
+ `[vidstack] \`initialFrame\` must be an integer, but is ${JSON.stringify(initialFrame)}`
170
+ );
171
+ }
172
+ if (initialFrame > frames - 1) {
173
+ throw new Error(
174
+ `[vidstack] \`initialFrame\` must be less or equal than \`durationInFrames - 1\`, but is ${JSON.stringify(
175
+ initialFrame
176
+ )}`
177
+ );
178
+ }
179
+ }
180
+ function validateSingleFrame(frame, variableName) {
181
+ if (isNil(frame)) {
182
+ return frame ?? null;
183
+ }
184
+ if (!isNumber(frame)) {
185
+ throw new TypeError(
186
+ `[vidstack] \`${variableName}\` must be a number, but is ${JSON.stringify(frame)}`
187
+ );
188
+ }
189
+ if (Number.isNaN(frame)) {
190
+ throw new TypeError(
191
+ `[vidstack] \`${variableName}\` must not be NaN, but is ${JSON.stringify(frame)}`
192
+ );
193
+ }
194
+ if (!Number.isFinite(frame)) {
195
+ throw new TypeError(
196
+ `[vidstack] \`${variableName}\` must be finite, but is ${JSON.stringify(frame)}`
197
+ );
198
+ }
199
+ if (frame % 1 !== 0) {
200
+ throw new TypeError(
201
+ `[vidstack] \`${variableName}\` must be an integer, but is ${JSON.stringify(frame)}`
202
+ );
203
+ }
204
+ return frame;
205
+ }
206
+ function validateInOutFrames(inFrame, outFrame, frames) {
207
+ const validatedInFrame = validateSingleFrame(inFrame, "inFrame"), validatedOutFrame = validateSingleFrame(outFrame, "outFrame");
208
+ if (isNull(validatedInFrame) && isNull(validatedOutFrame)) {
209
+ return;
210
+ }
211
+ if (!isNull(validatedInFrame) && validatedInFrame > frames - 1) {
212
+ throw new Error(
213
+ `[vidstack] \`inFrame\` must be less than (durationInFrames - 1), but is \`${validatedInFrame}\``
214
+ );
215
+ }
216
+ if (!isNull(validatedOutFrame) && validatedOutFrame > frames) {
217
+ throw new Error(
218
+ `[vidstack] \`outFrame\` must be less than (durationInFrames), but is \`${validatedOutFrame}\``
219
+ );
220
+ }
221
+ if (!isNull(validatedInFrame) && validatedInFrame < 0) {
222
+ throw new Error(
223
+ `[vidstack] \`inFrame\` must be greater than 0, but is \`${validatedInFrame}\``
224
+ );
225
+ }
226
+ if (!isNull(validatedOutFrame) && validatedOutFrame <= 0) {
227
+ throw new Error(
228
+ `[vidstack] \`outFrame\` must be greater than 0, but is \`${validatedOutFrame}\`. If you want to render a single frame, use \`<RemotionThumbnail />\` instead.`
229
+ );
230
+ }
231
+ if (!isNull(validatedOutFrame) && !isNull(validatedInFrame) && validatedOutFrame <= validatedInFrame) {
232
+ throw new Error(
233
+ "[vidstack] `outFrame` must be greater than `inFrame`, but is " + validatedOutFrame + " <= " + validatedInFrame
234
+ );
235
+ }
236
+ }
237
+ function validateSharedNumberOfAudioTags(tags) {
238
+ if (isUndefined(tags)) return;
239
+ if (tags % 1 !== 0 || !Number.isFinite(tags) || Number.isNaN(tags) || tags < 0) {
240
+ throw new TypeError(
241
+ `[vidstack] \`numberOfSharedAudioTags\` must be an integer but got \`${tags}\` instead`
242
+ );
243
+ }
244
+ }
245
+ function validatePlaybackRate(playbackRate) {
246
+ if (playbackRate > 4) {
247
+ throw new Error(
248
+ `[vidstack] The highest possible playback rate with Remotion is 4. You passed: ${playbackRate}`
249
+ );
250
+ }
251
+ if (playbackRate < -4) {
252
+ throw new Error(
253
+ `[vidstack] The lowest possible playback rate with Remotion is -4. You passed: ${playbackRate}`
254
+ );
255
+ }
256
+ if (playbackRate === 0) {
257
+ throw new Error(`[vidstack] A playback rate of 0 is not supported.`);
258
+ }
259
+ }
260
+ function validateComponent(src) {
261
+ if (src.type === Composition) {
262
+ throw new TypeError(
263
+ `[vidstack] \`src\` should not be an instance of \`<Composition/>\`. Pass the React component directly, and set the duration, fps and dimensions as source props.`
264
+ );
265
+ }
266
+ if (src === Composition) {
267
+ throw new TypeError(
268
+ `[vidstack] \`src\` must not be the \`Composition\` component. Pass your own React component directly, and set the duration, fps and dimensions as source props.`
269
+ );
270
+ }
271
+ }
272
+
273
+ class RemotionProvider {
274
+ $$PROVIDER_TYPE = "REMOTION";
275
+ scope = createScope();
276
+ #src = signal(null);
277
+ #setup = false;
278
+ #loadStart = false;
279
+ #audio = null;
280
+ #waiting = signal(false);
281
+ #waitingPromise = null;
282
+ #mediaTags = signal([]);
283
+ #mediaElements = signal([]);
284
+ #bufferingElements = /* @__PURE__ */ new Set();
285
+ #timeline = null;
286
+ #frame = signal({ [REMOTION_PROVIDER_ID]: 0 });
287
+ #layoutEngine = new RemotionLayoutEngine();
288
+ #playbackEngine = null;
289
+ #container;
290
+ #ctx;
291
+ #setTimeline;
292
+ #setMediaVolume = {
293
+ setMediaMuted: this.setMuted.bind(this),
294
+ setMediaVolume: this.setVolume.bind(this)
295
+ };
296
+ get type() {
297
+ return "remotion";
298
+ }
299
+ get currentSrc() {
300
+ return peek(this.#src);
301
+ }
302
+ get frame() {
303
+ return this.#frame();
304
+ }
305
+ constructor(container, ctx) {
306
+ this.#container = container;
307
+ this.#ctx = ctx;
308
+ this.#setTimeline = {
309
+ setFrame: this.#setFrame.bind(this),
310
+ setPlaying: this.#setPlaying.bind(this)
311
+ };
312
+ this.#layoutEngine.setContainer(container);
313
+ }
314
+ setup() {
315
+ effect(this.#watchWaiting.bind(this));
316
+ effect(this.#watchMediaTags.bind(this));
317
+ effect(this.#watchMediaElements.bind(this));
318
+ }
319
+ #watchMediaTags() {
320
+ this.#mediaTags();
321
+ this.#discoverMediaElements();
322
+ }
323
+ #discoverMediaElements() {
324
+ const elements = [...this.#container.querySelectorAll("audio,video")];
325
+ this.#mediaElements.set(elements);
326
+ }
327
+ #watchMediaElements() {
328
+ const elements = this.#mediaElements();
329
+ for (const tag of elements) {
330
+ const onWait = this.#onWaitFor.bind(this, tag), onStopWaiting = this.#onStopWaitingFor.bind(this, tag);
331
+ if (tag.currentSrc && tag.readyState < 4) {
332
+ this.#onWaitFor(tag);
333
+ listenEvent(tag, "canplay", onStopWaiting);
334
+ }
335
+ listenEvent(tag, "waiting", onWait);
336
+ listenEvent(tag, "playing", onStopWaiting);
337
+ }
338
+ for (const el of this.#bufferingElements) {
339
+ if (!elements.includes(el)) this.#onStopWaitingFor(el);
340
+ }
341
+ }
342
+ #onFrameChange(frame) {
343
+ const { inFrame, fps } = this.#src(), { seeking } = this.#ctx.$state, time = Math.max(0, frame - inFrame) / fps;
344
+ this.#frame.set((record) => ({
345
+ ...record,
346
+ [REMOTION_PROVIDER_ID]: frame
347
+ }));
348
+ this.#ctx.notify("time-change", time);
349
+ if (seeking()) {
350
+ tick();
351
+ this.#ctx.notify("seeked", time);
352
+ }
353
+ }
354
+ #onFrameEnd() {
355
+ this.pause();
356
+ this.#ctx.notify("end");
357
+ }
358
+ async play() {
359
+ const { ended } = this.#ctx.$state;
360
+ if (peek(ended)) {
361
+ this.#setFrame({ [REMOTION_PROVIDER_ID]: 0 });
362
+ }
363
+ try {
364
+ const mediaElements = peek(this.#mediaElements);
365
+ if (mediaElements.length) {
366
+ await Promise.all(mediaElements.map((media) => media.play()));
367
+ }
368
+ this.#ctx.notify("play");
369
+ tick();
370
+ if (this.#waitingPromise) {
371
+ this.#ctx.notify("waiting");
372
+ return this.#waitingPromise.promise;
373
+ } else {
374
+ this.#playbackEngine?.play();
375
+ this.#ctx.notify("playing");
376
+ }
377
+ } catch (error) {
378
+ throw error;
379
+ }
380
+ }
381
+ async pause() {
382
+ const { paused } = this.#ctx.$state;
383
+ this.#playbackEngine?.stop();
384
+ this.#ctx.notify("pause");
385
+ }
386
+ setMuted(value) {
387
+ if (!this.#ctx) return;
388
+ const { muted, volume } = this.#ctx.$state;
389
+ if (isFunction(value)) {
390
+ this.setMuted(value(muted()));
391
+ return;
392
+ }
393
+ this.#ctx.notify("volume-change", {
394
+ volume: peek(volume),
395
+ muted: value
396
+ });
397
+ }
398
+ setCurrentTime(time) {
399
+ const { fps } = this.#src(), frame = time * fps;
400
+ this.#ctx.notify("seeking", time);
401
+ this.#setFrame({ [REMOTION_PROVIDER_ID]: frame });
402
+ }
403
+ setVolume(value) {
404
+ if (!this.#ctx) return;
405
+ const { volume, muted } = this.#ctx.$state;
406
+ if (isFunction(value)) {
407
+ this.setVolume(value(volume()));
408
+ return;
409
+ }
410
+ this.#ctx.notify("volume-change", {
411
+ volume: value,
412
+ muted: peek(muted)
413
+ });
414
+ }
415
+ setPlaybackRate(rate) {
416
+ if (isFunction(rate)) {
417
+ const { playbackRate } = this.#ctx.$state;
418
+ this.setPlaybackRate(rate(peek(playbackRate)));
419
+ return;
420
+ }
421
+ validatePlaybackRate(rate);
422
+ this.#playbackEngine?.setPlaybackRate(rate);
423
+ this.#ctx.notify("rate-change", rate);
424
+ }
425
+ async loadSource(src) {
426
+ if (!isRemotionSrc(src)) return;
427
+ const onUserError = src.onError, resolvedSrc = {
428
+ compositionWidth: 1920,
429
+ compositionHeight: 1080,
430
+ fps: 30,
431
+ initialFrame: 0,
432
+ inFrame: 0,
433
+ outFrame: src.durationInFrames,
434
+ numberOfSharedAudioTags: 5,
435
+ inputProps: {},
436
+ ...src,
437
+ onError: (error) => {
438
+ {
439
+ this.#ctx.logger?.errorGroup(`[vidstack] ${error.message}`).labelledLog("Source", peek(this.#src)).labelledLog("Error", error).dispatch();
440
+ }
441
+ this.pause();
442
+ this.#ctx.notify("error", {
443
+ message: error.message,
444
+ code: 1
445
+ });
446
+ onUserError?.(error);
447
+ }
448
+ };
449
+ this.#src.set(resolvedSrc);
450
+ for (const prop of Object.keys(resolvedSrc)) {
451
+ src[prop] = resolvedSrc[prop];
452
+ }
453
+ this.changeSrc(resolvedSrc);
454
+ }
455
+ destroy() {
456
+ this.changeSrc(null);
457
+ }
458
+ changeSrc(src) {
459
+ this.#playbackEngine?.destroy();
460
+ this.#waiting.set(false);
461
+ this.#waitingPromise?.reject("src changed");
462
+ this.#waitingPromise = null;
463
+ this.#audio = null;
464
+ this.#timeline = null;
465
+ this.#playbackEngine = null;
466
+ this.#mediaTags.set([]);
467
+ this.#bufferingElements.clear();
468
+ this.#frame.set({ [REMOTION_PROVIDER_ID]: 0 });
469
+ this.#layoutEngine.setSrc(src);
470
+ if (src) {
471
+ this.#timeline = this.#createTimelineContextValue();
472
+ this.#playbackEngine = new RemotionPlaybackEngine(
473
+ src,
474
+ this.#onFrameChange.bind(this),
475
+ this.#onFrameEnd.bind(this)
476
+ );
477
+ }
478
+ }
479
+ render = () => {
480
+ const $src = useSignal(this.#src);
481
+ if (!$src) {
482
+ throw Error(
483
+ "[vidstack] attempting to render remotion provider without src"
484
+ );
485
+ }
486
+ React.useEffect(() => {
487
+ if (!isRemotionSrc($src)) return;
488
+ validateRemotionResource($src);
489
+ const rafId = requestAnimationFrame(() => {
490
+ if (!this.#setup) {
491
+ this.#ctx.notify("provider-setup", this);
492
+ this.#setup = true;
493
+ }
494
+ if (!this.#loadStart) {
495
+ this.#ctx.notify("load-start");
496
+ this.#loadStart = true;
497
+ }
498
+ this.#discoverMediaElements();
499
+ tick();
500
+ if (!this.#waiting()) this.#ready($src);
501
+ });
502
+ return () => {
503
+ cancelAnimationFrame(rafId);
504
+ this.#loadStart = false;
505
+ };
506
+ }, [$src]);
507
+ const Component = Internals.useLazyComponent({
508
+ component: $src.src
509
+ });
510
+ const { $state } = this.#ctx, $volume = useSignal($state.volume), $isMuted = useSignal($state.muted);
511
+ const mediaVolume = React.useMemo(() => {
512
+ const { muted, volume } = this.#ctx.$state;
513
+ return { mediaMuted: muted(), mediaVolume: volume() };
514
+ }, [$isMuted, $volume]);
515
+ return /* @__PURE__ */ React.createElement(
516
+ RemotionContextProvider,
517
+ {
518
+ src: $src,
519
+ component: Component,
520
+ timeline: this.#timeline,
521
+ mediaVolume,
522
+ setMediaVolume: this.#setMediaVolume
523
+ },
524
+ /* @__PURE__ */ React.createElement(Internals.Timeline.SetTimelineContext.Provider, { value: this.#setTimeline }, React.createElement(this.renderVideo, { src: $src }))
525
+ );
526
+ };
527
+ renderVideo = ({ src }) => {
528
+ const video = Internals.useVideo(), Video = video ? video.component : null, audioContext = React.useContext(Internals.SharedAudioContext);
529
+ const { $state } = this.#ctx;
530
+ useSignal(this.#frame);
531
+ useSignal($state.playing);
532
+ useSignal($state.playbackRate);
533
+ React.useEffect(() => {
534
+ this.#audio = audioContext;
535
+ return () => {
536
+ this.#audio = null;
537
+ };
538
+ }, [audioContext]);
539
+ const LoadingContent = React.useMemo(() => src.renderLoading?.(), [src]);
540
+ const Content = Video ? /* @__PURE__ */ React.createElement(ErrorBoundary, { fallback: src.errorFallback, onError: src.onError }, /* @__PURE__ */ React.createElement(Internals.ClipComposition, null, /* @__PURE__ */ React.createElement(Video, { ...video?.props, ...src.inputProps }))) : null;
541
+ return /* @__PURE__ */ React.createElement(React.Suspense, { fallback: LoadingContent }, Content);
542
+ };
543
+ #ready(src) {
544
+ if (!src) return;
545
+ const { outFrame, inFrame, fps } = src, duration = (outFrame - inFrame) / fps;
546
+ this.#ctx.notify("loaded-metadata");
547
+ this.#ctx.notify("loaded-data");
548
+ this.#ctx.delegate.ready({
549
+ duration,
550
+ seekable: new TimeRange(0, duration),
551
+ buffered: new TimeRange(0, duration)
552
+ });
553
+ if (src.initialFrame) {
554
+ this.#setFrame({
555
+ [REMOTION_PROVIDER_ID]: src.initialFrame
556
+ });
557
+ }
558
+ }
559
+ #onWaitFor(el) {
560
+ this.#bufferingElements.add(el);
561
+ this.#waiting.set(true);
562
+ if (!this.#waitingPromise) {
563
+ this.#waitingPromise = deferredPromise();
564
+ }
565
+ }
566
+ #onStopWaitingFor(el) {
567
+ this.#bufferingElements.delete(el);
568
+ if (this.#bufferingElements.size) return;
569
+ this.#waiting.set(false);
570
+ this.#waitingPromise?.resolve();
571
+ this.#waitingPromise = null;
572
+ const { canPlay } = this.#ctx.$state;
573
+ if (!peek(canPlay)) {
574
+ this.#ready(peek(this.#src));
575
+ }
576
+ }
577
+ #watchWaiting() {
578
+ this.#waiting();
579
+ const { paused } = this.#ctx.$state;
580
+ if (peek(paused)) return;
581
+ if (this.#waiting()) {
582
+ this.#playbackEngine?.stop();
583
+ this.#ctx.notify("waiting");
584
+ } else {
585
+ this.#playbackEngine?.play();
586
+ this.#ctx.notify("playing");
587
+ }
588
+ }
589
+ #setFrame(value) {
590
+ if (isFunction(value)) {
591
+ this.#setFrame(value(this.#frame()));
592
+ return;
593
+ }
594
+ this.#frame.set((record) => ({ ...record, ...value }));
595
+ const nextFrame = value[REMOTION_PROVIDER_ID];
596
+ if (this.#playbackEngine && this.#playbackEngine.frame !== nextFrame) {
597
+ this.#playbackEngine.frame = nextFrame;
598
+ }
599
+ }
600
+ #setPlaying(value) {
601
+ const { playing } = this.#ctx.$state;
602
+ if (isFunction(value)) {
603
+ this.#setPlaying(value(playing()));
604
+ return;
605
+ }
606
+ if (value) {
607
+ this.play();
608
+ } else if (!value) {
609
+ this.pause();
610
+ }
611
+ }
612
+ #createTimelineContextValue() {
613
+ const { playing, playbackRate } = this.#ctx.$state, frame = this.#frame, mediaTags = this.#mediaTags, setPlaybackRate = this.setPlaybackRate.bind(this);
614
+ return {
615
+ rootId: REMOTION_PROVIDER_ID,
616
+ get frame() {
617
+ return frame();
618
+ },
619
+ get playing() {
620
+ return playing();
621
+ },
622
+ get playbackRate() {
623
+ return playbackRate();
624
+ },
625
+ imperativePlaying: {
626
+ get current() {
627
+ return playing();
628
+ }
629
+ },
630
+ setPlaybackRate,
631
+ audioAndVideoTags: {
632
+ get current() {
633
+ return mediaTags();
634
+ },
635
+ set current(tags) {
636
+ mediaTags.set(tags);
637
+ }
638
+ }
639
+ };
640
+ }
641
+ }
642
+
643
+ export { RemotionProvider };