@vanillaskyai/video 0.10.6 → 0.10.8
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.
- package/CHANGELOG.md +21 -0
- package/dist/{chapter-title-YRLIQY3V.js → chapter-title-2JVDU62E.js} +1 -1
- package/dist/check-runtime.js +2 -2
- package/dist/{chunk-EWWCQFTI.js → chunk-7AA2JWHZ.js} +3 -2
- package/dist/{chunk-DD4ZSYKG.js → chunk-J7EGPURK.js} +309 -129
- package/dist/{chunk-VWJBIYBM.js → chunk-KUCEOG2L.js} +53 -132
- package/dist/{chunk-XBIKTSFY.js → chunk-Q3LPOPHL.js} +1 -1
- package/dist/{chunk-JNZRVC45.js → chunk-R5ZX2LJV.js} +1 -1
- package/dist/{cinema-media-AYKCBXRI.js → cinema-media-WUS7CKPC.js} +3 -4
- package/dist/{comparison-74B2XEH4.js → comparison-T4OYCOH3.js} +3 -4
- package/dist/{editorial-timeline-DUW7C75H.js → editorial-timeline-JHQZIPNE.js} +3 -4
- package/dist/{key-figure-OEWIMPGS.js → key-figure-YWN2OBQU.js} +3 -4
- package/dist/{mobile-message-KBLF3WUR.js → mobile-message-CDKOERRZ.js} +3 -4
- package/dist/{quote-QCGR2HOU.js → quote-JKABOMIG.js} +3 -4
- package/dist/react.js +36 -22
- package/dist/server.js +15 -5
- package/package.json +1 -1
- package/registry/items/backgrounds.json +2 -2
- package/registry/items/chapterTitle.json +1 -1
- package/starters/video-chat/README.md +4 -8
- package/starters/video-chat/package.json +1 -1
- package/starters/video-chat/server.ts +0 -5
- package/dist/chunk-MGCD3ZJ3.js +0 -207
- package/dist/scene-video-backdrop-MUGIXE2Q.js +0 -7
- package/dist/{chunk-OOBT4X46.js → chunk-5JBMYQP6.js} +34 -34
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ExternalVideoBackdropProvider,
|
|
3
|
+
resolveDensity
|
|
4
|
+
} from "./chunk-5JBMYQP6.js";
|
|
1
5
|
import {
|
|
2
6
|
limitsConcurrentVideoDecoders,
|
|
3
7
|
resolveMediaType
|
|
4
8
|
} from "./chunk-224QNWRA.js";
|
|
5
|
-
import {
|
|
6
|
-
ExternalVideoBackdropProvider,
|
|
7
|
-
resolveDensity
|
|
8
|
-
} from "./chunk-OOBT4X46.js";
|
|
9
9
|
import {
|
|
10
10
|
resolveVideoTimeline
|
|
11
11
|
} from "./chunk-SPVTJH3F.js";
|
|
@@ -33,17 +33,19 @@ function MountedSceneReadiness({ scene, playing, fallback = false, onFailure })
|
|
|
33
33
|
let frame = 0;
|
|
34
34
|
let callback;
|
|
35
35
|
let observed;
|
|
36
|
+
let presented;
|
|
37
|
+
const root = marker.current?.closest("[data-video-frame]");
|
|
36
38
|
const start = performance.now();
|
|
37
39
|
const finish = (error, actualVideoFrame = false) => {
|
|
38
40
|
if (!stopped) {
|
|
39
41
|
stopped = true;
|
|
42
|
+
if (callback !== void 0) observed?.cancelVideoFrameCallback?.(callback);
|
|
40
43
|
if (error && onFailureRef.current) onFailureRef.current();
|
|
41
44
|
else report(key, error, actualVideoFrame);
|
|
42
45
|
}
|
|
43
46
|
};
|
|
44
47
|
const check = () => {
|
|
45
48
|
if (stopped) return;
|
|
46
|
-
const root = marker.current?.closest("[data-video-frame]");
|
|
47
49
|
if (fallback && root?.querySelector("[data-scene-fallback]") && !root.querySelector("[data-template-loading]") && document.fonts?.status !== "loading") {
|
|
48
50
|
finish();
|
|
49
51
|
return;
|
|
@@ -58,9 +60,12 @@ function MountedSceneReadiness({ scene, playing, fallback = false, onFailure })
|
|
|
58
60
|
return;
|
|
59
61
|
}
|
|
60
62
|
if (isVideo) {
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
63
|
+
const video = layer.querySelector("video");
|
|
64
|
+
if (video && video.getAttribute("src") === mediaUrl && video.currentSrc === video.src && video.readyState >= 2) {
|
|
65
|
+
if (presented === video) {
|
|
66
|
+
finish(void 0, true);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
64
69
|
observed = video;
|
|
65
70
|
if (video.requestVideoFrameCallback) {
|
|
66
71
|
callback = video.requestVideoFrameCallback(() => finish(void 0, true));
|
|
@@ -83,9 +88,20 @@ function MountedSceneReadiness({ scene, playing, fallback = false, onFailure })
|
|
|
83
88
|
}
|
|
84
89
|
frame = requestAnimationFrame(check);
|
|
85
90
|
};
|
|
91
|
+
const onPresented = (event) => {
|
|
92
|
+
const video = event.target;
|
|
93
|
+
if (!(video instanceof HTMLVideoElement) || stopped || video.getAttribute("src") !== String(scene.variables.mediaUrl || "") || video.currentSrc !== video.src) return;
|
|
94
|
+
presented = video;
|
|
95
|
+
cancelAnimationFrame(frame);
|
|
96
|
+
if (callback !== void 0) observed?.cancelVideoFrameCallback?.(callback);
|
|
97
|
+
callback = void 0;
|
|
98
|
+
check();
|
|
99
|
+
};
|
|
100
|
+
root?.addEventListener("vanillasky:video-frame-presented", onPresented);
|
|
86
101
|
check();
|
|
87
102
|
const timeout = setTimeout(() => finish(new Error("Scene media did not become ready")), 8e3);
|
|
88
103
|
return () => {
|
|
104
|
+
root?.removeEventListener("vanillasky:video-frame-presented", onPresented);
|
|
89
105
|
stopped = true;
|
|
90
106
|
clearTimeout(timeout);
|
|
91
107
|
cancelAnimationFrame(frame);
|
|
@@ -94,47 +110,14 @@ function MountedSceneReadiness({ scene, playing, fallback = false, onFailure })
|
|
|
94
110
|
}, [key, report, scene, playing, fallback]);
|
|
95
111
|
return /* @__PURE__ */ jsx("span", { ref: marker, hidden: true });
|
|
96
112
|
}
|
|
97
|
-
function PreparedSceneReadiness({ scene }) {
|
|
98
|
-
const marker = useRef(null);
|
|
99
|
-
const report = useContext(MountedReadinessContext);
|
|
100
|
-
useEffect(() => {
|
|
101
|
-
if (!report) return;
|
|
102
|
-
let frame = 0;
|
|
103
|
-
let stopped = false;
|
|
104
|
-
const check = () => {
|
|
105
|
-
if (stopped) return;
|
|
106
|
-
const root = marker.current?.closest("[data-video-frame]");
|
|
107
|
-
const incoming = root?.querySelector("[data-scene-layer='incoming']");
|
|
108
|
-
const video = incoming?.getAttribute("data-layer-scene-id") === scene.id ? incoming.querySelector("video") : void 0;
|
|
109
|
-
if (video && video.getAttribute("src") === scene.variables.mediaUrl && video.readyState >= 2) {
|
|
110
|
-
report(sceneReadinessKey(scene), void 0, false, true);
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
const image = [...root?.querySelectorAll("img[data-video-poster-plane='prepared']") ?? []].find((image2) => image2.getAttribute("src") === scene.variables.mediaPoster);
|
|
114
|
-
if (image?.complete && image.naturalWidth > 0) {
|
|
115
|
-
void image.decode().then(() => {
|
|
116
|
-
if (!stopped && image.isConnected) report(sceneReadinessKey(scene), void 0, false, true);
|
|
117
|
-
}).catch(() => void 0);
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
frame = requestAnimationFrame(check);
|
|
121
|
-
};
|
|
122
|
-
check();
|
|
123
|
-
return () => {
|
|
124
|
-
stopped = true;
|
|
125
|
-
cancelAnimationFrame(frame);
|
|
126
|
-
};
|
|
127
|
-
}, [scene, report]);
|
|
128
|
-
return /* @__PURE__ */ jsx("span", { ref: marker, hidden: true });
|
|
129
|
-
}
|
|
130
113
|
|
|
131
114
|
// src/player/video-frame.tsx
|
|
132
115
|
import {
|
|
133
116
|
createElement,
|
|
134
117
|
Component,
|
|
135
|
-
lazy,
|
|
136
118
|
Suspense,
|
|
137
119
|
useState,
|
|
120
|
+
useRef as useRef2,
|
|
138
121
|
useCallback,
|
|
139
122
|
useEffect as useEffect2,
|
|
140
123
|
useSyncExternalStore
|
|
@@ -209,7 +192,6 @@ var SceneBoundary = class extends Component {
|
|
|
209
192
|
}
|
|
210
193
|
};
|
|
211
194
|
var SCENE_TRANSITION_SECONDS = 0.3;
|
|
212
|
-
var SceneVideoBackdrop = lazy(() => import("./scene-video-backdrop-MUGIXE2Q.js").then((module) => ({ default: module.SceneVideoBackdrop })));
|
|
213
195
|
var MEDIA_PREROLL_SECONDS = 1.2;
|
|
214
196
|
var CONTIGUITY_ULP_FACTOR = 4;
|
|
215
197
|
var subscribeToDecoderPolicy = () => () => {
|
|
@@ -369,19 +351,25 @@ function VideoFrame({
|
|
|
369
351
|
className,
|
|
370
352
|
style
|
|
371
353
|
}) {
|
|
354
|
+
const recoveryRoot = useRef2(null);
|
|
355
|
+
const reportedFailures = useRef2(/* @__PURE__ */ new Set());
|
|
372
356
|
const [failedMedia, setFailedMedia] = useState(() => /* @__PURE__ */ new Set());
|
|
373
|
-
const markMediaFailed = useCallback((key) => {
|
|
357
|
+
const markMediaFailed = useCallback((key, reason = "playback-error") => {
|
|
374
358
|
if (!key || !config.scenes.some((scene) => sceneReadinessKey(scene) === key)) return;
|
|
359
|
+
if (!reportedFailures.current.has(key)) {
|
|
360
|
+
reportedFailures.current.add(key);
|
|
361
|
+
recoveryRoot.current?.dispatchEvent(new CustomEvent("vanillasky:media-recovery", { bubbles: true, detail: { reason: ["decode-error", "frame-readiness-timeout", "stalled-media", "playback-error"].includes(reason) ? reason : "playback-error" } }));
|
|
362
|
+
}
|
|
375
363
|
setFailedMedia((previous) => previous.has(key) ? previous : /* @__PURE__ */ new Set([...previous, key]));
|
|
376
364
|
}, [config.scenes]);
|
|
377
365
|
useEffect2(() => {
|
|
378
366
|
const currentKeys = new Set(config.scenes.map(sceneReadinessKey));
|
|
367
|
+
for (const key of reportedFailures.current) if (!currentKeys.has(key)) reportedFailures.current.delete(key);
|
|
379
368
|
setFailedMedia((previous) => {
|
|
380
369
|
const retained = new Set([...previous].filter((key) => currentKeys.has(key)));
|
|
381
370
|
return retained.size === previous.size ? previous : retained;
|
|
382
371
|
});
|
|
383
372
|
}, [config.scenes]);
|
|
384
|
-
const [readyPersistentVideo, setReadyPersistentVideo] = useState();
|
|
385
373
|
const decoderConstrainedDevice = useDecoderConstraint();
|
|
386
374
|
const timeline = resolveVideoTimeline(config);
|
|
387
375
|
const lastRange = timeline.at(-1);
|
|
@@ -435,35 +423,13 @@ function VideoFrame({
|
|
|
435
423
|
);
|
|
436
424
|
const prerollDuration = prerollsNext ? Math.min(Math.max(MEDIA_PREROLL_SECONDS, blendDuration), Math.max(0, duration)) : blendDuration;
|
|
437
425
|
const prerollStart = active.end - prerollDuration;
|
|
426
|
+
const boundedPreparation = decoderConstrainedDevice && registrySupportsExternalVideoBackdrop(kit);
|
|
438
427
|
const decoderConstrainedTransition = Boolean(
|
|
439
|
-
contiguousNext && decoderConstrainedDevice && sceneHasVideoBackdrop(active) && sceneHasVideoBackdrop(contiguousNext)
|
|
428
|
+
contiguousNext && decoderConstrainedDevice && !boundedPreparation && sceneHasVideoBackdrop(active) && sceneHasVideoBackdrop(contiguousNext)
|
|
440
429
|
);
|
|
441
|
-
const persistentVideoEnabled = decoderConstrainedDevice && registrySupportsExternalVideoBackdrop(kit);
|
|
442
|
-
const activeUsesPersistentVideo = persistentVideoEnabled && sceneHasVideoBackdrop(active);
|
|
443
|
-
const incomingUsesPersistentVideo = Boolean(
|
|
444
|
-
persistentVideoEnabled && contiguousNext && !sceneHasVideoBackdrop(active) && sceneHasVideoBackdrop(contiguousNext) && time >= prerollStart && time < blendEnd
|
|
445
|
-
);
|
|
446
|
-
const persistentVideoRange = activeUsesPersistentVideo ? active : incomingUsesPersistentVideo && contiguousNext ? contiguousNext : void 0;
|
|
447
|
-
const persistentVideoKey = persistentVideoRange ? `${persistentVideoRange.scene.id}\0${String(persistentVideoRange.scene.variables.mediaUrl || "")}` : void 0;
|
|
448
|
-
const firstVideoRange = timeline.find(sceneHasVideoBackdrop);
|
|
449
|
-
const posterPreparationRange = activeUsesPersistentVideo ? contiguousNext && sceneHasVideoBackdrop(contiguousNext) ? contiguousNext : activeIndex === timeline.length - 1 && firstVideoRange?.scene.id !== active.scene.id ? firstVideoRange : void 0 : void 0;
|
|
450
|
-
const preparedReadinessRange = posterPreparationRange ?? (contiguousNext && sceneHasVideoBackdrop(contiguousNext) ? contiguousNext : void 0);
|
|
451
|
-
const preparedPoster = posterPreparationRange && String(
|
|
452
|
-
posterPreparationRange.scene.variables.mediaPoster || ""
|
|
453
|
-
) ? {
|
|
454
|
-
presentationKey: `${posterPreparationRange.scene.id}\0${String(
|
|
455
|
-
posterPreparationRange.scene.variables.mediaUrl || ""
|
|
456
|
-
)}`,
|
|
457
|
-
mediaPoster: String(posterPreparationRange.scene.variables.mediaPoster),
|
|
458
|
-
mediaPosition: String(posterPreparationRange.scene.variables.mediaPosition || "center"),
|
|
459
|
-
backgroundEffect: posterPreparationRange.scene.backgroundEffect ?? config.style.defaultBackgroundEffect
|
|
460
|
-
} : void 0;
|
|
461
430
|
const activeMediaFailed = failedMedia.has(sceneReadinessKey(active.scene));
|
|
462
|
-
const persistentVideoFailed = persistentVideoKey !== void 0 && failedMedia.has(persistentVideoKey);
|
|
463
|
-
const persistentVideoReady = persistentVideoRange !== void 0 && (String(persistentVideoRange.scene.variables.mediaPoster || "") !== "" || readyPersistentVideo === persistentVideoKey);
|
|
464
|
-
const persistentVideoMode = persistentVideoFailed ? "fallback" : persistentVideoReady ? "ready" : "pending";
|
|
465
431
|
const mountingNext = Boolean(
|
|
466
|
-
contiguousNext && !decoderConstrainedTransition && time >= prerollStart && time < blendEnd && (eligibleNextTransition || prerollsNext)
|
|
432
|
+
contiguousNext && !decoderConstrainedTransition && (boundedPreparation || time >= prerollStart) && time < blendEnd && (eligibleNextTransition || prerollsNext || boundedPreparation && sceneHasVideoBackdrop(contiguousNext))
|
|
467
433
|
);
|
|
468
434
|
const previewingNext = Boolean(
|
|
469
435
|
eligibleNextTransition && time >= blendStart && time < blendEnd
|
|
@@ -471,7 +437,9 @@ function VideoFrame({
|
|
|
471
437
|
const blendProgress = previewingNext && blendDuration > 0 ? Math.round(clamp01((time - blendStart) / blendDuration) * 1e6) / 1e6 : 0;
|
|
472
438
|
const progress = rawProgress;
|
|
473
439
|
const isFinalScene = activeIndex === timeline.length - 1;
|
|
474
|
-
const
|
|
440
|
+
const presentsChapter = active.scene.templateId === "chapterTitle" || active.scene.templateId === "cinemaMedia" && (activeMediaFailed || !String(active.scene.variables.mediaUrl || "").trim());
|
|
441
|
+
const finalHold = presentsChapter ? 0.76 : activeTiming?.holdProgress;
|
|
442
|
+
const motionProgress = isFinalScene && finalHold !== void 0 ? Math.min(rawProgress, finalHold) : rawProgress;
|
|
475
443
|
const canvas = getDimensions(config.orientation);
|
|
476
444
|
const scale = Math.min(width / canvas.width, height / canvas.height);
|
|
477
445
|
const canvasLeft = (width - canvas.width * scale) / 2;
|
|
@@ -479,10 +447,15 @@ function VideoFrame({
|
|
|
479
447
|
return /* @__PURE__ */ jsxs(
|
|
480
448
|
"div",
|
|
481
449
|
{
|
|
450
|
+
ref: recoveryRoot,
|
|
482
451
|
onErrorCapture: (event) => {
|
|
483
452
|
const target = event.target;
|
|
484
|
-
if ((target instanceof HTMLVideoElement || target instanceof HTMLImageElement)
|
|
485
|
-
|
|
453
|
+
if (!(target instanceof HTMLVideoElement || target instanceof HTMLImageElement)) return;
|
|
454
|
+
const ownerId = target.closest("[data-layer-scene-id]")?.getAttribute("data-layer-scene-id");
|
|
455
|
+
const owner = [active, contiguousNext].find((range) => range?.scene.id === ownerId);
|
|
456
|
+
const template = owner && kit.getTemplate(owner.scene.templateId);
|
|
457
|
+
if (owner && template && supportsExternalVideoBackdrop(template) && target.getAttribute("src") === owner.scene.variables.mediaUrl) {
|
|
458
|
+
markMediaFailed(sceneReadinessKey(owner.scene), "decode-error");
|
|
486
459
|
}
|
|
487
460
|
},
|
|
488
461
|
"data-video-frame": "ready",
|
|
@@ -504,10 +477,9 @@ function VideoFrame({
|
|
|
504
477
|
scene: active.scene,
|
|
505
478
|
playing,
|
|
506
479
|
fallback: activeMediaFailed,
|
|
507
|
-
onFailure: sceneHasBackdrop(active) && supportsExternalVideoBackdrop(activeTemplate) && !activeMediaFailed ? () => markMediaFailed(sceneReadinessKey(active.scene)) : void 0
|
|
480
|
+
onFailure: sceneHasBackdrop(active) && supportsExternalVideoBackdrop(activeTemplate) && !activeMediaFailed ? () => markMediaFailed(sceneReadinessKey(active.scene), "frame-readiness-timeout") : void 0
|
|
508
481
|
}
|
|
509
482
|
),
|
|
510
|
-
preparedReadinessRange && /* @__PURE__ */ jsx2(PreparedSceneReadiness, { scene: preparedReadinessRange.scene }),
|
|
511
483
|
/* @__PURE__ */ jsxs(
|
|
512
484
|
"div",
|
|
513
485
|
{
|
|
@@ -536,58 +508,6 @@ function VideoFrame({
|
|
|
536
508
|
}
|
|
537
509
|
}
|
|
538
510
|
),
|
|
539
|
-
persistentVideoRange && !persistentVideoFailed && /* @__PURE__ */ jsx2(
|
|
540
|
-
"div",
|
|
541
|
-
{
|
|
542
|
-
"data-persistent-video-scene-id": persistentVideoRange.scene.id,
|
|
543
|
-
"aria-hidden": "true",
|
|
544
|
-
style: { position: "absolute", inset: 0, zIndex: 0 },
|
|
545
|
-
children: /* @__PURE__ */ jsx2(Suspense, { fallback: String(persistentVideoRange.scene.variables.mediaPoster || "") ? /* @__PURE__ */ jsx2(
|
|
546
|
-
"img",
|
|
547
|
-
{
|
|
548
|
-
src: String(persistentVideoRange.scene.variables.mediaPoster),
|
|
549
|
-
alt: "",
|
|
550
|
-
"data-video-poster-plane": "loading",
|
|
551
|
-
"data-video-poster-visible": "true",
|
|
552
|
-
style: {
|
|
553
|
-
position: "absolute",
|
|
554
|
-
inset: 0,
|
|
555
|
-
width: "100%",
|
|
556
|
-
height: "100%",
|
|
557
|
-
objectFit: "cover",
|
|
558
|
-
objectPosition: String(persistentVideoRange.scene.variables.mediaPosition || "center")
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
) : null, children: /* @__PURE__ */ jsx2(
|
|
562
|
-
SceneVideoBackdrop,
|
|
563
|
-
{
|
|
564
|
-
mediaUrl: String(persistentVideoRange.scene.variables.mediaUrl || ""),
|
|
565
|
-
mediaPoster: String(persistentVideoRange.scene.variables.mediaPoster || "") || void 0,
|
|
566
|
-
mediaPosition: String(persistentVideoRange.scene.variables.mediaPosition || "center"),
|
|
567
|
-
backgroundEffect: persistentVideoRange.scene.backgroundEffect ?? config.style.defaultBackgroundEffect,
|
|
568
|
-
progress: persistentVideoRange.scene.id === active.scene.id ? rawProgress : 0,
|
|
569
|
-
sceneDuration: persistentVideoRange.end - persistentVideoRange.start,
|
|
570
|
-
isPlaying: persistentVideoRange.scene.id === active.scene.id && playing,
|
|
571
|
-
preparingNarration,
|
|
572
|
-
muted: mediaAudioMuted || persistentVideoRange.scene.id !== active.scene.id || !playing,
|
|
573
|
-
volume: mediaAudioVolume,
|
|
574
|
-
playbackId: persistentVideoRange.scene.id,
|
|
575
|
-
retainPoster: true,
|
|
576
|
-
persistent: true,
|
|
577
|
-
preparedPoster: preparedPoster ? {
|
|
578
|
-
...preparedPoster,
|
|
579
|
-
// The image is already decoded and costs no second video
|
|
580
|
-
// decoder. Fade it above the outgoing video using the same
|
|
581
|
-
// authored transition clock, then reuse that exact DOM image
|
|
582
|
-
// as the new source's underlay at the cut.
|
|
583
|
-
opacity: decoderConstrainedTransition ? blendProgress : 0
|
|
584
|
-
} : void 0,
|
|
585
|
-
onReady: () => setReadyPersistentVideo(persistentVideoKey),
|
|
586
|
-
onError: () => markMediaFailed(persistentVideoKey)
|
|
587
|
-
}
|
|
588
|
-
) })
|
|
589
|
-
}
|
|
590
|
-
),
|
|
591
511
|
mountingNext && contiguousNext ? [
|
|
592
512
|
/* @__PURE__ */ jsx2(
|
|
593
513
|
SceneLayer,
|
|
@@ -596,7 +516,7 @@ function VideoFrame({
|
|
|
596
516
|
kit,
|
|
597
517
|
config,
|
|
598
518
|
range: active,
|
|
599
|
-
onMediaError: () => markMediaFailed(sceneReadinessKey(active.scene)),
|
|
519
|
+
onMediaError: (reason) => markMediaFailed(sceneReadinessKey(active.scene), reason),
|
|
600
520
|
progress,
|
|
601
521
|
motionProgress,
|
|
602
522
|
width: canvas.width,
|
|
@@ -609,7 +529,7 @@ function VideoFrame({
|
|
|
609
529
|
opacity: 1 - blendProgress,
|
|
610
530
|
interactive: true,
|
|
611
531
|
zIndex: 1,
|
|
612
|
-
externalVideoBackdrop: activeMediaFailed ? "fallback" :
|
|
532
|
+
externalVideoBackdrop: activeMediaFailed ? "fallback" : false
|
|
613
533
|
},
|
|
614
534
|
active.scene.id
|
|
615
535
|
),
|
|
@@ -631,7 +551,8 @@ function VideoFrame({
|
|
|
631
551
|
opacity: blendProgress,
|
|
632
552
|
interactive: false,
|
|
633
553
|
zIndex: 2,
|
|
634
|
-
|
|
554
|
+
onMediaError: (reason) => markMediaFailed(sceneReadinessKey(contiguousNext.scene), reason),
|
|
555
|
+
externalVideoBackdrop: failedMedia.has(sceneReadinessKey(contiguousNext.scene)) ? "fallback" : false
|
|
635
556
|
},
|
|
636
557
|
contiguousNext.scene.id
|
|
637
558
|
)
|
|
@@ -643,7 +564,7 @@ function VideoFrame({
|
|
|
643
564
|
kit,
|
|
644
565
|
config,
|
|
645
566
|
range: active,
|
|
646
|
-
onMediaError: () => markMediaFailed(sceneReadinessKey(active.scene)),
|
|
567
|
+
onMediaError: (reason) => markMediaFailed(sceneReadinessKey(active.scene), reason),
|
|
647
568
|
progress,
|
|
648
569
|
motionProgress,
|
|
649
570
|
width: canvas.width,
|
|
@@ -656,7 +577,7 @@ function VideoFrame({
|
|
|
656
577
|
opacity: 1,
|
|
657
578
|
interactive: true,
|
|
658
579
|
zIndex: 1,
|
|
659
|
-
externalVideoBackdrop: activeMediaFailed ? "fallback" :
|
|
580
|
+
externalVideoBackdrop: activeMediaFailed ? "fallback" : false
|
|
660
581
|
},
|
|
661
582
|
active.scene.id
|
|
662
583
|
)
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MediaScene,
|
|
3
3
|
MediaSceneTemplate
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-Q3LPOPHL.js";
|
|
5
|
+
import "./chunk-J7EGPURK.js";
|
|
6
|
+
import "./chunk-5JBMYQP6.js";
|
|
7
7
|
import "./chunk-224QNWRA.js";
|
|
8
|
-
import "./chunk-OOBT4X46.js";
|
|
9
8
|
export {
|
|
10
9
|
MediaScene,
|
|
11
10
|
MediaSceneTemplate
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
EditorialSurface
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-DD4ZSYKG.js";
|
|
3
|
+
} from "./chunk-R5ZX2LJV.js";
|
|
4
|
+
import "./chunk-J7EGPURK.js";
|
|
6
5
|
import {
|
|
7
6
|
editorialLabel,
|
|
8
7
|
fade
|
|
9
8
|
} from "./chunk-4YM2M62S.js";
|
|
9
|
+
import "./chunk-5JBMYQP6.js";
|
|
10
10
|
import {
|
|
11
11
|
hasSceneMedia
|
|
12
12
|
} from "./chunk-224QNWRA.js";
|
|
13
|
-
import "./chunk-OOBT4X46.js";
|
|
14
13
|
|
|
15
14
|
// src/visual-system/scene-templates/comparison.tsx
|
|
16
15
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
EditorialSurface
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-DD4ZSYKG.js";
|
|
3
|
+
} from "./chunk-R5ZX2LJV.js";
|
|
4
|
+
import "./chunk-J7EGPURK.js";
|
|
6
5
|
import {
|
|
7
6
|
fade
|
|
8
7
|
} from "./chunk-4YM2M62S.js";
|
|
8
|
+
import "./chunk-5JBMYQP6.js";
|
|
9
9
|
import "./chunk-224QNWRA.js";
|
|
10
|
-
import "./chunk-OOBT4X46.js";
|
|
11
10
|
|
|
12
11
|
// src/visual-system/scene-templates/editorial-timeline.tsx
|
|
13
12
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
EditorialSurface
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-DD4ZSYKG.js";
|
|
3
|
+
} from "./chunk-R5ZX2LJV.js";
|
|
4
|
+
import "./chunk-J7EGPURK.js";
|
|
6
5
|
import {
|
|
7
6
|
editorialLabel,
|
|
8
7
|
fade
|
|
9
8
|
} from "./chunk-4YM2M62S.js";
|
|
9
|
+
import "./chunk-5JBMYQP6.js";
|
|
10
10
|
import {
|
|
11
11
|
hasSceneMedia
|
|
12
12
|
} from "./chunk-224QNWRA.js";
|
|
13
|
-
import "./chunk-OOBT4X46.js";
|
|
14
13
|
|
|
15
14
|
// src/visual-system/scene-templates/key-figure.tsx
|
|
16
15
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MediaScene
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-MGCD3ZJ3.js";
|
|
3
|
+
} from "./chunk-Q3LPOPHL.js";
|
|
5
4
|
import {
|
|
6
5
|
spring
|
|
7
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-J7EGPURK.js";
|
|
8
7
|
import {
|
|
9
8
|
editorialFont
|
|
10
9
|
} from "./chunk-4YM2M62S.js";
|
|
10
|
+
import "./chunk-5JBMYQP6.js";
|
|
11
11
|
import "./chunk-224QNWRA.js";
|
|
12
|
-
import "./chunk-OOBT4X46.js";
|
|
13
12
|
|
|
14
13
|
// src/visual-system/scene-templates/mobile-message.tsx
|
|
15
14
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
EditorialSurface
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-DD4ZSYKG.js";
|
|
3
|
+
} from "./chunk-R5ZX2LJV.js";
|
|
4
|
+
import "./chunk-J7EGPURK.js";
|
|
6
5
|
import {
|
|
7
6
|
fade
|
|
8
7
|
} from "./chunk-4YM2M62S.js";
|
|
8
|
+
import "./chunk-5JBMYQP6.js";
|
|
9
9
|
import {
|
|
10
10
|
hasSceneMedia
|
|
11
11
|
} from "./chunk-224QNWRA.js";
|
|
12
|
-
import "./chunk-OOBT4X46.js";
|
|
13
12
|
|
|
14
13
|
// src/visual-system/scene-templates/quote.tsx
|
|
15
14
|
import { jsx, jsxs } from "react/jsx-runtime";
|
package/dist/react.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
TitleSceneTemplate
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-7AA2JWHZ.js";
|
|
4
4
|
import "./chunk-4YM2M62S.js";
|
|
5
5
|
import {
|
|
6
6
|
getSceneDuration,
|
|
@@ -40,9 +40,9 @@ import {
|
|
|
40
40
|
VideoFrame,
|
|
41
41
|
getDimensions,
|
|
42
42
|
sceneReadinessKey
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-KUCEOG2L.js";
|
|
44
|
+
import "./chunk-5JBMYQP6.js";
|
|
44
45
|
import "./chunk-224QNWRA.js";
|
|
45
|
-
import "./chunk-OOBT4X46.js";
|
|
46
46
|
import {
|
|
47
47
|
getVideoDuration,
|
|
48
48
|
resolveVideoTimeline
|
|
@@ -94,13 +94,13 @@ import { createElement } from "react";
|
|
|
94
94
|
|
|
95
95
|
// src/visual-system/catalog/builtin-loaders.generated.ts
|
|
96
96
|
var GENERATED_BUILTIN_TEMPLATE_LOADERS = {
|
|
97
|
-
"cinemaMedia": () => import("./cinema-media-
|
|
98
|
-
"chapterTitle": () => import("./chapter-title-
|
|
99
|
-
"editorialTimeline": () => import("./editorial-timeline-
|
|
100
|
-
"mobileMessage": () => import("./mobile-message-
|
|
101
|
-
"comparison": () => import("./comparison-
|
|
102
|
-
"quote": () => import("./quote-
|
|
103
|
-
"keyFigure": () => import("./key-figure-
|
|
97
|
+
"cinemaMedia": () => import("./cinema-media-WUS7CKPC.js").then((module) => ({ default: module.MediaSceneTemplate })),
|
|
98
|
+
"chapterTitle": () => import("./chapter-title-2JVDU62E.js").then((module) => ({ default: module.TitleSceneTemplate })),
|
|
99
|
+
"editorialTimeline": () => import("./editorial-timeline-JHQZIPNE.js").then((module) => ({ default: module.TimelineSceneTemplate })),
|
|
100
|
+
"mobileMessage": () => import("./mobile-message-CDKOERRZ.js").then((module) => ({ default: module.NotificationSceneTemplate })),
|
|
101
|
+
"comparison": () => import("./comparison-T4OYCOH3.js").then((module) => ({ default: module.ComparisonSceneTemplate })),
|
|
102
|
+
"quote": () => import("./quote-JKABOMIG.js").then((module) => ({ default: module.QuoteSceneTemplate })),
|
|
103
|
+
"keyFigure": () => import("./key-figure-YWN2OBQU.js").then((module) => ({ default: module.KeyFigureSceneTemplate }))
|
|
104
104
|
};
|
|
105
105
|
|
|
106
106
|
// src/visual-system/catalog/builtin-player.generated.ts
|
|
@@ -534,7 +534,6 @@ function usePlaybackClock({
|
|
|
534
534
|
loopRef,
|
|
535
535
|
sceneIndexRef,
|
|
536
536
|
visualReadyRef,
|
|
537
|
-
posterBridgeKeysRef,
|
|
538
537
|
callbacksRef,
|
|
539
538
|
setCurrentTime,
|
|
540
539
|
setIsPlaying
|
|
@@ -545,6 +544,10 @@ function usePlaybackClock({
|
|
|
545
544
|
let onsetWaitSeconds = 0;
|
|
546
545
|
let clockWaitSeconds = 0;
|
|
547
546
|
let lastNarrationTime;
|
|
547
|
+
let committedTime = timeRef.current;
|
|
548
|
+
let groupHandoff;
|
|
549
|
+
let requestId = stateRef.current.requestId;
|
|
550
|
+
let runId = stateRef.current.runId;
|
|
548
551
|
const failNarration = (error, state) => {
|
|
549
552
|
setIsPlaying(false);
|
|
550
553
|
try {
|
|
@@ -565,6 +568,12 @@ function usePlaybackClock({
|
|
|
565
568
|
const tick = (now) => {
|
|
566
569
|
const current = stateRef.current;
|
|
567
570
|
const config = current.config;
|
|
571
|
+
const externallySeeked = timeRef.current !== committedTime;
|
|
572
|
+
const replaced = current.requestId !== requestId || current.runId !== runId;
|
|
573
|
+
requestId = current.requestId;
|
|
574
|
+
runId = current.runId;
|
|
575
|
+
if (externallySeeked || replaced) groupHandoff = void 0;
|
|
576
|
+
let deferGroupStall = false;
|
|
568
577
|
const elapsed = Math.max(0, (now - previous) / 1e3);
|
|
569
578
|
let narrationReady = true;
|
|
570
579
|
try {
|
|
@@ -599,6 +608,7 @@ function usePlaybackClock({
|
|
|
599
608
|
return;
|
|
600
609
|
}
|
|
601
610
|
clockWaitSeconds = narrationTime !== void 0 && narrationTime === lastNarrationTime && narrationReady && !stalled ? clockWaitSeconds + elapsed : 0;
|
|
611
|
+
const audioMovedBackwards = narrationTime !== void 0 && lastNarrationTime !== void 0 && narrationTime < lastNarrationTime;
|
|
602
612
|
lastNarrationTime = narrationTime;
|
|
603
613
|
if (clockWaitSeconds >= 8) {
|
|
604
614
|
failNarration(new Error("Narration audio clock did not advance within eight seconds"), current);
|
|
@@ -613,8 +623,18 @@ function usePlaybackClock({
|
|
|
613
623
|
nextTime = Math.min(raw, duration2);
|
|
614
624
|
}
|
|
615
625
|
const target = ranges.find((range) => nextTime >= range.start && nextTime < range.end) ?? ranges.at(-1);
|
|
616
|
-
const waitingForVisual = Boolean(target && visualReadyRef && visualReadyRef.current !== sceneReadinessKey(target.scene)
|
|
617
|
-
if (waitingForVisual && target)
|
|
626
|
+
const waitingForVisual = Boolean(target && visualReadyRef && visualReadyRef.current !== sceneReadinessKey(target.scene));
|
|
627
|
+
if (waitingForVisual && target) {
|
|
628
|
+
nextTime = target.start;
|
|
629
|
+
const fromGroup = cued?.scene.narrationGroup;
|
|
630
|
+
const toGroup = target.scene.narrationGroup;
|
|
631
|
+
const continuesParagraph = !externallySeeked && !replaced && !audioMovedBackwards && narrationReady && narrationTime !== void 0 && fromGroup && toGroup && fromGroup.id === toGroup.id && fromGroup.text === toGroup.text && target === ranges[sceneIndexRef.current + 1] && narrationTime > fromGroup.offsetSeconds + 0.04;
|
|
632
|
+
if (continuesParagraph) {
|
|
633
|
+
const key = `${sceneReadinessKey(cued.scene)}\0${sceneReadinessKey(target.scene)}\0${fromGroup.id}\0${fromGroup.text}`;
|
|
634
|
+
if (groupHandoff?.key !== key) groupHandoff = { key, startedAt: now };
|
|
635
|
+
deferGroupStall = !stalled && now - groupHandoff.startedAt < 200;
|
|
636
|
+
} else groupHandoff = void 0;
|
|
637
|
+
} else groupHandoff = void 0;
|
|
618
638
|
if (nextTime !== timeRef.current) {
|
|
619
639
|
timeRef.current = nextTime;
|
|
620
640
|
setCurrentTime(nextTime);
|
|
@@ -645,7 +665,8 @@ function usePlaybackClock({
|
|
|
645
665
|
}
|
|
646
666
|
const duration = current.config ? getVideoDuration(current.config) : 0;
|
|
647
667
|
const active = current.config ? resolveVideoTimeline(current.config).find((range) => timeRef.current >= range.start && timeRef.current < range.end) : void 0;
|
|
648
|
-
reportStall(Boolean(active && visualReadyRef && visualReadyRef.current !== sceneReadinessKey(active.scene) && !
|
|
668
|
+
reportStall(Boolean(active && visualReadyRef && visualReadyRef.current !== sceneReadinessKey(active.scene) && !deferGroupStall) || !settled && Boolean(current.config?.scenes.length) && duration > 0 && timeRef.current >= duration);
|
|
669
|
+
committedTime = timeRef.current;
|
|
649
670
|
if (!settled || looping || timeRef.current < duration) frame = requestAnimationFrame(tick);
|
|
650
671
|
else setIsPlaying(false);
|
|
651
672
|
};
|
|
@@ -732,13 +753,8 @@ function VideoPlayerRuntime({
|
|
|
732
753
|
const loopRef = useRef(loop);
|
|
733
754
|
const sceneIndexRef = useRef(-1);
|
|
734
755
|
const mediaFrameReportedRef = useRef(false);
|
|
735
|
-
const posterBridgeKeysRef = useRef(/* @__PURE__ */ new Set());
|
|
736
756
|
const visualReadyRef = useRef(void 0);
|
|
737
|
-
const reportVisualReady = useMemo(() => (key, error, actualVideoFrame = false
|
|
738
|
-
if (posterBridge) {
|
|
739
|
-
posterBridgeKeysRef.current.add(key);
|
|
740
|
-
return;
|
|
741
|
-
}
|
|
757
|
+
const reportVisualReady = useMemo(() => (key, error, actualVideoFrame = false) => {
|
|
742
758
|
if (error) {
|
|
743
759
|
setIsPlaying(false);
|
|
744
760
|
callbacksRef.current.onError?.(error, stateRef.current);
|
|
@@ -798,7 +814,6 @@ function VideoPlayerRuntime({
|
|
|
798
814
|
setActiveStream(stream);
|
|
799
815
|
setActiveSavedVideo(video);
|
|
800
816
|
mediaFrameReportedRef.current = false;
|
|
801
|
-
posterBridgeKeysRef.current.clear();
|
|
802
817
|
sceneIndexRef.current = -1;
|
|
803
818
|
setReplacementPending(stream != null);
|
|
804
819
|
setState(video ? savedVideoState(video) : createVideoState());
|
|
@@ -917,7 +932,6 @@ function VideoPlayerRuntime({
|
|
|
917
932
|
loopRef,
|
|
918
933
|
sceneIndexRef,
|
|
919
934
|
visualReadyRef,
|
|
920
|
-
posterBridgeKeysRef,
|
|
921
935
|
callbacksRef,
|
|
922
936
|
setCurrentTime,
|
|
923
937
|
setIsPlaying
|