@vanillaskyai/video 0.5.8 → 0.7.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 +178 -0
- package/PUBLIC-API.md +129 -9
- package/README.md +70 -108
- package/dist/{bg-confetti-SHQI7ATB.js → bg-confetti-HITCGLGD.js} +1 -1
- package/dist/{bg-emoji-XYFRA63Q.js → bg-emoji-VU4UZYZN.js} +1 -1
- package/dist/{bg-media-FEBATBT2.js → bg-media-L34PDQXJ.js} +4 -4
- package/dist/{brand-message-P56WEJPG.js → brand-message-FUJ4STFO.js} +3 -3
- package/dist/{builtin-server-YHEZ2JRF.js → builtin-server-KB7FKF6A.js} +2 -2
- package/dist/{chart-bar-ZB45ZRKH.js → chart-bar-EGPHJATL.js} +4 -4
- package/dist/{chart-counter-HFYNE4HT.js → chart-counter-5FFWQNZO.js} +4 -4
- package/dist/{chart-progress-ring-ZKMLRGSB.js → chart-progress-ring-JMXQLMLC.js} +4 -4
- package/dist/check-runtime.js +2 -2
- package/dist/{chunk-66MNRUCR.js → chunk-2PYO6VAC.js} +51 -3
- package/dist/{chunk-ZQQQAAKP.js → chunk-2XT4MZ76.js} +33 -2
- package/dist/chunk-5CDAM24P.js +31 -0
- package/dist/{chunk-PNS52FL4.js → chunk-5SLENAJW.js} +19 -6
- package/dist/{chunk-EFL34TXF.js → chunk-AITKH6QT.js} +24 -8
- package/dist/{chunk-HT6BGERF.js → chunk-FRN6WKHA.js} +28 -10
- package/dist/{chunk-FZHMQFG3.js → chunk-GAIOHGNR.js} +5 -21
- package/dist/{chunk-3RV4YKB3.js → chunk-JNN3EYVP.js} +51 -26
- package/dist/{chunk-NGY3TNND.js → chunk-K746NUIP.js} +70 -50
- package/dist/{chunk-HVCPEAQF.js → chunk-LKBZX7GV.js} +9 -6
- package/dist/{chunk-G66Z5CWR.js → chunk-MMUXVA47.js} +27 -3
- package/dist/{chunk-6M6DATLW.js → chunk-MXZSDGZQ.js} +6 -5
- package/dist/{chunk-3OU7HIEB.js → chunk-RE4IMWJR.js} +15 -31
- package/dist/{chunk-FVTMYS6U.js → chunk-RGF452LL.js} +1 -1
- package/dist/{chunk-34O5BY6X.js → chunk-RXHW4EP4.js} +21 -4
- package/dist/chunk-SKRGRKHY.js +142 -0
- package/dist/{chunk-TCEHK2BW.js → chunk-YJJC4N4D.js} +2 -1
- package/dist/cli.js +438 -30
- package/dist/{compose-video-JWIEDTEJ.js → compose-video-PD6LKKRK.js} +4 -4
- package/dist/{cta-logo-S4OMTNXD.js → cta-logo-YR7LYUR5.js} +3 -3
- package/dist/{cta-media-EROTHDRR.js → cta-media-DQJBKUO2.js} +4 -4
- package/dist/{events-BBP30j3c.d.ts → events-B6qS1Lsb.d.ts} +2 -2
- package/dist/{incoming-call-5IWJ2TAS.js → incoming-call-54KQ7O5A.js} +3 -3
- package/dist/index.d.ts +89 -3
- package/dist/index.js +12 -1
- package/dist/{infographic-before-after-2I7YZVDD.js → infographic-before-after-ROS52GOW.js} +1 -1
- package/dist/{infographic-feature-list-7SK65U3K.js → infographic-feature-list-E7MGUDAN.js} +4 -4
- package/dist/{infographic-problem-solution-IW35S6BR.js → infographic-problem-solution-3S6NGO5N.js} +4 -4
- package/dist/{infographic-stat-row-XHUZZPDM.js → infographic-stat-row-SYB7AB7H.js} +4 -4
- package/dist/{infographic-steps-JDDEDI7X.js → infographic-steps-KCE6JWE2.js} +4 -4
- package/dist/{kit-DEG3fcaL.d.ts → kit-8g46H2RZ.d.ts} +1 -1
- package/dist/{prompt-input-6ZWXEL3V.js → prompt-input-MHX4O42G.js} +3 -3
- package/dist/react.d.ts +200 -6
- package/dist/react.js +1859 -43
- package/dist/{reaction-Z3JIM3MQ.js → reaction-SLEGR3BE.js} +4 -4
- package/dist/{scene-video-backdrop-IL4F2SVD.js → scene-video-backdrop-XFPX4O3I.js} +2 -1
- package/dist/server.d.ts +104 -4
- package/dist/server.js +976 -26
- package/dist/{showcase-code-NWQAAJIA.js → showcase-code-2HLAVKBM.js} +4 -4
- package/dist/{showcase-phone-5UW45ATT.js → showcase-phone-Q4HEO4LH.js} +4 -4
- package/dist/{showcase-terminal-UVOD25UF.js → showcase-terminal-DL45LUFG.js} +4 -4
- package/dist/{showcase-web-3AW6VHIG.js → showcase-web-2QZO73FZ.js} +4 -4
- package/dist/{social-milestone-KPKHFOB5.js → social-milestone-GEFUQSBF.js} +3 -3
- package/dist/{social-notification-EDOU6TZB.js → social-notification-FJ5VHVLK.js} +3 -3
- package/dist/{social-review-stack-EZOO33SV.js → social-review-stack-KXQCKFRP.js} +3 -3
- package/dist/{social-testimonial-DLOINMMY.js → social-testimonial-JZ7CHC7S.js} +3 -3
- package/dist/{social-tweet-6JUM323G.js → social-tweet-UCDXM25F.js} +3 -3
- package/dist/{system-prompt-4I6Z5HK3.js → system-prompt-RRXIWDDD.js} +5 -3
- package/dist/template-catalog.js +1 -1
- package/dist/templates.d.ts +3 -3
- package/dist/test.d.ts +2 -2
- package/dist/test.js +3 -3
- package/dist/{text-stream-J6EDDJP4.js → text-stream-FW4BLBAL.js} +2 -2
- package/dist/{types-BV9IqExh.d.ts → types-2wHBqtg8.d.ts} +29 -1
- package/dist/types-DrABlRa7.d.ts +46 -0
- package/docs/agent-integration.md +49 -25
- package/docs/architecture.md +37 -22
- package/docs/branding-and-personalization.md +1 -1
- package/docs/concepts.md +14 -0
- package/docs/custom-templates.md +9 -9
- package/docs/customization.md +41 -5
- package/docs/getting-started.md +81 -84
- package/docs/media-and-audio.md +113 -117
- package/docs/persistence.md +1 -1
- package/docs/production.md +81 -92
- package/docs/prompt-and-input.md +71 -161
- package/docs/provider-integration.md +91 -49
- package/docs/responsive-orientation.md +1 -1
- package/docs/security.md +6 -5
- package/docs/streaming-protocol.md +1 -1
- package/docs/testing.md +51 -43
- package/examples/custom-template/README.md +1 -1
- package/package.json +20 -21
- package/registry/items/backgrounds.json +2 -2
- package/registry/items/barChart.json +6 -4
- package/registry/items/beforeAfter.json +1 -1
- package/registry/items/bigNumber.json +4 -3
- package/registry/items/brandMessage.json +3 -2
- package/registry/items/cardList.json +6 -4
- package/registry/items/codeEditor.json +4 -3
- package/registry/items/confetti.json +1 -1
- package/registry/items/ctaLogo.json +3 -2
- package/registry/items/ctaMedia.json +4 -3
- package/registry/items/emojiBurst.json +1 -1
- package/registry/items/incomingCall.json +3 -2
- package/registry/items/media.json +4 -3
- package/registry/items/milestone.json +3 -2
- package/registry/items/notification.json +3 -2
- package/registry/items/phoneMockup.json +4 -3
- package/registry/items/problemSolution.json +4 -3
- package/registry/items/progressRing.json +4 -3
- package/registry/items/promptInput.json +3 -2
- package/registry/items/reaction.json +2 -2
- package/registry/items/reviewStack.json +3 -2
- package/registry/items/steps.json +6 -4
- package/registry/items/terminal.json +5 -4
- package/registry/items/testimonial.json +3 -2
- package/registry/items/tripleStats.json +4 -3
- package/registry/items/tweet.json +3 -2
- package/registry/items/webMockup.json +4 -3
- package/starters/video-chat/.env.example +16 -0
- package/starters/video-chat/README.md +63 -0
- package/starters/video-chat/index.html +12 -0
- package/starters/video-chat/package.json +28 -0
- package/starters/video-chat/server.ts +152 -0
- package/starters/video-chat/src/main.tsx +8 -0
- package/starters/video-chat/stock.ts +139 -0
- package/starters/video-chat/tsconfig.json +20 -0
- package/starters/video-chat/vite.config.ts +81 -0
- package/styles/video-chat.css +713 -0
- package/dist/chunk-C6WVCZRW.js +0 -19
- package/docs/input-and-first-scene.md +0 -64
- package/docs/integrate-nextjs.md +0 -86
- package/docs/live-channels.md +0 -149
- package/docs/use-cases.md +0 -59
- package/examples/nextjs-quickstart/.env.example +0 -2
- package/examples/nextjs-quickstart/README.md +0 -27
- package/examples/nextjs-quickstart/next-env.d.ts +0 -4
- package/examples/nextjs-quickstart/package.json +0 -25
- package/examples/nextjs-quickstart/src/app/api/video/route.ts +0 -24
- package/examples/nextjs-quickstart/src/app/layout.tsx +0 -5
- package/examples/nextjs-quickstart/src/app/page.tsx +0 -31
- package/examples/nextjs-quickstart/tsconfig.json +0 -26
|
@@ -3,23 +3,23 @@ import {
|
|
|
3
3
|
} from "./chunk-E7CL7UPB.js";
|
|
4
4
|
import {
|
|
5
5
|
applyVideoEvent,
|
|
6
|
-
checksumVideo,
|
|
7
6
|
createReplayableStream,
|
|
8
7
|
createVideoState
|
|
9
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-GAIOHGNR.js";
|
|
10
9
|
import {
|
|
11
10
|
parseVideoPlanPart,
|
|
12
11
|
safePublicDiagnostic
|
|
13
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-MMUXVA47.js";
|
|
14
13
|
import {
|
|
15
14
|
MAX_RETAINED_INSTRUCTIONS_LENGTH,
|
|
16
15
|
MAX_RETAINED_MEDIA_URLS,
|
|
17
16
|
MAX_RETAINED_MEDIA_URL_LENGTH,
|
|
18
17
|
MAX_RETAINED_SOURCE_LENGTH,
|
|
18
|
+
checksumVideo,
|
|
19
|
+
createVideoEventFactory,
|
|
19
20
|
parseVideo
|
|
20
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-2PYO6VAC.js";
|
|
21
22
|
import {
|
|
22
|
-
VIDEO_PROTOCOL_VERSION,
|
|
23
23
|
VIDEO_SCHEMA_VERSION,
|
|
24
24
|
createVideoRequest
|
|
25
25
|
} from "./chunk-AOWSXU2K.js";
|
|
@@ -32,25 +32,6 @@ import {
|
|
|
32
32
|
resolveVideoBrand
|
|
33
33
|
} from "./chunk-XGRA2MUV.js";
|
|
34
34
|
|
|
35
|
-
// src/protocol/events.ts
|
|
36
|
-
function createVideoEventFactory(options) {
|
|
37
|
-
let sequence = options.initialSequence ?? 0;
|
|
38
|
-
return {
|
|
39
|
-
create(type, data) {
|
|
40
|
-
const currentSequence = sequence;
|
|
41
|
-
sequence += 1;
|
|
42
|
-
return {
|
|
43
|
-
protocolVersion: VIDEO_PROTOCOL_VERSION,
|
|
44
|
-
runId: options.runId,
|
|
45
|
-
sequence: currentSequence,
|
|
46
|
-
eventId: `${options.runId}:${currentSequence}`,
|
|
47
|
-
type,
|
|
48
|
-
data
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
|
|
54
35
|
// src/server/prompts/user-prompt.ts
|
|
55
36
|
var SUPPLIED_MEDIA_REFERENCE_BASE = "https://vanillasky.invalid/supplied/";
|
|
56
37
|
function suppliedMediaReferences(input) {
|
|
@@ -92,10 +73,12 @@ function buildVideoUserPrompt(input, openingDurationSec = 0) {
|
|
|
92
73
|
"Compose a video response from the structured customer input below.",
|
|
93
74
|
`Knowledge mode: ${input.knowledgeMode ?? "input-only"}.`,
|
|
94
75
|
`Maximum duration: ${input.maxDurationSec ?? 30} seconds, including the supplied opening.`,
|
|
95
|
-
typeof input.opening === "string" && input.opening.trim() ? `The host has already added the opening scene, which consumes ${openingDurationSec} seconds. Continue after it and do not repeat or rewrite it.` : "Add the first grounded scene as soon as it is complete.",
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
76
|
+
input.opening === false ? "The host owns the opening wait. Add the first grounded scene as soon as it is complete; it may use host-resolved media." : typeof input.opening === "string" && input.opening.trim() ? `The host has already added the opening scene, which consumes ${openingDurationSec} seconds. Continue after it and do not repeat or rewrite it.` : "Add the first grounded scene as soon as it is complete.",
|
|
77
|
+
...input.opening === false ? [] : [
|
|
78
|
+
"The first generated body scene must be fully playable without external media. Use a content-fit text, data, comparison, list, or device-free template with no media URL or keyword.",
|
|
79
|
+
"Never use media, ctaMedia, or reaction as the first generated body template, even with mediaType=gradient. Choose a non-media template first.",
|
|
80
|
+
"Add that scene before resolving any stock or supplied asset. Resolve media as part of each complete later body scene."
|
|
81
|
+
],
|
|
99
82
|
"Use only claims supported by the factual basis permitted by the trusted system prompt.",
|
|
100
83
|
"Select the most decision-relevant grounded takeaways that fit the duration; represent each selected takeaway once before completing the response.",
|
|
101
84
|
"For a long source, summarize instead of attempting to represent every fact, unless the creative instructions explicitly request complete fact coverage that fits the duration.",
|
|
@@ -107,7 +90,7 @@ function buildVideoUserPrompt(input, openingDurationSec = 0) {
|
|
|
107
90
|
"After the first playable body scene, emit exactly one scene.add with placement closer. Generate a short grounded conclusion that answers the story's so-what; it must not repeat hook language or imply another scene follows.",
|
|
108
91
|
"Use a different suitable template for each body scene when the catalog supports it.",
|
|
109
92
|
"Never add filler to satisfy a count or diversity target.",
|
|
110
|
-
input.suppliedMedia?.length ? "Select zero or more relevant opaque supplied-media references for visible later scenes. Never invent or transform a reference. Only emit mediaKeyword when the trusted system catalog explicitly exposes it, and only on later scenes. Never invent mediaUrl or mediaPoster." : "No supplied media URL is available. Use asset-free templates unless the trusted system catalog explicitly permits host-resolved media intent. Only emit mediaKeyword when the trusted system catalog explicitly exposes it, and only on later scenes. Never invent mediaUrl or mediaPoster.",
|
|
93
|
+
input.suppliedMedia?.length ? input.opening === false ? "Select zero or more relevant opaque supplied-media references for visible scenes. Never invent or transform a reference. Only emit mediaKeyword when the trusted system catalog explicitly exposes it. Never invent mediaUrl or mediaPoster." : "Select zero or more relevant opaque supplied-media references for visible later scenes. Never invent or transform a reference. Only emit mediaKeyword when the trusted system catalog explicitly exposes it, and only on later scenes. Never invent mediaUrl or mediaPoster." : input.opening === false ? "No supplied media URL is available. Use asset-free templates unless the trusted system catalog explicitly permits host-resolved media intent, which may begin on the first scene. Only emit mediaKeyword when the trusted system catalog explicitly exposes it. Never invent mediaUrl or mediaPoster." : "No supplied media URL is available. Use asset-free templates unless the trusted system catalog explicitly permits host-resolved media intent. Only emit mediaKeyword when the trusted system catalog explicitly exposes it, and only on later scenes. Never invent mediaUrl or mediaPoster.",
|
|
111
94
|
"",
|
|
112
95
|
"RAW INPUT",
|
|
113
96
|
input.input.trim(),
|
|
@@ -225,7 +208,8 @@ function buildInitialComposition(input, audio, snapshotRetention, closerReserveS
|
|
|
225
208
|
motion: input.style?.motion ?? "normal",
|
|
226
209
|
defaultBackgroundEffect: input.style?.backgroundEffect ?? "static",
|
|
227
210
|
defaultTextArchetype: input.style?.textArchetype ?? "subtle",
|
|
228
|
-
defaultTransition: "crossfade"
|
|
211
|
+
defaultTransition: "crossfade",
|
|
212
|
+
...input.style?.generatedLook ? { generatedLook: input.style.generatedLook } : {}
|
|
229
213
|
},
|
|
230
214
|
meta
|
|
231
215
|
},
|
|
@@ -670,7 +654,7 @@ function createVideo(rawInput, options) {
|
|
|
670
654
|
position
|
|
671
655
|
}));
|
|
672
656
|
}
|
|
673
|
-
const systemPrompt = options.systemPrompt ?? (await import("./system-prompt-
|
|
657
|
+
const systemPrompt = options.systemPrompt ?? (await import("./system-prompt-RRXIWDDD.js")).createVideoSystemPrompt(input.knowledgeMode);
|
|
674
658
|
const context = { request, systemPrompt, userPrompt, initialConfig, signal: controller.signal };
|
|
675
659
|
attachGenerationLifecycleSink(context, lifecycle);
|
|
676
660
|
for await (const untrustedPart of options.generate(context)) {
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from "./chunk-E7CL7UPB.js";
|
|
7
7
|
import {
|
|
8
8
|
parseVideoPlanPart
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-MMUXVA47.js";
|
|
10
10
|
|
|
11
11
|
// src/server/model/truncated-json.ts
|
|
12
12
|
function isConfidentlyTruncatedJson(source) {
|
|
@@ -48,11 +48,28 @@ function parsePlanLine(line) {
|
|
|
48
48
|
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
49
49
|
const object = value;
|
|
50
50
|
const scene = object.scene;
|
|
51
|
-
if (object.type === "scene.add" &&
|
|
52
|
-
const {
|
|
51
|
+
if (object.type === "scene.add" && scene && typeof scene === "object" && !Array.isArray(scene)) {
|
|
52
|
+
const planPart = { ...object };
|
|
53
|
+
const repairedScene = { ...scene };
|
|
54
|
+
let repaired = false;
|
|
55
|
+
if (object.placement != null && object.placement !== "closer") {
|
|
56
|
+
delete planPart.placement;
|
|
57
|
+
repaired = true;
|
|
58
|
+
}
|
|
59
|
+
if (object.timing != null && !("timing" in scene)) {
|
|
60
|
+
repairedScene.timing = object.timing;
|
|
61
|
+
delete planPart.timing;
|
|
62
|
+
repaired = true;
|
|
63
|
+
}
|
|
64
|
+
if (object.narration != null && !("narration" in scene)) {
|
|
65
|
+
repairedScene.narration = object.narration;
|
|
66
|
+
delete planPart.narration;
|
|
67
|
+
repaired = true;
|
|
68
|
+
}
|
|
69
|
+
if (!repaired) return parseVideoPlanPart(value);
|
|
53
70
|
return parseVideoPlanPart({
|
|
54
71
|
...planPart,
|
|
55
|
-
scene:
|
|
72
|
+
scene: repairedScene
|
|
56
73
|
});
|
|
57
74
|
}
|
|
58
75
|
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import {
|
|
2
|
+
checksumVideo,
|
|
3
|
+
createVideoEventFactory
|
|
4
|
+
} from "./chunk-2PYO6VAC.js";
|
|
5
|
+
import {
|
|
6
|
+
VIDEO_SCHEMA_VERSION
|
|
7
|
+
} from "./chunk-AOWSXU2K.js";
|
|
8
|
+
import {
|
|
9
|
+
getReadableSceneDuration
|
|
10
|
+
} from "./chunk-3O7OMMMF.js";
|
|
11
|
+
|
|
12
|
+
// src/protocol/scene-timeline.ts
|
|
13
|
+
function createQueue() {
|
|
14
|
+
const buffered = [];
|
|
15
|
+
const waiting = [];
|
|
16
|
+
let closed = false;
|
|
17
|
+
return {
|
|
18
|
+
push(value) {
|
|
19
|
+
const next = waiting.shift();
|
|
20
|
+
if (next) next({ value, done: false });
|
|
21
|
+
else buffered.push(value);
|
|
22
|
+
},
|
|
23
|
+
close() {
|
|
24
|
+
closed = true;
|
|
25
|
+
let next = waiting.shift();
|
|
26
|
+
while (next) {
|
|
27
|
+
next({ value: void 0, done: true });
|
|
28
|
+
next = waiting.shift();
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
iterable: {
|
|
32
|
+
[Symbol.asyncIterator]() {
|
|
33
|
+
return {
|
|
34
|
+
next() {
|
|
35
|
+
const buffer = buffered.shift();
|
|
36
|
+
if (buffer !== void 0) return Promise.resolve({ value: buffer, done: false });
|
|
37
|
+
if (closed) return Promise.resolve({ value: void 0, done: true });
|
|
38
|
+
return new Promise((resolve) => waiting.push(resolve));
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
var runCounter = 0;
|
|
46
|
+
function createSceneTimeline(options) {
|
|
47
|
+
const queue = createQueue();
|
|
48
|
+
const runId = options.runId ?? `composed-${runCounter += 1}`;
|
|
49
|
+
const events = createVideoEventFactory({ runId });
|
|
50
|
+
const orientation = options.orientation ?? "landscape";
|
|
51
|
+
const snapshot = {
|
|
52
|
+
schemaVersion: VIDEO_SCHEMA_VERSION,
|
|
53
|
+
orientation,
|
|
54
|
+
scenes: [],
|
|
55
|
+
style: options.style
|
|
56
|
+
};
|
|
57
|
+
let position = 0;
|
|
58
|
+
let finished = false;
|
|
59
|
+
const held = [];
|
|
60
|
+
let openForScenes = !options.awaitAudio;
|
|
61
|
+
const emit = (event) => {
|
|
62
|
+
if (finished) return;
|
|
63
|
+
queue.push(event);
|
|
64
|
+
};
|
|
65
|
+
emit(events.create("response.start", {
|
|
66
|
+
requestId: options.requestId ?? runId,
|
|
67
|
+
format: { orientation },
|
|
68
|
+
style: options.style
|
|
69
|
+
}));
|
|
70
|
+
if (options.audio) {
|
|
71
|
+
snapshot.audio = options.audio;
|
|
72
|
+
emit(events.create("audio.set", { audio: options.audio }));
|
|
73
|
+
}
|
|
74
|
+
const release = () => {
|
|
75
|
+
const pending = held.splice(0, held.length);
|
|
76
|
+
for (const scene of pending) {
|
|
77
|
+
snapshot.scenes.push(scene);
|
|
78
|
+
emit(events.create("scene.add", { scene, position: position++ }));
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
return {
|
|
82
|
+
stream: queue.iterable,
|
|
83
|
+
add(scene) {
|
|
84
|
+
if (finished) return;
|
|
85
|
+
if (!openForScenes) {
|
|
86
|
+
held.push(scene);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
snapshot.scenes.push(scene);
|
|
90
|
+
emit(events.create("scene.add", { scene, position: position++ }));
|
|
91
|
+
},
|
|
92
|
+
setAudio(audio) {
|
|
93
|
+
if (finished || openForScenes) return;
|
|
94
|
+
if (audio) {
|
|
95
|
+
snapshot.audio = audio;
|
|
96
|
+
emit(events.create("audio.set", { audio }));
|
|
97
|
+
}
|
|
98
|
+
openForScenes = true;
|
|
99
|
+
release();
|
|
100
|
+
},
|
|
101
|
+
complete() {
|
|
102
|
+
if (finished) return;
|
|
103
|
+
if (!openForScenes) {
|
|
104
|
+
openForScenes = true;
|
|
105
|
+
release();
|
|
106
|
+
}
|
|
107
|
+
emit(events.create("response.complete", {
|
|
108
|
+
finishReason: "stop",
|
|
109
|
+
snapshot,
|
|
110
|
+
checksum: checksumVideo(snapshot)
|
|
111
|
+
}));
|
|
112
|
+
finished = true;
|
|
113
|
+
queue.close();
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// src/protocol/scene-duration.ts
|
|
119
|
+
var NARRATION_WORDS_PER_SECOND = 2.6;
|
|
120
|
+
var NARRATION_TAIL_SECONDS = 0.6;
|
|
121
|
+
function getSceneDurationBounds(scene, metadata) {
|
|
122
|
+
return {
|
|
123
|
+
minimum: Math.max(1e-3, metadata?.minDuration ?? 1),
|
|
124
|
+
readable: getReadableSceneDuration(scene, metadata)
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
function getSpokenDuration(narration) {
|
|
128
|
+
const words = narration.trim().split(/\s+/u).filter(Boolean).length;
|
|
129
|
+
if (words === 0) return 0;
|
|
130
|
+
return words / NARRATION_WORDS_PER_SECOND + NARRATION_TAIL_SECONDS;
|
|
131
|
+
}
|
|
132
|
+
function getSceneDuration(scene, metadata) {
|
|
133
|
+
const { readable } = getSceneDurationBounds(scene, metadata);
|
|
134
|
+
return Math.max(readable, scene.narration ? getSpokenDuration(scene.narration) : 0);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export {
|
|
138
|
+
createSceneTimeline,
|
|
139
|
+
getSceneDurationBounds,
|
|
140
|
+
getSpokenDuration,
|
|
141
|
+
getSceneDuration
|
|
142
|
+
};
|
|
@@ -572,6 +572,7 @@ var TemplateText = ({
|
|
|
572
572
|
} : baseTypo;
|
|
573
573
|
const presetWeight = tt ? Math.min(900, Math.max(100, fontWeight + tt.weightDelta)) : fontWeight;
|
|
574
574
|
const presetSize = tt ? fontSize * tt.sizeScale : fontSize;
|
|
575
|
+
const overMediaColor = overMedia && isLikelyDark(color) ? "#FFFFFF" : color;
|
|
575
576
|
const textShadow = overMedia ? MEDIA_TEXT_SHADOW : dropShadowFor(color);
|
|
576
577
|
const containerStyle = {
|
|
577
578
|
position: "absolute",
|
|
@@ -580,7 +581,7 @@ var TemplateText = ({
|
|
|
580
581
|
display: "flex",
|
|
581
582
|
justifyContent: "center",
|
|
582
583
|
padding: `0 ${safeZone.right}px 0 ${safeZone.left}px`,
|
|
583
|
-
color,
|
|
584
|
+
color: overMediaColor,
|
|
584
585
|
fontFamily: font,
|
|
585
586
|
fontWeight: presetWeight,
|
|
586
587
|
fontSize: presetSize,
|