@vanillaskyai/video 0.1.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -1
- package/PUBLIC-API.md +20 -2
- package/README.md +14 -6
- package/dist/{builtin-server-F7YXRVCH.js → builtin-server-BRTZN4Q7.js} +2 -2
- package/dist/check-runtime.js +1 -1
- package/dist/{chunk-EVG2ZYIY.js → chunk-3O7OMMMF.js} +7 -4
- package/dist/{chunk-GRMUV7QY.js → chunk-BKF3A357.js} +1 -1
- package/dist/{chunk-YC5MFXA5.js → chunk-GR4I3MN2.js} +37 -15
- package/dist/{chunk-A2X45FET.js → chunk-I5YWVQ5R.js} +1 -1
- package/dist/{chunk-ERY4S6QV.js → chunk-JW47XCRL.js} +6 -1
- package/dist/{chunk-XB7LH4J2.js → chunk-QTMHS7JD.js} +2 -1
- package/dist/{chunk-W2XJKG6C.js → chunk-RBQN3VSY.js} +2 -2
- package/dist/{chunk-OOPIETLW.js → chunk-S5ZU5WUU.js} +1 -1
- package/dist/{chunk-ABPKM4GK.js → chunk-STIFILQG.js} +1 -1
- package/dist/chunk-WHPZED7X.js +57 -0
- package/dist/{chunk-CHLGW22F.js → chunk-XAMUOSX7.js} +3 -3
- package/dist/{chunk-IXCUY3B3.js → chunk-XYZOJ5NZ.js} +195 -52
- package/dist/cli.js +5 -5
- package/dist/{compose-video-CN3VSWST.js → compose-video-TQOHDXNW.js} +4 -4
- package/dist/{events-_wfjbmEp.d.ts → events-CTIsANzz.d.ts} +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/{kit-BMNcHqa9.d.ts → kit-DA2cfJ96.d.ts} +1 -1
- package/dist/react.d.ts +7 -4
- package/dist/react.js +226 -30
- package/dist/server.d.ts +21 -4
- package/dist/server.js +205 -18
- package/dist/system-prompt-NMYHLAMJ.js +10 -0
- package/dist/template-catalog.js +1 -1
- package/dist/templates.d.ts +3 -3
- package/dist/test.d.ts +3 -2
- package/dist/test.js +3 -3
- package/dist/{text-stream-6XHC7J47.js → text-stream-UPGUD2TD.js} +2 -2
- package/dist/{types-B-PZR6G_.d.ts → types-CkO2EYr4.d.ts} +8 -4
- package/docs/concepts.md +11 -1
- package/docs/custom-templates.md +34 -6
- package/docs/customization.md +2 -1
- package/docs/errors.md +3 -1
- package/docs/getting-started.md +13 -10
- package/docs/input-and-first-scene.md +17 -6
- package/docs/integrate-nextjs.md +6 -3
- package/docs/media-and-audio.md +73 -14
- package/docs/prompt-and-input.md +27 -5
- package/docs/provider-integration.md +45 -2
- package/docs/reference/protocol.md +9 -0
- package/examples/nextjs-quickstart/README.md +3 -1
- package/examples/nextjs-quickstart/package.json +3 -2
- package/examples/nextjs-quickstart/src/app/api/video/route.ts +1 -1
- package/package.json +1 -1
- package/registry/items/brandMessage.json +1 -2
- package/registry/items/media.json +2 -1
- package/dist/chunk-FQ47WXAJ.js +0 -38
- package/dist/system-prompt-A6UXNTPK.js +0 -8
package/dist/react.js
CHANGED
|
@@ -2,14 +2,14 @@ import {
|
|
|
2
2
|
VIDEO_STREAM_CONTENT_TYPE,
|
|
3
3
|
VIDEO_STREAM_HEADER,
|
|
4
4
|
decodeVideoSse
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-S5ZU5WUU.js";
|
|
6
6
|
import {
|
|
7
7
|
applyVideoEvent,
|
|
8
8
|
createVideoState
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-STIFILQG.js";
|
|
10
10
|
import {
|
|
11
11
|
safePublicDiagnostic
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-JW47XCRL.js";
|
|
13
13
|
import {
|
|
14
14
|
parseVideo
|
|
15
15
|
} from "./chunk-GHJEAP4O.js";
|
|
@@ -24,12 +24,12 @@ import {
|
|
|
24
24
|
BUILTIN_TEMPLATE_CAPABILITIES,
|
|
25
25
|
BUILTIN_TEMPLATE_CATALOG,
|
|
26
26
|
getBuiltinTemplateMetadata
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-XAMUOSX7.js";
|
|
28
28
|
import "./chunk-2E6T633S.js";
|
|
29
29
|
import {
|
|
30
30
|
VideoFrame,
|
|
31
31
|
getDimensions
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-QTMHS7JD.js";
|
|
33
33
|
import {
|
|
34
34
|
fontStack
|
|
35
35
|
} from "./chunk-FNAEQ7QO.js";
|
|
@@ -144,6 +144,7 @@ function preloadBuiltinTemplate(id) {
|
|
|
144
144
|
|
|
145
145
|
// src/player/video-player.tsx
|
|
146
146
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
147
|
+
var MINIMUM_GENERATION_INTRO_MS = 3e3;
|
|
147
148
|
function savedVideoState(video) {
|
|
148
149
|
return {
|
|
149
150
|
...createVideoState(),
|
|
@@ -155,6 +156,7 @@ function VideoPlayerRuntime({
|
|
|
155
156
|
kit,
|
|
156
157
|
stream,
|
|
157
158
|
video,
|
|
159
|
+
playbackMode,
|
|
158
160
|
autoPlay = true,
|
|
159
161
|
startMuted = true,
|
|
160
162
|
width,
|
|
@@ -167,33 +169,62 @@ function VideoPlayerRuntime({
|
|
|
167
169
|
onError,
|
|
168
170
|
onStateChange
|
|
169
171
|
}) {
|
|
170
|
-
const [reducedMotion] = useState(
|
|
172
|
+
const [reducedMotion, setReducedMotion] = useState(
|
|
171
173
|
() => typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches
|
|
172
174
|
);
|
|
173
|
-
const [
|
|
174
|
-
const
|
|
175
|
+
const [audioUnlocked, setAudioUnlocked] = useState(false);
|
|
176
|
+
const resolvedStartMuted = playbackMode === "muted-autoplay" ? true : playbackMode ? false : startMuted;
|
|
177
|
+
const shouldAutoPlay = playbackMode === "manual" ? false : playbackMode === "autoplay-after-interaction" ? audioUnlocked : playbackMode === "muted-autoplay" || playbackMode === "autoplay-with-sound" ? true : autoPlay;
|
|
178
|
+
const autoStartGeneration = Boolean(playbackMode && stream && shouldAutoPlay && !reducedMotion);
|
|
179
|
+
const [isPlaying, setIsPlaying] = useState(() => shouldAutoPlay && !reducedMotion && !autoStartGeneration);
|
|
180
|
+
const [isMuted, setIsMuted] = useState(resolvedStartMuted);
|
|
175
181
|
const [isFullscreen, setIsFullscreen] = useState(false);
|
|
176
182
|
const [state, setState] = useState(() => video ? savedVideoState(video) : createVideoState());
|
|
177
183
|
const [currentTime, setCurrentTime] = useState(0);
|
|
184
|
+
const [activeStream, setActiveStream] = useState(stream);
|
|
185
|
+
const [replacementPending, setReplacementPending] = useState(false);
|
|
186
|
+
const [startRequested, setStartRequested] = useState(autoStartGeneration);
|
|
187
|
+
const [introPlaying, setIntroPlaying] = useState(autoStartGeneration);
|
|
188
|
+
const [generationIntroComplete, setGenerationIntroComplete] = useState(() => !playbackMode || !stream);
|
|
178
189
|
const [observedWidth, setObservedWidth] = useState(0);
|
|
179
190
|
const containerRef = useRef(null);
|
|
180
191
|
const stateRef = useRef(state);
|
|
181
192
|
const timeRef = useRef(currentTime);
|
|
182
193
|
const audioRef = useRef(null);
|
|
194
|
+
const introStartedAtRef = useRef(autoStartGeneration ? performance.now() : null);
|
|
183
195
|
const callbacksRef = useRef({ onComplete, onError, onStateChange });
|
|
184
196
|
stateRef.current = state;
|
|
185
197
|
timeRef.current = currentTime;
|
|
186
198
|
callbacksRef.current = { onComplete, onError, onStateChange };
|
|
199
|
+
if (stream !== activeStream) {
|
|
200
|
+
const autoStartReplacement = Boolean(playbackMode && stream && shouldAutoPlay && !reducedMotion);
|
|
201
|
+
setActiveStream(stream);
|
|
202
|
+
setReplacementPending(stream != null);
|
|
203
|
+
setState(video ? savedVideoState(video) : createVideoState());
|
|
204
|
+
setCurrentTime(0);
|
|
205
|
+
setIsMuted(resolvedStartMuted);
|
|
206
|
+
setIsPlaying(shouldAutoPlay && !reducedMotion && !autoStartReplacement);
|
|
207
|
+
setStartRequested(autoStartReplacement);
|
|
208
|
+
setIntroPlaying(autoStartReplacement);
|
|
209
|
+
setGenerationIntroComplete(!playbackMode || !stream);
|
|
210
|
+
introStartedAtRef.current = autoStartReplacement ? performance.now() : null;
|
|
211
|
+
}
|
|
187
212
|
useEffect(() => {
|
|
188
213
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
189
214
|
const preference = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
190
215
|
const handleChange = (event) => {
|
|
191
|
-
|
|
216
|
+
setReducedMotion(event.matches);
|
|
217
|
+
if (event.matches) {
|
|
218
|
+
introStartedAtRef.current = null;
|
|
219
|
+
setStartRequested(false);
|
|
220
|
+
setIntroPlaying(false);
|
|
221
|
+
setIsPlaying(false);
|
|
222
|
+
}
|
|
192
223
|
};
|
|
193
224
|
preference.addEventListener?.("change", handleChange);
|
|
194
225
|
return () => preference.removeEventListener?.("change", handleChange);
|
|
195
226
|
}, []);
|
|
196
|
-
useEffect(() => setIsMuted(
|
|
227
|
+
useEffect(() => setIsMuted(resolvedStartMuted), [resolvedStartMuted]);
|
|
197
228
|
useEffect(() => {
|
|
198
229
|
const updateFullscreen = () => setIsFullscreen(document.fullscreenElement === containerRef.current);
|
|
199
230
|
document.addEventListener("fullscreenchange", updateFullscreen);
|
|
@@ -224,6 +255,7 @@ function VideoPlayerRuntime({
|
|
|
224
255
|
...current.config ? { mutableSceneIds } : {}
|
|
225
256
|
});
|
|
226
257
|
stateRef.current = next;
|
|
258
|
+
setReplacementPending(false);
|
|
227
259
|
setState(next);
|
|
228
260
|
callbacksRef.current.onStateChange?.(next);
|
|
229
261
|
if (next.status === "complete" && current.status !== "complete") {
|
|
@@ -302,14 +334,65 @@ function VideoPlayerRuntime({
|
|
|
302
334
|
useEffect(() => {
|
|
303
335
|
const audio = audioRef.current;
|
|
304
336
|
if (!audio) return;
|
|
305
|
-
if (isPlaying) {
|
|
306
|
-
void audio.play().
|
|
337
|
+
if (isPlaying || introPlaying) {
|
|
338
|
+
void audio.play().then(() => {
|
|
339
|
+
if (!audio.muted) setAudioUnlocked(true);
|
|
340
|
+
}).catch(() => {
|
|
341
|
+
audio.currentTime = 0;
|
|
342
|
+
timeRef.current = 0;
|
|
343
|
+
setCurrentTime(0);
|
|
344
|
+
setStartRequested(false);
|
|
345
|
+
setIntroPlaying(false);
|
|
307
346
|
setIsPlaying(false);
|
|
308
347
|
});
|
|
309
348
|
} else {
|
|
310
349
|
audio.pause();
|
|
311
350
|
}
|
|
312
|
-
}, [isPlaying, state.config?.audio?.audioUrl]);
|
|
351
|
+
}, [introPlaying, isPlaying, state.config?.audio?.audioUrl]);
|
|
352
|
+
useEffect(() => {
|
|
353
|
+
if (!state.config?.scenes.length) {
|
|
354
|
+
const terminalWithoutVideo = state.status === "complete" || state.status === "error" || state.status === "aborted";
|
|
355
|
+
if (terminalWithoutVideo) {
|
|
356
|
+
audioRef.current?.pause();
|
|
357
|
+
introStartedAtRef.current = null;
|
|
358
|
+
setStartRequested(false);
|
|
359
|
+
setIntroPlaying(false);
|
|
360
|
+
setGenerationIntroComplete(true);
|
|
361
|
+
}
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
if (!startRequested) return;
|
|
365
|
+
if (state.config.scenes[0]?.id === "supplied-opening") {
|
|
366
|
+
timeRef.current = 0;
|
|
367
|
+
setCurrentTime(0);
|
|
368
|
+
if (audioRef.current) audioRef.current.volume = state.config.audio?.volume ?? 1;
|
|
369
|
+
introStartedAtRef.current = null;
|
|
370
|
+
setStartRequested(false);
|
|
371
|
+
setIntroPlaying(false);
|
|
372
|
+
setGenerationIntroComplete(true);
|
|
373
|
+
setIsPlaying(true);
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
const startedAt = introStartedAtRef.current ?? performance.now();
|
|
377
|
+
introStartedAtRef.current = startedAt;
|
|
378
|
+
const remaining = Math.max(0, MINIMUM_GENERATION_INTRO_MS - (performance.now() - startedAt));
|
|
379
|
+
const startGeneratedVideo = () => {
|
|
380
|
+
timeRef.current = 0;
|
|
381
|
+
setCurrentTime(0);
|
|
382
|
+
if (audioRef.current) audioRef.current.volume = state.config?.audio?.volume ?? 1;
|
|
383
|
+
introStartedAtRef.current = null;
|
|
384
|
+
setStartRequested(false);
|
|
385
|
+
setIntroPlaying(false);
|
|
386
|
+
setGenerationIntroComplete(true);
|
|
387
|
+
setIsPlaying(true);
|
|
388
|
+
};
|
|
389
|
+
if (remaining <= 0) {
|
|
390
|
+
startGeneratedVideo();
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
const timer = setTimeout(startGeneratedVideo, remaining);
|
|
394
|
+
return () => clearTimeout(timer);
|
|
395
|
+
}, [startRequested, state.config?.audio?.volume, state.config?.scenes.length, state.status]);
|
|
313
396
|
const streamOrientation = state.config?.orientation ?? "portrait";
|
|
314
397
|
const responsiveWidth = width ?? observedWidth;
|
|
315
398
|
const orientation = orientationOverride === "auto" ? responsiveWidth > 0 ? responsiveWidth <= responsiveBreakpoint ? "portrait" : "landscape" : streamOrientation : orientationOverride ?? streamOrientation;
|
|
@@ -322,15 +405,63 @@ function VideoPlayerRuntime({
|
|
|
322
405
|
const duration = config ? getVideoDuration(config) : 0;
|
|
323
406
|
const terminal = state.status === "complete" || state.status === "error" || state.status === "aborted";
|
|
324
407
|
const ended = terminal && duration > 0 && currentTime >= duration - 1e-3;
|
|
408
|
+
const generationIntroWaiting = Boolean(playbackMode && stream && !generationIntroComplete);
|
|
409
|
+
const firstSceneRange = config ? resolveVideoTimeline(config)[0] : void 0;
|
|
410
|
+
const hasSuppliedOpening = firstSceneRange?.scene.id === "supplied-opening";
|
|
411
|
+
const showStartPoster = (!generationIntroWaiting || hasSuppliedOpening) && !startRequested && !isPlaying && !ended && currentTime <= 1e-3 && Boolean(config?.scenes.length);
|
|
412
|
+
const firstSceneHoldProgress = firstSceneRange ? kit.getTemplateMetadata(firstSceneRange.scene.templateId)?.transitionTiming?.holdProgress ?? 0.7 : 0;
|
|
413
|
+
const posterTime = firstSceneRange ? firstSceneRange.start + Math.max(0, firstSceneRange.end - firstSceneRange.start) * firstSceneHoldProgress : currentTime;
|
|
414
|
+
const startPlayback = () => {
|
|
415
|
+
setGenerationIntroComplete(true);
|
|
416
|
+
const audio = audioRef.current;
|
|
417
|
+
if (audio) {
|
|
418
|
+
void audio.play().then(() => {
|
|
419
|
+
if (!audio.muted) setAudioUnlocked(true);
|
|
420
|
+
}).catch(() => {
|
|
421
|
+
audio.currentTime = 0;
|
|
422
|
+
timeRef.current = 0;
|
|
423
|
+
setCurrentTime(0);
|
|
424
|
+
setIsPlaying(false);
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
setIsPlaying(true);
|
|
428
|
+
};
|
|
429
|
+
const armPlayback = () => {
|
|
430
|
+
introStartedAtRef.current = performance.now();
|
|
431
|
+
setStartRequested(true);
|
|
432
|
+
setIntroPlaying(true);
|
|
433
|
+
const audio = audioRef.current;
|
|
434
|
+
if (!audio) return;
|
|
435
|
+
const volume = stateRef.current.config?.audio?.volume ?? 1;
|
|
436
|
+
audio.volume = volume;
|
|
437
|
+
void audio.play().then(() => {
|
|
438
|
+
if (!audio.muted) setAudioUnlocked(true);
|
|
439
|
+
}).catch(() => {
|
|
440
|
+
audio.volume = volume;
|
|
441
|
+
audio.currentTime = 0;
|
|
442
|
+
timeRef.current = 0;
|
|
443
|
+
setCurrentTime(0);
|
|
444
|
+
introStartedAtRef.current = null;
|
|
445
|
+
setStartRequested(false);
|
|
446
|
+
setIntroPlaying(false);
|
|
447
|
+
setIsPlaying(false);
|
|
448
|
+
});
|
|
449
|
+
};
|
|
325
450
|
const togglePlayback = () => {
|
|
451
|
+
if (startRequested) return;
|
|
452
|
+
if (!stateRef.current.config?.scenes.length) {
|
|
453
|
+
armPlayback();
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
326
456
|
if (!isPlaying && ended) {
|
|
327
457
|
timeRef.current = 0;
|
|
328
458
|
setCurrentTime(0);
|
|
329
459
|
if (audioRef.current) audioRef.current.currentTime = 0;
|
|
330
|
-
|
|
460
|
+
startPlayback();
|
|
331
461
|
return;
|
|
332
462
|
}
|
|
333
|
-
|
|
463
|
+
if (isPlaying) setIsPlaying(false);
|
|
464
|
+
else startPlayback();
|
|
334
465
|
};
|
|
335
466
|
const toggleFullscreen = async () => {
|
|
336
467
|
const container = containerRef.current;
|
|
@@ -352,7 +483,31 @@ function VideoPlayerRuntime({
|
|
|
352
483
|
font: "600 13px/1 system-ui, sans-serif",
|
|
353
484
|
cursor: "pointer"
|
|
354
485
|
};
|
|
355
|
-
const
|
|
486
|
+
const startButtonStyle = {
|
|
487
|
+
display: "inline-flex",
|
|
488
|
+
alignItems: "center",
|
|
489
|
+
gap: 10,
|
|
490
|
+
minHeight: 54,
|
|
491
|
+
padding: "12px 18px",
|
|
492
|
+
border: "1px solid rgba(255, 255, 255, 0.3)",
|
|
493
|
+
borderRadius: 999,
|
|
494
|
+
backgroundColor: "rgba(9, 7, 18, 0.88)",
|
|
495
|
+
color: "#ffffff",
|
|
496
|
+
boxShadow: "0 8px 28px rgba(0, 0, 0, 0.4)",
|
|
497
|
+
backdropFilter: "blur(12px)",
|
|
498
|
+
font: "700 15px/1 system-ui, sans-serif",
|
|
499
|
+
cursor: "pointer"
|
|
500
|
+
};
|
|
501
|
+
const startButtonPositionStyle = {
|
|
502
|
+
position: "absolute",
|
|
503
|
+
left: "50%",
|
|
504
|
+
top: "50%",
|
|
505
|
+
zIndex: 3,
|
|
506
|
+
transform: "translate(-50%, -50%)"
|
|
507
|
+
};
|
|
508
|
+
const pendingReplacement = replacementPending && state.status === "idle";
|
|
509
|
+
const displayedStatus = pendingReplacement ? "streaming" : state.status;
|
|
510
|
+
const generationCoverVisible = generationIntroWaiting && !hasSuppliedOpening || displayedStatus === "streaming" && !config?.scenes.length;
|
|
356
511
|
const coverBackground = config?.style.brand.background;
|
|
357
512
|
const coverText = config?.style.brand.colors.foreground ?? "#ffffff";
|
|
358
513
|
const coverBackgroundCss = coverBackground?.type === "solid" ? coverBackground.color : `linear-gradient(135deg, ${coverBackground?.colors[0] ?? "#8711C1"}, ${coverBackground?.colors[1] ?? "#2167E3"})`;
|
|
@@ -370,13 +525,19 @@ function VideoPlayerRuntime({
|
|
|
370
525
|
}
|
|
371
526
|
},
|
|
372
527
|
"data-testid": "video-player",
|
|
373
|
-
"data-status":
|
|
528
|
+
"data-status": displayedStatus,
|
|
374
529
|
"data-finish-reason": state.finishReason,
|
|
375
530
|
"data-scenes": config?.scenes.length ?? 0,
|
|
376
531
|
"data-orientation": orientation,
|
|
377
532
|
"data-current-time": currentTime.toFixed(3),
|
|
378
|
-
"data-playing": isPlaying,
|
|
533
|
+
"data-playing": isPlaying || introPlaying,
|
|
379
534
|
"data-ended": ended,
|
|
535
|
+
"data-start-poster": showStartPoster,
|
|
536
|
+
"data-start-requested": startRequested,
|
|
537
|
+
"data-intro-playing": introPlaying,
|
|
538
|
+
"data-generation-intro-complete": generationIntroComplete,
|
|
539
|
+
"data-audio-unlocked": audioUnlocked,
|
|
540
|
+
"data-playback-mode": playbackMode ?? "custom",
|
|
380
541
|
className,
|
|
381
542
|
style: {
|
|
382
543
|
width: width ?? "100%",
|
|
@@ -387,7 +548,7 @@ function VideoPlayerRuntime({
|
|
|
387
548
|
...style
|
|
388
549
|
},
|
|
389
550
|
children: [
|
|
390
|
-
generationCoverVisible ? /* @__PURE__ */
|
|
551
|
+
generationCoverVisible ? /* @__PURE__ */ jsxs(
|
|
391
552
|
"div",
|
|
392
553
|
{
|
|
393
554
|
"data-testid": "video-generation-cover",
|
|
@@ -404,18 +565,33 @@ function VideoPlayerRuntime({
|
|
|
404
565
|
background: coverBackgroundCss,
|
|
405
566
|
fontFamily: fontStack(config?.style.brand.font)
|
|
406
567
|
},
|
|
407
|
-
children:
|
|
408
|
-
/* @__PURE__ */
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
568
|
+
children: [
|
|
569
|
+
/* @__PURE__ */ jsxs("div", { style: { position: "absolute", top: "28%", left: "10%", right: "10%" }, children: [
|
|
570
|
+
/* @__PURE__ */ jsx("div", { "aria-hidden": "true", style: { fontSize: "clamp(28px, 8vw, 72px)", opacity: 0.9 }, children: "\u2726" }),
|
|
571
|
+
/* @__PURE__ */ jsx("strong", { style: { display: "block", marginTop: 18, fontSize: "clamp(24px, 5vw, 56px)", lineHeight: 1.08 }, children: "Creating your video\u2026" }),
|
|
572
|
+
/* @__PURE__ */ jsx("span", { style: { display: "block", marginTop: 14, fontSize: "clamp(14px, 2vw, 22px)", lineHeight: 1.4, opacity: 0.78 }, children: "Choosing the best scenes for your content." })
|
|
573
|
+
] }),
|
|
574
|
+
!startRequested && !isPlaying ? /* @__PURE__ */ jsxs(
|
|
575
|
+
"button",
|
|
576
|
+
{
|
|
577
|
+
type: "button",
|
|
578
|
+
"aria-label": config?.audio && !isMuted ? "Play video with sound" : "Play video response",
|
|
579
|
+
onClick: armPlayback,
|
|
580
|
+
style: { ...startButtonStyle, ...startButtonPositionStyle },
|
|
581
|
+
children: [
|
|
582
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\u25B6" }),
|
|
583
|
+
config?.audio && !isMuted ? "Play with sound" : "Play video"
|
|
584
|
+
]
|
|
585
|
+
}
|
|
586
|
+
) : null
|
|
587
|
+
]
|
|
412
588
|
}
|
|
413
589
|
) : config?.scenes.length ? /* @__PURE__ */ jsx(
|
|
414
590
|
VideoFrame,
|
|
415
591
|
{
|
|
416
592
|
kit,
|
|
417
593
|
config: displayConfig,
|
|
418
|
-
time: currentTime,
|
|
594
|
+
time: showStartPoster ? posterTime : currentTime,
|
|
419
595
|
width: dimensions.width,
|
|
420
596
|
height: dimensions.height,
|
|
421
597
|
playing: isPlaying,
|
|
@@ -427,6 +603,23 @@ function VideoPlayerRuntime({
|
|
|
427
603
|
}
|
|
428
604
|
}
|
|
429
605
|
) : null,
|
|
606
|
+
showStartPoster ? /* @__PURE__ */ jsxs(
|
|
607
|
+
"button",
|
|
608
|
+
{
|
|
609
|
+
type: "button",
|
|
610
|
+
"data-testid": "video-start-button",
|
|
611
|
+
"aria-label": config?.audio && !isMuted ? "Play video with sound" : "Play video response",
|
|
612
|
+
onClick: startPlayback,
|
|
613
|
+
style: {
|
|
614
|
+
...startButtonStyle,
|
|
615
|
+
...startButtonPositionStyle
|
|
616
|
+
},
|
|
617
|
+
children: [
|
|
618
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\u25B6" }),
|
|
619
|
+
config?.audio && !isMuted ? "Play with sound" : "Play video"
|
|
620
|
+
]
|
|
621
|
+
}
|
|
622
|
+
) : null,
|
|
430
623
|
config?.audio ? /* @__PURE__ */ jsx(
|
|
431
624
|
"audio",
|
|
432
625
|
{
|
|
@@ -435,7 +628,7 @@ function VideoPlayerRuntime({
|
|
|
435
628
|
autoPlay: isPlaying,
|
|
436
629
|
muted: isMuted,
|
|
437
630
|
preload: "auto",
|
|
438
|
-
loop: state.status === "streaming"
|
|
631
|
+
loop: state.status === "streaming" || introPlaying
|
|
439
632
|
}
|
|
440
633
|
) : null,
|
|
441
634
|
!generationCoverVisible ? /* @__PURE__ */ jsxs(
|
|
@@ -460,23 +653,26 @@ function VideoPlayerRuntime({
|
|
|
460
653
|
boxShadow: "0 4px 20px rgba(0, 0, 0, 0.35)"
|
|
461
654
|
},
|
|
462
655
|
children: [
|
|
463
|
-
/* @__PURE__ */ jsx(
|
|
656
|
+
!showStartPoster ? /* @__PURE__ */ jsx(
|
|
464
657
|
"button",
|
|
465
658
|
{
|
|
466
659
|
type: "button",
|
|
467
660
|
"aria-label": ended ? "Replay video response" : isPlaying ? "Pause video response" : "Play video response",
|
|
468
661
|
onClick: togglePlayback,
|
|
469
662
|
style: controlButtonStyle,
|
|
470
|
-
children: ended ? "\u21BB" : isPlaying ? "\u2161" : "\u25B6"
|
|
663
|
+
children: ended ? "\u21BB Replay" : isPlaying ? "\u2161" : "\u25B6"
|
|
471
664
|
}
|
|
472
|
-
),
|
|
665
|
+
) : null,
|
|
473
666
|
config?.audio ? /* @__PURE__ */ jsx(
|
|
474
667
|
"button",
|
|
475
668
|
{
|
|
476
669
|
type: "button",
|
|
477
670
|
"aria-label": isMuted ? "Unmute video response" : "Mute video response",
|
|
478
671
|
"aria-pressed": !isMuted,
|
|
479
|
-
onClick: () => setIsMuted((muted) =>
|
|
672
|
+
onClick: () => setIsMuted((muted) => {
|
|
673
|
+
if (muted) setAudioUnlocked(true);
|
|
674
|
+
return !muted;
|
|
675
|
+
}),
|
|
480
676
|
style: controlButtonStyle,
|
|
481
677
|
children: isMuted ? "\u{1F507}" : "\u{1F50A}"
|
|
482
678
|
}
|
package/dist/server.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { b as VideoFinishReason, a as VideoWarning, V as VideoEvent } from './events-
|
|
3
|
-
export { c as VideoWarningCategory } from './events-
|
|
1
|
+
import { m as VideoGenerationContext, n as VideoPlanner, o as VideoRequest, k as VideoCapabilities, d as VideoInput, a as VideoAudio, p as VideoSceneValidator, q as VideoTemplatePacing, r as VideoSnapshotRetention, s as VideoResumeCursor, t as VideoSceneValidationContext, g as VideoScene } from './types-CkO2EYr4.js';
|
|
2
|
+
import { b as VideoFinishReason, a as VideoWarning, V as VideoEvent } from './events-CTIsANzz.js';
|
|
3
|
+
export { c as VideoWarningCategory } from './events-CTIsANzz.js';
|
|
4
4
|
import { S as SceneTemplateMetadata } from './catalog-types-BIhSpOWK.js';
|
|
5
5
|
|
|
6
6
|
interface VideoProviderUsage {
|
|
@@ -84,6 +84,8 @@ interface VideoStreamHandlerOptions {
|
|
|
84
84
|
onComplete?: (summary: VideoGenerationSummary) => unknown;
|
|
85
85
|
/** Drop malformed generated parts by default, or preserve fail-fast behavior. */
|
|
86
86
|
invalidPartBehavior?: "drop" | "fail";
|
|
87
|
+
/** Require one explicit closer before a standard generated plan is considered complete. */
|
|
88
|
+
requireCloser?: boolean;
|
|
87
89
|
/** Allow credentialed cross-origin requests from explicit allowedOrigins. */
|
|
88
90
|
allowCredentials?: boolean;
|
|
89
91
|
/** Templates and extensions implemented by this customer deployment. */
|
|
@@ -120,6 +122,19 @@ declare function createTemplateSceneValidator(options: {
|
|
|
120
122
|
}) => boolean;
|
|
121
123
|
}): VideoSceneValidator;
|
|
122
124
|
|
|
125
|
+
interface ResolvedMedia {
|
|
126
|
+
url: string;
|
|
127
|
+
type: "image" | "video";
|
|
128
|
+
posterUrl?: string;
|
|
129
|
+
}
|
|
130
|
+
interface MediaResolverContext {
|
|
131
|
+
input: VideoInput;
|
|
132
|
+
templateId: string;
|
|
133
|
+
preferredType: "image" | "video" | "any";
|
|
134
|
+
signal: AbortSignal;
|
|
135
|
+
}
|
|
136
|
+
type MediaResolver = (query: string, context: MediaResolverContext) => ResolvedMedia | null | Promise<ResolvedMedia | null>;
|
|
137
|
+
|
|
123
138
|
interface VideoHandlerOptions extends Omit<VideoStreamHandlerOptions, "generate" | "systemPrompt" | "supportedCapabilities" | "validateScene" | "getTemplatePacing"> {
|
|
124
139
|
/** Customer-owned templates that replace matching built-ins and add new IDs. */
|
|
125
140
|
templates?: ServerTemplateRegistry;
|
|
@@ -131,6 +146,8 @@ interface VideoHandlerOptions extends Omit<VideoStreamHandlerOptions, "generate"
|
|
|
131
146
|
basePrompt?: string;
|
|
132
147
|
/** Authorize an app-approved media URL in addition to URLs supplied in the request. */
|
|
133
148
|
allowMediaUrl?: Parameters<typeof createTemplateSceneValidator>[0]["allowMediaUrl"];
|
|
149
|
+
/** Resolve bounded semantic media intent through an application-owned provider. */
|
|
150
|
+
resolveMedia?: MediaResolver;
|
|
134
151
|
}
|
|
135
152
|
/**
|
|
136
153
|
* Build the secure route for a template kit while leaving provider, model,
|
|
@@ -138,4 +155,4 @@ interface VideoHandlerOptions extends Omit<VideoStreamHandlerOptions, "generate"
|
|
|
138
155
|
*/
|
|
139
156
|
declare function createVideoHandler(options: VideoHandlerOptions): VideoStreamHandler;
|
|
140
157
|
|
|
141
|
-
export { SceneTemplateMetadata as ServerTemplateMetadata, type ServerTemplateRegistry, VideoFinishReason, type VideoGenerationSummary, type VideoHandlerOptions, type VideoProviderUsage, VideoWarning, createServerTemplateRegistry, createVideoHandler };
|
|
158
|
+
export { type MediaResolver, type MediaResolverContext, type ResolvedMedia, SceneTemplateMetadata as ServerTemplateMetadata, type ServerTemplateRegistry, VideoFinishReason, type VideoGenerationSummary, type VideoHandlerOptions, type VideoProviderUsage, VideoWarning, createServerTemplateRegistry, createVideoHandler };
|