@vanillaskyai/video 0.10.2 → 0.10.3
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 +8 -0
- package/README.md +12 -7
- package/dist/check-runtime.js +2 -2
- package/dist/{chunk-6KZGF63O.js → chunk-3U2F7C7C.js} +53 -34
- package/dist/{chunk-5C6HZNHY.js → chunk-LJR5VLEI.js} +3 -2
- package/dist/{chunk-77VY4O7A.js → chunk-SI6CFFAA.js} +57 -10
- package/dist/{chunk-KHLO5OHT.js → chunk-UCXQORDZ.js} +1 -1
- package/dist/{chunk-VQH3JTQC.js → chunk-VVNZCY2U.js} +1 -1
- package/dist/{chunk-TVIU23OM.js → chunk-YZZSWGC3.js} +8 -3
- package/dist/{cinema-media-APDJS7SC.js → cinema-media-4JUYKPQI.js} +4 -4
- package/dist/{comparison-ZVE2DE7U.js → comparison-3QLMUC5V.js} +4 -4
- package/dist/{editorial-timeline-YIXXVJUV.js → editorial-timeline-IVE2P25N.js} +4 -4
- package/dist/{key-figure-I2C37FWV.js → key-figure-APD56LCO.js} +4 -4
- package/dist/{mobile-message-JSGBU6EX.js → mobile-message-WLK3WY5B.js} +4 -4
- package/dist/{quote-XH54G3FS.js → quote-Z6YET5BO.js} +4 -4
- package/dist/react.js +25 -13
- package/dist/{scene-video-backdrop-PCTARAAJ.js → scene-video-backdrop-OWUXPXHZ.js} +2 -2
- package/dist/server.js +302 -257
- package/docs/agent-integration.md +5 -4
- package/docs/getting-started.md +7 -5
- package/docs/media-and-audio.md +23 -17
- package/docs/production.md +7 -4
- package/docs/prompt-and-input.md +24 -15
- package/docs/provider-integration.md +2 -2
- package/docs/reference/protocol.md +7 -1
- package/docs/reference/provider-adapters.md +5 -3
- package/docs/testing.md +7 -2
- package/package.json +1 -1
- package/registry/items/backgrounds.json +2 -2
- package/registry/items/cinemaMedia.json +1 -1
- package/registry/items/comparison.json +1 -1
- package/registry/items/editorialTimeline.json +1 -1
- package/registry/items/keyFigure.json +1 -1
- package/registry/items/mobileMessage.json +1 -1
- package/registry/items/quote.json +1 -1
- package/starters/video-chat/README.md +18 -17
- package/starters/video-chat/package.json +1 -1
- package/starters/video-chat/providers/video.ts +5 -4
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,14 @@ VanillaSky follows semantic versioning. This changelog begins with the 0.1 beta.
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## 0.10.3
|
|
8
|
+
|
|
9
|
+
- Remove the implicit documentary visual style from the chat interface; preserve explicitly supplied application styles and let the answer direct its own look.
|
|
10
|
+
- Default chat now plans an answer brief and narrated shots, with an immediate introduction followed by AI-first footage and relevant stock fallback. Creative direction adapts to the request; the model no longer chooses body templates, media sources, scene IDs, or completion commands. Explicit custom template registries retain their existing composition contract.
|
|
11
|
+
- Reserve the answer's ending before streaming body shots, retain valid narration when visuals are unavailable, and skip exact repeated opening or ending lines before requesting media.
|
|
12
|
+
- Fit short clips to measured narration within a bounded playback rate. If moving coverage runs out, use bounded recovery and an explicit waiting state instead of holding a finished frame while speech continues. Preserve deliberate pauses and audio activation across scenes.
|
|
13
|
+
- The optional starter video adapter uses Fal Turbo with five-second clips and intent-specific shot direction; providers, credentials, admission and spending limits remain application-owned.
|
|
14
|
+
|
|
7
15
|
## 0.10.2
|
|
8
16
|
|
|
9
17
|
- Keep generated narration playing in Safari after a delayed opening-to-body handoff by reusing the permitted audio element; isolate late playback failures from subsequent lines.
|
package/README.md
CHANGED
|
@@ -25,9 +25,10 @@ npx vanillasky doctor
|
|
|
25
25
|
npm run dev
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
Open the reported localhost URL. One text key gives you the
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
Open the reported localhost URL. One text key gives you the chat, an immediate introduction, and browser voice.
|
|
29
|
+
Add the video adapter for generated footage and optional stock for fallback.
|
|
30
|
+
Without a media provider, answers retain narration and subtitles with an
|
|
31
|
+
unavailable-visual state. If installation is interrupted, rerun the init command.
|
|
31
32
|
|
|
32
33
|
Optional upgrades keep the same client:
|
|
33
34
|
|
|
@@ -80,11 +81,15 @@ conversation and playback lifecycle. Edit the generated server when you want a
|
|
|
80
81
|
different provider. The [provider guide](docs/provider-integration.md) explains
|
|
81
82
|
both boundaries.
|
|
82
83
|
|
|
83
|
-
##
|
|
84
|
+
## An immediate intro, then moving footage
|
|
84
85
|
|
|
85
|
-
The
|
|
86
|
-
|
|
87
|
-
|
|
86
|
+
The default chat uses a template introduction while its first shot prepares,
|
|
87
|
+
then generated footage with narration and subtitles. Relevant stock is the
|
|
88
|
+
fallback when generation is unavailable or fails. The planner adapts its
|
|
89
|
+
visible actions and spoken beats to explanations, stories, comedy, imagination,
|
|
90
|
+
and practical requests. It does not choose body templates.
|
|
91
|
+
|
|
92
|
+
Packaged templates remain available for custom compositions and source ownership.
|
|
88
93
|
|
|
89
94
|
Copy template source only when you want to own and edit it:
|
|
90
95
|
|
package/dist/check-runtime.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
VideoFrame
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-3U2F7C7C.js";
|
|
4
4
|
import "./chunk-224QNWRA.js";
|
|
5
|
-
import "./chunk-
|
|
5
|
+
import "./chunk-YZZSWGC3.js";
|
|
6
6
|
import "./chunk-SPVTJH3F.js";
|
|
7
7
|
import "./chunk-R3XAOMKP.js";
|
|
8
8
|
import "./chunk-73NTSFFI.js";
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
ExternalVideoBackdropProvider,
|
|
7
7
|
resolveDensity
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-YZZSWGC3.js";
|
|
9
9
|
import {
|
|
10
10
|
resolveVideoTimeline
|
|
11
11
|
} from "./chunk-SPVTJH3F.js";
|
|
@@ -209,7 +209,7 @@ var SceneBoundary = class extends Component {
|
|
|
209
209
|
}
|
|
210
210
|
};
|
|
211
211
|
var SCENE_TRANSITION_SECONDS = 0.3;
|
|
212
|
-
var SceneVideoBackdrop = lazy(() => import("./scene-video-backdrop-
|
|
212
|
+
var SceneVideoBackdrop = lazy(() => import("./scene-video-backdrop-OWUXPXHZ.js").then((module) => ({ default: module.SceneVideoBackdrop })));
|
|
213
213
|
var MEDIA_PREROLL_SECONDS = 1.2;
|
|
214
214
|
var CONTIGUITY_ULP_FACTOR = 4;
|
|
215
215
|
var subscribeToDecoderPolicy = () => () => {
|
|
@@ -265,6 +265,7 @@ function SceneLayer({
|
|
|
265
265
|
width,
|
|
266
266
|
height,
|
|
267
267
|
playing,
|
|
268
|
+
preparingNarration,
|
|
268
269
|
mediaAudioMuted,
|
|
269
270
|
mediaAudioVolume,
|
|
270
271
|
layer,
|
|
@@ -283,7 +284,8 @@ function SceneLayer({
|
|
|
283
284
|
mode: externalVideoBackdrop,
|
|
284
285
|
audioMuted: mediaAudioMuted || !playing,
|
|
285
286
|
audioVolume: mediaAudioVolume,
|
|
286
|
-
|
|
287
|
+
preparingNarration,
|
|
288
|
+
children: /* @__PURE__ */ jsxs(
|
|
287
289
|
"div",
|
|
288
290
|
{
|
|
289
291
|
"data-scene-layer": layer,
|
|
@@ -304,37 +306,48 @@ function SceneLayer({
|
|
|
304
306
|
"--vanillasky-transition-semantic-visibility": layer === "incoming" ? "hidden" : "visible",
|
|
305
307
|
"--vanillasky-template-surface": externalVideoBackdrop !== false ? "transparent" : void 0
|
|
306
308
|
},
|
|
307
|
-
children:
|
|
308
|
-
"
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
309
|
+
children: [
|
|
310
|
+
range.scene.templateId === "cinemaMedia" && !recoveryTitle && (mediaFailed || !String(range.scene.variables.mediaUrl || "").trim()) && /* @__PURE__ */ jsx2(
|
|
311
|
+
"div",
|
|
312
|
+
{
|
|
313
|
+
role: "status",
|
|
314
|
+
"data-media-unavailable": "true",
|
|
315
|
+
style: { position: "absolute", inset: 0, zIndex: 2, display: "grid", placeContent: "center", color: "#bbb", font: "14px system-ui", background: "#000" },
|
|
316
|
+
children: "Visual unavailable"
|
|
317
|
+
}
|
|
318
|
+
),
|
|
319
|
+
template ? /* @__PURE__ */ jsx2(SceneBoundary, { scene: range.scene, onFramePresented, children: /* @__PURE__ */ jsxs(Suspense, { fallback: /* @__PURE__ */ jsx2(
|
|
320
|
+
"div",
|
|
321
|
+
{
|
|
322
|
+
"data-template-loading": range.scene.templateId,
|
|
323
|
+
style: { position: "absolute", inset: 0 }
|
|
324
|
+
}
|
|
325
|
+
), children: [
|
|
326
|
+
/* @__PURE__ */ jsx2(PresentedScene, { notify: onFramePresented }),
|
|
327
|
+
createElement(template.component, {
|
|
328
|
+
variables: {
|
|
329
|
+
...template.defaults ?? getTemplateDefaults(template.schema),
|
|
330
|
+
...range.scene.variables,
|
|
331
|
+
...mediaFailed ? { mediaUrl: "", mediaPoster: "", mediaType: "gradient" } : {},
|
|
332
|
+
...recoveryTitle ? { title: recoveryTitle } : {}
|
|
333
|
+
},
|
|
334
|
+
style: config.style,
|
|
335
|
+
progress,
|
|
336
|
+
motionProgress,
|
|
337
|
+
beatIntensity: 0,
|
|
338
|
+
width,
|
|
339
|
+
height,
|
|
340
|
+
textArchetype: range.scene.textArchetype ?? config.style.defaultTextArchetype,
|
|
341
|
+
backgroundEffect: range.scene.backgroundEffect ?? config.style.defaultBackgroundEffect,
|
|
342
|
+
safeZone: scaleSafeZone(
|
|
343
|
+
getSafeZone(config.orientation),
|
|
344
|
+
resolveDensity(config.style.density).safeZoneScale
|
|
345
|
+
),
|
|
346
|
+
sceneDuration: duration,
|
|
347
|
+
isPlaying: playing
|
|
348
|
+
})
|
|
349
|
+
] }) }, range.scene.id) : /* @__PURE__ */ jsx2(SafeScene, { scene: range.scene, onFramePresented })
|
|
350
|
+
]
|
|
338
351
|
}
|
|
339
352
|
)
|
|
340
353
|
}
|
|
@@ -348,6 +361,7 @@ function VideoFrame({
|
|
|
348
361
|
width,
|
|
349
362
|
height,
|
|
350
363
|
playing = false,
|
|
364
|
+
preparingNarration = false,
|
|
351
365
|
mediaAudioMuted = true,
|
|
352
366
|
mediaAudioVolume = 1,
|
|
353
367
|
className,
|
|
@@ -550,7 +564,9 @@ function VideoFrame({
|
|
|
550
564
|
mediaPosition: String(persistentVideoRange.scene.variables.mediaPosition || "center"),
|
|
551
565
|
backgroundEffect: persistentVideoRange.scene.backgroundEffect ?? config.style.defaultBackgroundEffect,
|
|
552
566
|
progress: persistentVideoRange.scene.id === active.scene.id ? rawProgress : 0,
|
|
567
|
+
sceneDuration: persistentVideoRange.end - persistentVideoRange.start,
|
|
553
568
|
isPlaying: persistentVideoRange.scene.id === active.scene.id && playing,
|
|
569
|
+
preparingNarration,
|
|
554
570
|
muted: mediaAudioMuted || persistentVideoRange.scene.id !== active.scene.id || !playing,
|
|
555
571
|
volume: mediaAudioVolume,
|
|
556
572
|
playbackId: persistentVideoRange.scene.id,
|
|
@@ -583,6 +599,7 @@ function VideoFrame({
|
|
|
583
599
|
width: canvas.width,
|
|
584
600
|
height: canvas.height,
|
|
585
601
|
playing,
|
|
602
|
+
preparingNarration,
|
|
586
603
|
mediaAudioMuted,
|
|
587
604
|
mediaAudioVolume,
|
|
588
605
|
layer: previewingNext ? "outgoing" : "active",
|
|
@@ -604,6 +621,7 @@ function VideoFrame({
|
|
|
604
621
|
width: canvas.width,
|
|
605
622
|
height: canvas.height,
|
|
606
623
|
playing: false,
|
|
624
|
+
preparingNarration: false,
|
|
607
625
|
mediaAudioMuted,
|
|
608
626
|
mediaAudioVolume,
|
|
609
627
|
layer: "incoming",
|
|
@@ -627,6 +645,7 @@ function VideoFrame({
|
|
|
627
645
|
width: canvas.width,
|
|
628
646
|
height: canvas.height,
|
|
629
647
|
playing,
|
|
648
|
+
preparingNarration,
|
|
630
649
|
mediaAudioMuted,
|
|
631
650
|
mediaAudioVolume,
|
|
632
651
|
layer: "active",
|
|
@@ -3,13 +3,13 @@ import {
|
|
|
3
3
|
SceneVideoBackdrop,
|
|
4
4
|
getBackgroundTransform,
|
|
5
5
|
resolveMediaPosition
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-SI6CFFAA.js";
|
|
7
7
|
import {
|
|
8
8
|
resolveMediaType
|
|
9
9
|
} from "./chunk-224QNWRA.js";
|
|
10
10
|
import {
|
|
11
11
|
useExternalVideoBackdrop
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-YZZSWGC3.js";
|
|
13
13
|
|
|
14
14
|
// src/visual-system/scene-templates/scene-background.tsx
|
|
15
15
|
import { useEffect, useState } from "react";
|
|
@@ -157,6 +157,7 @@ var SceneBackground = ({
|
|
|
157
157
|
mediaPosition,
|
|
158
158
|
backgroundEffect,
|
|
159
159
|
progress,
|
|
160
|
+
sceneDuration,
|
|
160
161
|
beatIntensity,
|
|
161
162
|
isPlaying,
|
|
162
163
|
onReady: () => setMediaPaint("ready"),
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
darken,
|
|
3
3
|
resolveTokens,
|
|
4
|
-
useMediaAudio
|
|
5
|
-
|
|
4
|
+
useMediaAudio,
|
|
5
|
+
useNarrationPreroll
|
|
6
|
+
} from "./chunk-YZZSWGC3.js";
|
|
6
7
|
|
|
7
8
|
// src/visual-system/scene-templates/scene-video-backdrop.tsx
|
|
8
|
-
import { useEffect, useRef, useState } from "react";
|
|
9
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
9
10
|
|
|
10
11
|
// src/visual-system/scene-templates/color-utils.ts
|
|
11
12
|
import React from "react";
|
|
@@ -228,6 +229,8 @@ var SceneVideoBackdrop = ({
|
|
|
228
229
|
mediaPosition = "center",
|
|
229
230
|
backgroundEffect,
|
|
230
231
|
progress,
|
|
232
|
+
sceneDuration,
|
|
233
|
+
preparingNarration = false,
|
|
231
234
|
beatIntensity = 0,
|
|
232
235
|
isPlaying,
|
|
233
236
|
muted,
|
|
@@ -240,15 +243,44 @@ var SceneVideoBackdrop = ({
|
|
|
240
243
|
onError
|
|
241
244
|
}) => {
|
|
242
245
|
const inheritedAudio = useMediaAudio();
|
|
246
|
+
const inheritedPreroll = useNarrationPreroll();
|
|
247
|
+
const rewindPreroll = preparingNarration || inheritedPreroll;
|
|
243
248
|
const resolvedMuted = muted ?? inheritedAudio.muted;
|
|
244
249
|
const resolvedVolume = volume ?? inheritedAudio.volume;
|
|
245
250
|
const resolvedPosition = resolveMediaPosition(mediaPosition);
|
|
246
251
|
const bgTransform = getBackgroundTransform(backgroundEffect, progress, beatIntensity);
|
|
247
252
|
const [decodedVideoUrl, setDecodedVideoUrl] = useState();
|
|
253
|
+
const [waitingKey, setWaitingKey] = useState();
|
|
254
|
+
const [exhaustedKey, setExhaustedKey] = useState();
|
|
255
|
+
const continuityReplay = useRef(void 0);
|
|
248
256
|
const videoRef = useRef(null);
|
|
249
257
|
const startedVideoUrl = useRef(void 0);
|
|
250
258
|
const startedPlaybackId = useRef(void 0);
|
|
251
259
|
const videoPresentationKey = `${playbackId}\0${mediaUrl}`;
|
|
260
|
+
const presentationRef = useRef({ key: videoPresentationKey, playing: isPlaying });
|
|
261
|
+
presentationRef.current = { key: videoPresentationKey, playing: isPlaying };
|
|
262
|
+
const unavailable = () => {
|
|
263
|
+
if (presentationRef.current.key === videoPresentationKey && presentationRef.current.playing) {
|
|
264
|
+
setExhaustedKey(videoPresentationKey);
|
|
265
|
+
onError?.();
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
const fitDuration = useCallback((video) => {
|
|
269
|
+
video.playbackRate = (resolvedMuted || video.preservesPitch === true) && sceneDuration && Number.isFinite(video.duration) && video.duration > 0 ? Math.max(0.75, Math.min(1, video.duration / (sceneDuration + 0.2))) : 1;
|
|
270
|
+
}, [resolvedMuted, sceneDuration]);
|
|
271
|
+
useEffect(() => {
|
|
272
|
+
if (videoRef.current) fitDuration(videoRef.current);
|
|
273
|
+
}, [fitDuration]);
|
|
274
|
+
const continueMotion = (video) => {
|
|
275
|
+
if (!isPlaying) return;
|
|
276
|
+
if (!resolvedMuted || continuityReplay.current === videoPresentationKey) {
|
|
277
|
+
setExhaustedKey(videoPresentationKey);
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
continuityReplay.current = videoPresentationKey;
|
|
281
|
+
video.currentTime = 0;
|
|
282
|
+
void video.play().catch(unavailable);
|
|
283
|
+
};
|
|
252
284
|
useEffect(() => {
|
|
253
285
|
const video = videoRef.current;
|
|
254
286
|
if (!video) return;
|
|
@@ -273,21 +305,21 @@ var SceneVideoBackdrop = ({
|
|
|
273
305
|
if (!video) return;
|
|
274
306
|
if (!isPlaying) {
|
|
275
307
|
video.pause();
|
|
308
|
+
if (rewindPreroll && video.currentTime > 0) video.currentTime = 0;
|
|
276
309
|
return;
|
|
277
310
|
}
|
|
278
311
|
if (startedPlaybackId.current === playbackId) {
|
|
279
|
-
if (
|
|
280
|
-
|
|
312
|
+
if (video.ended) continueMotion(video);
|
|
313
|
+
else void video.play().catch(unavailable);
|
|
281
314
|
return;
|
|
282
315
|
}
|
|
283
316
|
const changingSource = startedVideoUrl.current !== void 0 && startedVideoUrl.current !== mediaUrl;
|
|
284
|
-
video
|
|
317
|
+
fitDuration(video);
|
|
285
318
|
if (!changingSource && video.currentTime > 0) video.currentTime = 0;
|
|
286
|
-
video.play().catch(
|
|
287
|
-
});
|
|
319
|
+
video.play().catch(unavailable);
|
|
288
320
|
startedVideoUrl.current = mediaUrl;
|
|
289
321
|
startedPlaybackId.current = playbackId;
|
|
290
|
-
}, [isPlaying, mediaUrl, playbackId]);
|
|
322
|
+
}, [isPlaying, mediaUrl, playbackId, rewindPreroll]);
|
|
291
323
|
const mediaStyle = {
|
|
292
324
|
position: "absolute",
|
|
293
325
|
inset: 0,
|
|
@@ -349,6 +381,15 @@ var SceneVideoBackdrop = ({
|
|
|
349
381
|
},
|
|
350
382
|
posterPlane.presentationKey
|
|
351
383
|
)),
|
|
384
|
+
(exhaustedKey === videoPresentationKey || waitingKey === videoPresentationKey) && /* @__PURE__ */ jsx(
|
|
385
|
+
"div",
|
|
386
|
+
{
|
|
387
|
+
role: "status",
|
|
388
|
+
"data-media-continuity": exhaustedKey === videoPresentationKey ? "exhausted" : "waiting",
|
|
389
|
+
style: { position: "absolute", inset: 0, zIndex: 3, background: "#000", color: "#bbb", display: "grid", placeContent: "center", font: "14px system-ui" },
|
|
390
|
+
children: exhaustedKey === videoPresentationKey ? "Visual unavailable" : "Loading visual"
|
|
391
|
+
}
|
|
392
|
+
),
|
|
352
393
|
/* @__PURE__ */ jsx(
|
|
353
394
|
"video",
|
|
354
395
|
{
|
|
@@ -359,6 +400,12 @@ var SceneVideoBackdrop = ({
|
|
|
359
400
|
loop: false,
|
|
360
401
|
playsInline: true,
|
|
361
402
|
preload: "auto",
|
|
403
|
+
onLoadedMetadata: (event) => fitDuration(event.currentTarget),
|
|
404
|
+
onEnded: (event) => continueMotion(event.currentTarget),
|
|
405
|
+
onWaiting: () => {
|
|
406
|
+
if (isPlaying) setWaitingKey(videoPresentationKey);
|
|
407
|
+
},
|
|
408
|
+
onPlaying: () => setWaitingKey(void 0),
|
|
362
409
|
onLoadedData: (event) => {
|
|
363
410
|
const video = event.currentTarget;
|
|
364
411
|
const markPresented = () => {
|
|
@@ -375,7 +422,7 @@ var SceneVideoBackdrop = ({
|
|
|
375
422
|
onError,
|
|
376
423
|
"data-media-position": mediaPosition,
|
|
377
424
|
"data-video-backdrop": persistent ? "persistent" : "scene",
|
|
378
|
-
style: mediaStyle
|
|
425
|
+
style: { ...mediaStyle, visibility: exhaustedKey === videoPresentationKey || waitingKey === videoPresentationKey ? "hidden" : void 0 }
|
|
379
426
|
}
|
|
380
427
|
)
|
|
381
428
|
] });
|
|
@@ -8,11 +8,12 @@ function ExternalVideoBackdropProvider({
|
|
|
8
8
|
mode,
|
|
9
9
|
audioMuted = true,
|
|
10
10
|
audioVolume = 1,
|
|
11
|
+
preparingNarration = false,
|
|
11
12
|
children
|
|
12
13
|
}) {
|
|
13
14
|
const value = React.useMemo(
|
|
14
|
-
() => ({ mode, audioMuted, audioVolume }),
|
|
15
|
-
[mode, audioMuted, audioVolume]
|
|
15
|
+
() => ({ mode, audioMuted, audioVolume, preparingNarration }),
|
|
16
|
+
[mode, audioMuted, audioVolume, preparingNarration]
|
|
16
17
|
);
|
|
17
18
|
return /* @__PURE__ */ jsx(BackdropContext.Provider, { value, children });
|
|
18
19
|
}
|
|
@@ -23,6 +24,9 @@ function useMediaAudio() {
|
|
|
23
24
|
const { audioMuted, audioVolume } = React.useContext(BackdropContext);
|
|
24
25
|
return { muted: audioMuted, volume: audioVolume };
|
|
25
26
|
}
|
|
27
|
+
function useNarrationPreroll() {
|
|
28
|
+
return React.useContext(BackdropContext).preparingNarration === true;
|
|
29
|
+
}
|
|
26
30
|
|
|
27
31
|
// src/visual-system/scene-templates/tokens.ts
|
|
28
32
|
var STYLE_PRESETS = {
|
|
@@ -142,5 +146,6 @@ export {
|
|
|
142
146
|
darken,
|
|
143
147
|
ExternalVideoBackdropProvider,
|
|
144
148
|
useExternalVideoBackdrop,
|
|
145
|
-
useMediaAudio
|
|
149
|
+
useMediaAudio,
|
|
150
|
+
useNarrationPreroll
|
|
146
151
|
};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MediaScene,
|
|
3
3
|
MediaSceneTemplate
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-VVNZCY2U.js";
|
|
5
|
+
import "./chunk-LJR5VLEI.js";
|
|
6
|
+
import "./chunk-SI6CFFAA.js";
|
|
7
7
|
import "./chunk-224QNWRA.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-YZZSWGC3.js";
|
|
9
9
|
export {
|
|
10
10
|
MediaScene,
|
|
11
11
|
MediaSceneTemplate
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
EditorialSurface
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-UCXQORDZ.js";
|
|
4
|
+
import "./chunk-LJR5VLEI.js";
|
|
5
|
+
import "./chunk-SI6CFFAA.js";
|
|
6
6
|
import {
|
|
7
7
|
editorialLabel,
|
|
8
8
|
fade
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
import {
|
|
11
11
|
hasSceneMedia
|
|
12
12
|
} from "./chunk-224QNWRA.js";
|
|
13
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-YZZSWGC3.js";
|
|
14
14
|
|
|
15
15
|
// src/visual-system/scene-templates/comparison.tsx
|
|
16
16
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
EditorialSurface
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-UCXQORDZ.js";
|
|
4
|
+
import "./chunk-LJR5VLEI.js";
|
|
5
|
+
import "./chunk-SI6CFFAA.js";
|
|
6
6
|
import {
|
|
7
7
|
fade
|
|
8
8
|
} from "./chunk-4YM2M62S.js";
|
|
9
9
|
import "./chunk-224QNWRA.js";
|
|
10
|
-
import "./chunk-
|
|
10
|
+
import "./chunk-YZZSWGC3.js";
|
|
11
11
|
|
|
12
12
|
// src/visual-system/scene-templates/editorial-timeline.tsx
|
|
13
13
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
EditorialSurface
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-UCXQORDZ.js";
|
|
4
|
+
import "./chunk-LJR5VLEI.js";
|
|
5
|
+
import "./chunk-SI6CFFAA.js";
|
|
6
6
|
import {
|
|
7
7
|
editorialLabel,
|
|
8
8
|
fade
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
import {
|
|
11
11
|
hasSceneMedia
|
|
12
12
|
} from "./chunk-224QNWRA.js";
|
|
13
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-YZZSWGC3.js";
|
|
14
14
|
|
|
15
15
|
// src/visual-system/scene-templates/key-figure.tsx
|
|
16
16
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MediaScene
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-VVNZCY2U.js";
|
|
4
|
+
import "./chunk-LJR5VLEI.js";
|
|
5
5
|
import {
|
|
6
6
|
spring
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-SI6CFFAA.js";
|
|
8
8
|
import {
|
|
9
9
|
editorialFont
|
|
10
10
|
} from "./chunk-4YM2M62S.js";
|
|
11
11
|
import "./chunk-224QNWRA.js";
|
|
12
|
-
import "./chunk-
|
|
12
|
+
import "./chunk-YZZSWGC3.js";
|
|
13
13
|
|
|
14
14
|
// src/visual-system/scene-templates/mobile-message.tsx
|
|
15
15
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
EditorialSurface
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-UCXQORDZ.js";
|
|
4
|
+
import "./chunk-LJR5VLEI.js";
|
|
5
|
+
import "./chunk-SI6CFFAA.js";
|
|
6
6
|
import {
|
|
7
7
|
fade
|
|
8
8
|
} from "./chunk-4YM2M62S.js";
|
|
9
9
|
import {
|
|
10
10
|
hasSceneMedia
|
|
11
11
|
} from "./chunk-224QNWRA.js";
|
|
12
|
-
import "./chunk-
|
|
12
|
+
import "./chunk-YZZSWGC3.js";
|
|
13
13
|
|
|
14
14
|
// src/visual-system/scene-templates/quote.tsx
|
|
15
15
|
import { jsx, jsxs } from "react/jsx-runtime";
|
package/dist/react.js
CHANGED
|
@@ -40,9 +40,9 @@ import {
|
|
|
40
40
|
VideoFrame,
|
|
41
41
|
getDimensions,
|
|
42
42
|
sceneReadinessKey
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-3U2F7C7C.js";
|
|
44
44
|
import "./chunk-224QNWRA.js";
|
|
45
|
-
import "./chunk-
|
|
45
|
+
import "./chunk-YZZSWGC3.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-
|
|
97
|
+
"cinemaMedia": () => import("./cinema-media-4JUYKPQI.js").then((module) => ({ default: module.MediaSceneTemplate })),
|
|
98
98
|
"chapterTitle": () => import("./chapter-title-YRLIQY3V.js").then((module) => ({ default: module.TitleSceneTemplate })),
|
|
99
|
-
"editorialTimeline": () => import("./editorial-timeline-
|
|
100
|
-
"mobileMessage": () => import("./mobile-message-
|
|
101
|
-
"comparison": () => import("./comparison-
|
|
102
|
-
"quote": () => import("./quote-
|
|
103
|
-
"keyFigure": () => import("./key-figure-
|
|
99
|
+
"editorialTimeline": () => import("./editorial-timeline-IVE2P25N.js").then((module) => ({ default: module.TimelineSceneTemplate })),
|
|
100
|
+
"mobileMessage": () => import("./mobile-message-WLK3WY5B.js").then((module) => ({ default: module.NotificationSceneTemplate })),
|
|
101
|
+
"comparison": () => import("./comparison-3QLMUC5V.js").then((module) => ({ default: module.ComparisonSceneTemplate })),
|
|
102
|
+
"quote": () => import("./quote-Z6YET5BO.js").then((module) => ({ default: module.QuoteSceneTemplate })),
|
|
103
|
+
"keyFigure": () => import("./key-figure-APD56LCO.js").then((module) => ({ default: module.KeyFigureSceneTemplate }))
|
|
104
104
|
};
|
|
105
105
|
|
|
106
106
|
// src/visual-system/catalog/builtin-player.generated.ts
|
|
@@ -754,6 +754,14 @@ function VideoPlayerRuntime({
|
|
|
754
754
|
}
|
|
755
755
|
}, []);
|
|
756
756
|
const playbackEndedRef = useRef(false);
|
|
757
|
+
let mediaPlaying = isPlaying;
|
|
758
|
+
if (sceneIndexRef.current >= 0) {
|
|
759
|
+
try {
|
|
760
|
+
mediaPlaying = isPlaying && narrationReady?.() !== false;
|
|
761
|
+
} catch {
|
|
762
|
+
mediaPlaying = false;
|
|
763
|
+
}
|
|
764
|
+
}
|
|
757
765
|
stateRef.current = state;
|
|
758
766
|
timeRef.current = currentTime;
|
|
759
767
|
callbacksRef.current = { onComplete, onPlaybackEnd, onError, onSceneChange, narrationReady, narrationTime, onFramePresented, onMediaFramePresented, onStallChange, onStateChange };
|
|
@@ -1131,7 +1139,8 @@ function VideoPlayerRuntime({
|
|
|
1131
1139
|
time: showStartPoster ? posterTime : currentTime,
|
|
1132
1140
|
width: dimensions.width,
|
|
1133
1141
|
height: dimensions.height,
|
|
1134
|
-
playing:
|
|
1142
|
+
playing: mediaPlaying,
|
|
1143
|
+
preparingNarration: isPlaying && !mediaPlaying,
|
|
1135
1144
|
mediaAudioMuted: !nativeMediaAudio || isMuted,
|
|
1136
1145
|
mediaAudioVolume: nativeMediaVolume,
|
|
1137
1146
|
style: {
|
|
@@ -1243,7 +1252,7 @@ var VideoError = class extends Error {
|
|
|
1243
1252
|
function recoverSceneMedia(scene) {
|
|
1244
1253
|
if (scene.templateId === "cinemaMedia") {
|
|
1245
1254
|
const title = scene.variables.fallbackText;
|
|
1246
|
-
if (typeof title !== "string" || !title.trim() || [...title].length > 65) return
|
|
1255
|
+
if (typeof title !== "string" || !title.trim() || [...title].length > 65) return { ...scene, variables: { mediaType: "video", mediaUrl: "" } };
|
|
1247
1256
|
return { ...scene, templateId: "chapterTitle", variables: { title: title.trim() } };
|
|
1248
1257
|
}
|
|
1249
1258
|
if (!["comparison", "editorialTimeline", "quote", "keyFigure"].includes(scene.templateId)) return void 0;
|
|
@@ -1397,7 +1406,11 @@ function useNarration(options) {
|
|
|
1397
1406
|
if (!optionsRef.current.voice.getCurrentTime) return void 0;
|
|
1398
1407
|
const time = currentRef.current ? optionsRef.current.voice.getCurrentTime() : void 0;
|
|
1399
1408
|
if (currentRef.current && readyRef.current && time === void 0) return void 0;
|
|
1400
|
-
if (time !== void 0 && Number.isFinite(time))
|
|
1409
|
+
if (time !== void 0 && Number.isFinite(time)) {
|
|
1410
|
+
const end = group?.totalSeconds ?? scene.timing.fixedDuration ?? Infinity;
|
|
1411
|
+
const limit = currentRef.current ? Math.max(0, end - 0.01) : end;
|
|
1412
|
+
clockRef.current = Math.min(limit, Math.max(group?.offsetSeconds ?? 0, time));
|
|
1413
|
+
}
|
|
1401
1414
|
return clockRef.current;
|
|
1402
1415
|
}, []);
|
|
1403
1416
|
const isReady = useCallback(() => optionsRef.current.enabled === false || readyRef.current || clockRef.current !== void 0 && clockRef.current >= (groupRef.current?.offsetSeconds ?? 0) + 0.04, []);
|
|
@@ -3367,8 +3380,7 @@ function VideoChat({ options = {}, className, welcomeTitle, showRecoveryNotice =
|
|
|
3367
3380
|
const sessionOrientation = options.orientation ?? viewportOrientation;
|
|
3368
3381
|
const { chat, restoreSession } = useVideoChatSession({
|
|
3369
3382
|
...options,
|
|
3370
|
-
orientation: sessionOrientation
|
|
3371
|
-
style: { generatedLook: "Natural light, restrained camera movement, documentary realism, consistent natural color. No embedded text.", ...options.style }
|
|
3383
|
+
orientation: sessionOrientation
|
|
3372
3384
|
});
|
|
3373
3385
|
const instanceId = useId();
|
|
3374
3386
|
const historyId = `${instanceId}-history`;
|