adyou 0.6.6 → 0.6.8
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.
|
@@ -152,7 +152,39 @@ export function tree(size, concept, brief, bg, logo, ctaText) {
|
|
|
152
152
|
ctaFs = Math.round(hh * 0.058);
|
|
153
153
|
}
|
|
154
154
|
const chipFs = Math.round(hh * 0.044);
|
|
155
|
-
|
|
155
|
+
let proofs = widePoster ? [...(brief.proofPoints || []), ...(brief.usp || [])].map((x) => { const t = String(x || '').replace(/\s+/g, ' ').trim(); return cutWords(t, /[\u3000-\u9fff\uac00-\ud7af]/.test(t) ? 18 : 34); }).filter((x) => x && wlen(x) <= 36).filter((x, i, a) => a.indexOf(x) === i).slice(0, 3) : [];
|
|
156
|
+
const cjk = /[\u3000-\u9fff\uac00-\ud7af]/.test(body);
|
|
157
|
+
let bodyText = banner ? cutWords(body, 70) : widePoster ? cutWords(body, cjk ? 60 : 110) : googleLight ? cutWords(body, 48) : body;
|
|
158
|
+
if (widePoster) {
|
|
159
|
+
// 세로 예산 — 헤드라인이 두 줄이면 CTA 가 바닥 밖으로 밀린다(힐스테이트 1200×628 실사고 · 2026-09-17) → 줄 수를 어림해 넘치면 헤드라인 축소 → 알약 줄이기 → 본문 한 줄 순으로 맞춘다
|
|
160
|
+
const colW = Math.round(w * 0.72);
|
|
161
|
+
const gap = Math.round(pad * 0.5);
|
|
162
|
+
// 글자 폭 어림(Pretendard 실측 · 에어서울 97px 헤드라인 780px): 한글·전각 0.86em · 숫자·라틴 0.55em · 공백 0.3em
|
|
163
|
+
const textW = (t, fs) => [...t].reduce((n, ch) => n + (ch === ' ' ? 0.3 : (ch.codePointAt(0) || 0) > 0x2e7f ? 0.86 : 0.55), 0) * fs;
|
|
164
|
+
const lines = (t, fs) => Math.max(1, Math.ceil(textW(t, fs) / colW));
|
|
165
|
+
const chipRows = () => { let rows = 0, x = 0; for (const t of proofs) {
|
|
166
|
+
const cw = textW(t, chipFs) + chipFs * 2.4;
|
|
167
|
+
if (!rows || x + cw > colW) {
|
|
168
|
+
rows++;
|
|
169
|
+
x = cw;
|
|
170
|
+
}
|
|
171
|
+
else
|
|
172
|
+
x += cw + chipFs * 0.45;
|
|
173
|
+
} return rows; };
|
|
174
|
+
// 실측 보정(에어서울 1200×628 · 헤드라인 97 + 본문 2줄 + 알약 2줄 + CTA ≈ 563px 로 들어감) — 로고 행 ≈ headFs×0.5 · 사이 간격 4곳
|
|
175
|
+
const total = () => headFs * (logo ? 0.95 : 0.5) + lines(head, headFs) * headFs * 1.12 + lines(bodyText, bodyFs) * bodyFs * 1.45 + (proofs.length ? chipRows() * chipFs * 1.9 : 0) + ctaFs * 2 + headFs * 0.28 * 1.4 + gap * 4;
|
|
176
|
+
const avail = hh - pad * 0.9;
|
|
177
|
+
if (total() > avail && chipRows() > 1)
|
|
178
|
+
proofs = proofs.slice(0, 2);
|
|
179
|
+
if (total() > avail && chipRows() > 1)
|
|
180
|
+
proofs = proofs.slice(0, 1);
|
|
181
|
+
if (total() > avail && lines(head, headFs) > 1)
|
|
182
|
+
headFs = Math.round(hh * 0.11);
|
|
183
|
+
if (total() > avail && lines(bodyText, bodyFs) > 1)
|
|
184
|
+
bodyText = cutWords(body, cjk ? 30 : 55);
|
|
185
|
+
if (total() > avail)
|
|
186
|
+
proofs = [];
|
|
187
|
+
}
|
|
156
188
|
const chips = proofs.length ? h('div', { display: 'flex', flexWrap: 'wrap', gap: Math.round(chipFs * 0.45) }, proofs.map((t) => h('div', { display: 'flex', alignItems: 'center', gap: Math.round(chipFs * 0.4), fontSize: chipFs, fontWeight: 700, color: fg, backgroundColor: dark ? 'rgba(255,255,255,.16)' : 'rgba(255,255,255,.78)', borderRadius: 999, padding: `${Math.round(chipFs * 0.28)}px ${Math.round(chipFs * 0.7)}px`, whiteSpace: 'nowrap' }, [h('div', { width: Math.round(chipFs * 0.42), height: Math.round(chipFs * 0.42), borderRadius: 999, backgroundColor: primary }), h('div', { whiteSpace: 'nowrap' }, t)]))) : null;
|
|
157
189
|
const children = [];
|
|
158
190
|
if (bg)
|
|
@@ -175,7 +207,7 @@ export function tree(size, concept, brief, bg, logo, ctaText) {
|
|
|
175
207
|
h('div', { display: 'flex', justifyContent: 'space-between', alignItems: 'center' }, [brandRow, domain && !banner ? h('div', { fontSize: Math.round(headFs * 0.3), fontWeight: 500, color: sub }, domain) : h('div', {}, '')]),
|
|
176
208
|
h('div', { display: 'flex', flexDirection: 'column', gap: Math.round(pad * (banner ? 0.35 : 0.5)), maxWidth: isWide ? Math.round(w * 0.72) : w - pad * 2 }, [
|
|
177
209
|
wordsEl(head, { fontSize: headFs, fontWeight: 800, color: fg, lineHeight: 1.12, letterSpacing: -1.5 }),
|
|
178
|
-
(banner && bodyFs < 14) || bodyFs === 0 ? h('div', {}, '') : wordsEl(
|
|
210
|
+
(banner && bodyFs < 14) || bodyFs === 0 ? h('div', {}, '') : wordsEl(bodyText, { fontSize: bodyFs, fontWeight: 500, color: sub, lineHeight: 1.45 }),
|
|
179
211
|
...(chips ? [chips] : []),
|
|
180
212
|
h('div', { display: 'flex', marginTop: Math.round(pad * 0.3) }, [ctaPill]),
|
|
181
213
|
]),
|
|
@@ -85,7 +85,10 @@ export async function generateStoryboards(brief, concept, o) {
|
|
|
85
85
|
continue;
|
|
86
86
|
}
|
|
87
87
|
const clips = p.clips.map((pc, i) => { const src = b.clips[i] || b.clips[b.clips.length - 1]; return { sec: pc.sec, kind: pc.kind, prompt: (src?.prompt || '').trim(), speech: src?.speech || undefined, continues: i > 0 ? !!src?.continues : false }; });
|
|
88
|
-
|
|
88
|
+
const caps = b.captions.map((c) => c.trim()).filter(Boolean).slice(0, 3);
|
|
89
|
+
// 🔴 장면 포맷의 voice 를 모델이 비우면 내레이션 없는 「음악만」 영상이 된다(힐스테이트 글자 훅 · 2026-09-17) → 자막 두 줄로 내레이션을 만든다
|
|
90
|
+
const voice = b.voice?.trim() || (p.format !== 'ugc_selfie' ? [caps[0], caps[1]].filter(Boolean).join(', ').replace(/[.!?。!?]?$/, '.') : undefined);
|
|
91
|
+
boards.push({ id: `${concept.key}_${p.format}`, format: p.format, genre: p.format === 'ugc_selfie' ? 'ugc' : (b.genre && genres.includes(b.genre) ? b.genre : genres[0]) || 'photoreal', hook: fitHook(b.hook), captions: caps, voice, music: b.music || tone.music, cta, durationSec: o.durationSec, clips, lang, cast: b.cast || undefined });
|
|
89
92
|
}
|
|
90
93
|
return boards;
|
|
91
94
|
}
|
package/package.json
CHANGED