@koda-sl/baker-cli 0.265.0-dev.1f1c09c80 → 0.265.1-dev.1f1c09c80
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 +41 -29
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -32656,7 +32656,7 @@ function buildAdBrandOverlay(opts) {
|
|
|
32656
32656
|
];
|
|
32657
32657
|
if (logo) {
|
|
32658
32658
|
parts.push(
|
|
32659
|
-
`<img class="
|
|
32659
|
+
`<img class="clip brand-mark" src="${escapeHtml2(logo.file)}" alt="${escapeHtml2(logo.alt)}" data-start="0" data-dur="${totalS}" />`
|
|
32660
32660
|
);
|
|
32661
32661
|
}
|
|
32662
32662
|
const cardBits = [];
|
|
@@ -32668,7 +32668,7 @@ function buildAdBrandOverlay(opts) {
|
|
|
32668
32668
|
cardBits.push(`<div class="endcard-cta"${style}>${escapeHtml2(cta.trim())}</div>`);
|
|
32669
32669
|
}
|
|
32670
32670
|
parts.push(
|
|
32671
|
-
`<div class="
|
|
32671
|
+
`<div class="clip endcard" data-start="${cardAtS}" data-dur="${cardDurationS}" data-role="cta">`,
|
|
32672
32672
|
...cardBits.map((b) => ` ${b}`),
|
|
32673
32673
|
"</div>"
|
|
32674
32674
|
);
|
|
@@ -32677,15 +32677,22 @@ function buildAdBrandOverlay(opts) {
|
|
|
32677
32677
|
function adBrandOverlayCss() {
|
|
32678
32678
|
return [
|
|
32679
32679
|
" /* --- brand layer (baker canvas scaffold-ad) --- */",
|
|
32680
|
-
" .
|
|
32681
|
-
"
|
|
32682
|
-
"
|
|
32680
|
+
" /* Positioned by this block alone. The composition that actually renders an ad",
|
|
32681
|
+
" is the caption track, which has no .pos-* helpers \u2014 relying on them put the",
|
|
32682
|
+
" brand layer in a file nothing opens and shipped an empty green end plate. */",
|
|
32683
|
+
" .brand-mark { position: absolute; top: 90px; left: 56px; width: 220px; height: auto;",
|
|
32684
|
+
" opacity: 0.92; filter: drop-shadow(0 2px 8px rgba(0,0,0,0.45)); }",
|
|
32685
|
+
" .endcard { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);",
|
|
32686
|
+
" display: flex; flex-direction: column; align-items: center; gap: 56px;",
|
|
32683
32687
|
" width: 100%; max-width: 1080px; padding: 0 60px; text-align: center; }",
|
|
32684
32688
|
" .endcard-logo { width: 620px; max-width: 78%; height: auto; }",
|
|
32685
32689
|
" /* Capped and wrapping, not sized to its content: measured in a real browser,",
|
|
32686
32690
|
" `GET YOUR FREE QUOTE` renders 948px wide against a 1080px canvas, so the next",
|
|
32687
32691
|
" slightly longer call to action runs off the frame. Two lines beat an edge. */",
|
|
32688
|
-
"
|
|
32692
|
+
" /* Declares its own family: rendered without one it inherited the document",
|
|
32693
|
+
" default and the call to action came out in Times, beside sans-serif captions. */",
|
|
32694
|
+
" .endcard-cta { font-family: 'BrandFont', 'Arial Black', 'Helvetica Neue', Arial, sans-serif;",
|
|
32695
|
+
" font-size: 64px; font-weight: 900; text-transform: uppercase;",
|
|
32689
32696
|
" letter-spacing: 0.01em; color: #fff; padding: 28px 58px; border-radius: 56px;",
|
|
32690
32697
|
" max-width: 900px; line-height: 1.15; background: rgba(0,0,0,0.82); }"
|
|
32691
32698
|
].join("\n");
|
|
@@ -32694,7 +32701,11 @@ function injectAdBrandOverlay(indexHtml, overlayHtml) {
|
|
|
32694
32701
|
if (!overlayHtml.trim()) return indexHtml;
|
|
32695
32702
|
const withCss = indexHtml.replace(" </style>", `${adBrandOverlayCss()}
|
|
32696
32703
|
</style>`);
|
|
32697
|
-
return withCss.replace("<!--OVERLAYS-->", () => overlayHtml);
|
|
32704
|
+
if (withCss.includes("<!--OVERLAYS-->")) return withCss.replace("<!--OVERLAYS-->", () => overlayHtml);
|
|
32705
|
+
const rootClose = withCss.lastIndexOf("</div>");
|
|
32706
|
+
if (rootClose === -1) return withCss;
|
|
32707
|
+
return `${withCss.slice(0, rootClose)}${overlayHtml}
|
|
32708
|
+
${withCss.slice(rootClose)}`;
|
|
32698
32709
|
}
|
|
32699
32710
|
|
|
32700
32711
|
// src/commands/canvas/composition-path.ts
|
|
@@ -32796,18 +32807,35 @@ var scaffoldAdCommand = defineCommand104({
|
|
|
32796
32807
|
await writeSceneFiles(outDir, blueprint);
|
|
32797
32808
|
await writeFile9(blueprintStylePath, renderStyleProjectionFromValue(blueprint), "utf8");
|
|
32798
32809
|
const logoPath = spec.data.brand?.logo?.trim();
|
|
32810
|
+
const opts = {
|
|
32811
|
+
imageModel: AD_IMAGE_MODEL,
|
|
32812
|
+
videoModel: DEFAULT_VIDEO_GENERATE_MODEL,
|
|
32813
|
+
overlayCompositionPath: path23.relative(outDir, compositionDest),
|
|
32814
|
+
captionsCompositionPath: path23.relative(outDir, captionsDest),
|
|
32815
|
+
blueprintPath: path23.relative(outDir, blueprintPath),
|
|
32816
|
+
blueprintStylePath: path23.relative(outDir, blueprintStylePath),
|
|
32817
|
+
aspect: spec.data.format.aspect_ratio,
|
|
32818
|
+
resolution: spec.data.format.resolution,
|
|
32819
|
+
// A beat is one clause and one card, so the cap has to clear a whole clause.
|
|
32820
|
+
// The composition's default of 3 is TikTok karaoke styling; applied to an ad
|
|
32821
|
+
// it overrode the clause rule on every line and rendered "IS STANDARD. WE".
|
|
32822
|
+
// 8 is the composition's own maximum and clears every beat measured here.
|
|
32823
|
+
captionWordsPerGroup: 8
|
|
32824
|
+
};
|
|
32825
|
+
const canvas = scaffoldVideoCanvas(blueprint, adSpecCastElements(spec.data), opts);
|
|
32826
|
+
const renderNode3 = canvas.nodes.find((n) => n.type === "hyperframe_render");
|
|
32827
|
+
const renderedDir = renderNode3 ? path23.join(outDir, String(renderNode3.params?.composition ?? "")) : null;
|
|
32799
32828
|
let staged = null;
|
|
32800
|
-
if (logoPath) {
|
|
32829
|
+
if (logoPath && renderedDir) {
|
|
32801
32830
|
const ext = path23.extname(logoPath) || ".png";
|
|
32802
|
-
const dest = path23.join(compositionDest, `brand-mark${ext}`);
|
|
32803
32831
|
try {
|
|
32804
|
-
await copyFile(logoPath,
|
|
32832
|
+
await copyFile(logoPath, path23.join(renderedDir, `brand-mark${ext}`));
|
|
32805
32833
|
staged = { file: `brand-mark${ext}`, alt: spec.data.brand?.name ?? "brand" };
|
|
32806
32834
|
} catch {
|
|
32807
32835
|
}
|
|
32808
32836
|
}
|
|
32809
32837
|
const closing = blueprint.scenes[blueprint.scenes.length - 1];
|
|
32810
|
-
const overlayHtml = endCardWanted(spec.data) && closing ? buildAdBrandOverlay({
|
|
32838
|
+
const overlayHtml = endCardWanted(spec.data) && closing && renderedDir ? buildAdBrandOverlay({
|
|
32811
32839
|
logo: staged,
|
|
32812
32840
|
cta: endCardCta(spec.data),
|
|
32813
32841
|
cardAtS: closing.start_s,
|
|
@@ -32815,27 +32843,11 @@ var scaffoldAdCommand = defineCommand104({
|
|
|
32815
32843
|
totalS: blueprint.estimated_duration_s,
|
|
32816
32844
|
accent: firstHex(spec.data.brand?.palette)
|
|
32817
32845
|
}) : "";
|
|
32818
|
-
if (overlayHtml) {
|
|
32819
|
-
const indexPath = path23.join(
|
|
32846
|
+
if (overlayHtml && renderedDir) {
|
|
32847
|
+
const indexPath = path23.join(renderedDir, "index.html");
|
|
32820
32848
|
const html = await readFile15(indexPath, "utf-8");
|
|
32821
32849
|
await writeFile9(indexPath, injectAdBrandOverlay(html, overlayHtml), "utf-8");
|
|
32822
32850
|
}
|
|
32823
|
-
const opts = {
|
|
32824
|
-
imageModel: AD_IMAGE_MODEL,
|
|
32825
|
-
videoModel: DEFAULT_VIDEO_GENERATE_MODEL,
|
|
32826
|
-
overlayCompositionPath: path23.relative(outDir, compositionDest),
|
|
32827
|
-
captionsCompositionPath: path23.relative(outDir, captionsDest),
|
|
32828
|
-
blueprintPath: path23.relative(outDir, blueprintPath),
|
|
32829
|
-
blueprintStylePath: path23.relative(outDir, blueprintStylePath),
|
|
32830
|
-
aspect: spec.data.format.aspect_ratio,
|
|
32831
|
-
resolution: spec.data.format.resolution,
|
|
32832
|
-
// A beat is one clause and one card, so the cap has to clear a whole clause.
|
|
32833
|
-
// The composition's default of 3 is TikTok karaoke styling; applied to an ad
|
|
32834
|
-
// it overrode the clause rule on every line and rendered "IS STANDARD. WE".
|
|
32835
|
-
// 8 is the composition's own maximum and clears every beat measured here.
|
|
32836
|
-
captionWordsPerGroup: 8
|
|
32837
|
-
};
|
|
32838
|
-
const canvas = scaffoldVideoCanvas(blueprint, adSpecCastElements(spec.data), opts);
|
|
32839
32851
|
await writeFile9(outPath, `${JSON.stringify(canvas, null, 2)}
|
|
32840
32852
|
`, "utf-8");
|
|
32841
32853
|
writeJson({
|