@koda-sl/baker-cli 0.295.0-dev.f941e60fb → 0.297.0-dev.306c0952c
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/dist/cli.js
CHANGED
|
@@ -54,6 +54,7 @@ import {
|
|
|
54
54
|
sha256Hex,
|
|
55
55
|
spineInputFlags,
|
|
56
56
|
spineInputOps,
|
|
57
|
+
splitScriptFor,
|
|
57
58
|
spokenWordsIn,
|
|
58
59
|
supportsLastFrame,
|
|
59
60
|
supportsParam,
|
|
@@ -62,7 +63,7 @@ import {
|
|
|
62
63
|
ulid,
|
|
63
64
|
validateCanvasDeep,
|
|
64
65
|
ytDlpBlockSignal
|
|
65
|
-
} from "./chunk-
|
|
66
|
+
} from "./chunk-YMHERSTK.js";
|
|
66
67
|
import {
|
|
67
68
|
csvOrJson,
|
|
68
69
|
daysAgoIso,
|
|
@@ -38222,6 +38223,15 @@ var scaffoldStaticAdCommand = defineCommand110({
|
|
|
38222
38223
|
}
|
|
38223
38224
|
});
|
|
38224
38225
|
|
|
38226
|
+
// src/commands/studio/avatarModel.ts
|
|
38227
|
+
function pinnedModelHint(input) {
|
|
38228
|
+
if (!input.avatar || !input.model) return null;
|
|
38229
|
+
if (input.model === DEFAULT_VIDEO_GENERATE_MODEL) return null;
|
|
38230
|
+
const speaks = input.generateAudio ?? true;
|
|
38231
|
+
if (!speaks) return null;
|
|
38232
|
+
return `You pinned --model ${input.model} on a speaking avatar. Without it this clip routes to ${DEFAULT_VIDEO_GENERATE_MODEL}, which was chosen for exactly this case: the better picture, both orientations, and audio always on. Drop --model unless the user asked for a specific one \u2014 and note ${input.model} may not take the length or the reference you are counting on.`;
|
|
38233
|
+
}
|
|
38234
|
+
|
|
38225
38235
|
// src/commands/canvas/scaffold-ad.ts
|
|
38226
38236
|
import { copyFile, cp, mkdir as mkdir7, readFile as readFile16, stat as stat4, writeFile as writeFile9 } from "fs/promises";
|
|
38227
38237
|
import path24 from "path";
|
|
@@ -38953,6 +38963,10 @@ function resolveShippedCanvasDir(name, startDir, exists2 = existsSync5, maxDepth
|
|
|
38953
38963
|
}
|
|
38954
38964
|
|
|
38955
38965
|
// src/commands/canvas/scaffold-ad.ts
|
|
38966
|
+
function pinnedOnAvatar(handle, model) {
|
|
38967
|
+
const hint = pinnedModelHint({ avatar: handle ?? void 0, model, generateAudio: true });
|
|
38968
|
+
return hint ? [hint] : [];
|
|
38969
|
+
}
|
|
38956
38970
|
var AD_IMAGE_MODEL = "openai/gpt-image-2.5-sunburst";
|
|
38957
38971
|
var SHIPPED_COMPOSITION_DIR = resolveShippedCanvasDir("video-overlay-composition", import.meta.dirname);
|
|
38958
38972
|
var SHIPPED_CAPTIONS_DIR = resolveShippedCanvasDir("tiktok-captions-composition", import.meta.dirname);
|
|
@@ -39275,6 +39289,10 @@ var scaffoldAdCommand = defineCommand111({
|
|
|
39275
39289
|
ok: true,
|
|
39276
39290
|
data: { canvas: outPath, beats: spec.data.beats.length, slug },
|
|
39277
39291
|
hints: [
|
|
39292
|
+
// Same reasoning as `studio animate`: a cast avatar that speaks routes to the
|
|
39293
|
+
// default model on purpose, and pinning one discards that silently. An ad's
|
|
39294
|
+
// beats always speak, so there is no silent case to exclude here.
|
|
39295
|
+
...pinnedOnAvatar(handle, requestedModel),
|
|
39278
39296
|
// `--until frames` on anything carrying a face or a mark, because that is where
|
|
39279
39297
|
// getting it wrong is expensive: the pictures cost a fraction of the clips, and
|
|
39280
39298
|
// every defect anyone has caught in a finished ad was visible in them. The run
|
|
@@ -57381,15 +57399,6 @@ import { defineCommand as defineCommand208 } from "citty";
|
|
|
57381
57399
|
// src/commands/studio/animate.ts
|
|
57382
57400
|
import { defineCommand as defineCommand200 } from "citty";
|
|
57383
57401
|
|
|
57384
|
-
// src/commands/studio/avatarModel.ts
|
|
57385
|
-
function pinnedModelHint(input) {
|
|
57386
|
-
if (!input.avatar || !input.model) return null;
|
|
57387
|
-
if (input.model === DEFAULT_VIDEO_GENERATE_MODEL) return null;
|
|
57388
|
-
const speaks = input.generateAudio ?? true;
|
|
57389
|
-
if (!speaks) return null;
|
|
57390
|
-
return `You pinned --model ${input.model} on a speaking avatar. Without it this clip routes to ${DEFAULT_VIDEO_GENERATE_MODEL}, which was chosen for exactly this case: the better picture, both orientations, and audio always on. Drop --model unless the user asked for a specific one \u2014 and note ${input.model} may not take the length or the reference you are counting on.`;
|
|
57391
|
-
}
|
|
57392
|
-
|
|
57393
57402
|
// src/commands/studio/batch.ts
|
|
57394
57403
|
function projectBatch(generation, full) {
|
|
57395
57404
|
const compact3 = {
|
|
@@ -57610,13 +57619,18 @@ var spokenWords = spokenWordsIn;
|
|
|
57610
57619
|
function wordsThatFit(seconds) {
|
|
57611
57620
|
return Math.floor(seconds * WORDS_PER_SECOND2);
|
|
57612
57621
|
}
|
|
57613
|
-
function spokenPaceHint(prompt, seconds) {
|
|
57614
|
-
if (!seconds) return null;
|
|
57622
|
+
function spokenPaceHint(prompt, seconds, model) {
|
|
57615
57623
|
const words2 = spokenWords(prompt);
|
|
57624
|
+
if (words2 === 0) return null;
|
|
57625
|
+
const split = model ? splitScriptFor(words2, model) : null;
|
|
57626
|
+
if (split) {
|
|
57627
|
+
return `The line is ${words2} words \u2014 about ${Math.ceil(words2 / WORDS_PER_SECOND2)}s of speech \u2014 and ${model} renders at most ${split.maxSeconds}s (~${Math.floor(split.maxSeconds * WORDS_PER_SECOND2)} words). It will not refuse and it will not cut: it will RUSH, swallowing syllables. Split the script into ${split.clips} takes of roughly ${split.wordsPerClip} words each, rendered separately and cut together \u2014 break it where the thought breaks, not mid-sentence. Or move to a model that renders longer (bytedance/seedance-2.5 goes to 30s).`;
|
|
57628
|
+
}
|
|
57629
|
+
if (!seconds) return null;
|
|
57616
57630
|
const fits = wordsThatFit(seconds);
|
|
57617
|
-
if (words2
|
|
57631
|
+
if (words2 <= fits) return null;
|
|
57618
57632
|
const rate = (words2 / seconds).toFixed(1);
|
|
57619
|
-
return `The line is ${words2} words and this clip is ${seconds}s \u2014 that is ${rate} words a second against a natural
|
|
57633
|
+
return `The line is ${words2} words and this clip is ${seconds}s \u2014 that is ${rate} words a second against a natural ${WORDS_PER_SECOND2}. The model will not run over, it will RUSH: syllables swallowed, endings clipped, and the take unusable however good the picture. Cut the line to about ${fits} words, or give it the length it needs (${Math.ceil(words2 / WORDS_PER_SECOND2)}s). Do not re-render the same line at the same length and hope.`;
|
|
57620
57634
|
}
|
|
57621
57635
|
|
|
57622
57636
|
// src/commands/studio/animate.ts
|
|
@@ -57849,7 +57863,7 @@ function costHintsFor(body) {
|
|
|
57849
57863
|
];
|
|
57850
57864
|
const pinned = pinnedModelHint({ avatar: body.avatar, model: body.model, generateAudio: body.generateAudio });
|
|
57851
57865
|
if (pinned) hints2.push(pinned);
|
|
57852
|
-
const pace = spokenPaceHint(body.prompt, body.duration);
|
|
57866
|
+
const pace = spokenPaceHint(body.prompt, body.duration, model);
|
|
57853
57867
|
if (pace) hints2.push(pace);
|
|
57854
57868
|
if (count > 1) {
|
|
57855
57869
|
hints2.push(
|