实战教程:解决生成式视频 prompt 不稳定问题,用原生 JS 构建稳定的输入生成管道,可直接应用。
生成式视频模型进步得很快,但一个出乎意料的普通问题仍在浪费大量时间:每当有人重写输入 brief,它的内容就会随之改变。
一个 prompt 包含了镜头和灯光信息,下一个却忘了宽高比。再后来的版本,又把主角产品的材质从陶瓷改成了玻璃。模型或许能力很强,但生产输入并不稳定。
为了实现可重复的工作流程,最好把两项工作分开:
决定创意方向;
将这个决定转化为 prompt 和 storyboard。
第一项工作需要创意,第二项则可以做到确定性。
在本教程中,我们将构建一个小型浏览器应用,把结构化表单转换为:
一个主图像或视频 prompt;
连贯性约束;
一个包含三至六个镜头的 storyboard;
可供后续生产流程使用的可下载 JSON。
它不使用任何框架,不需要构建步骤,也不调用 AI API。
先从生成会话期间应当保持稳定的信息开始:
const brief = {
projectType: "video",
subject: "a matte ceramic skincare bottle on a mirrored plinth",
style: "premium editorial product film, tactile, photorealistic",
camera: "slow macro push-in with a 50 mm lens",
lighting: "soft cobalt edge light with a warm amber key",
requirements: "readable label and consistent bottle geometry",
negative: "warped typography, duplicated objects, flicker",
aspectRatio: "9:16",
shotCount: "4",
duration: "12 seconds"
};
这个对象的作用不只是整理表单值。它让所有下游函数都能共享同一个事实来源。
表单输入中经常会出现意外的换行和重复空格。一个小型规范化函数就能让输出保持整洁易读:
const clean = (value) =>
String(value || "")
.trim()
.replace(/\s+/g, " ");
接下来,把可选字段转换为带标签的句子:
const sentence = (label, value) => {
const normalized = clean(value);
return normalized ? `${label}: ${normalized}.` : "";
};
现在,prompt 构建器既可以清晰明确,又不会显得重复:
function buildPrompt(input) {
const subject = clean(input.subject);
if (!subject) {
throw new Error("A core idea is required.");
}
const parts = [
`Create a cinematic AI video featuring ${subject}.`,
sentence("Visual direction", input.style),
sentence("Camera and composition", input.camera),
sentence("Lighting and color", input.lighting),
sentence("Required details", input.requirements),
sentence("Avoid", input.negative),
sentence("Delivery format", `${clean(input.aspectRatio)} aspect ratio`)
];
return parts.filter(Boolean).join(" ");
}
结果是确定性的:相同的输入会产生相同的输出。无论是比较不同模型,还是重新生成某个镜头,这一点都很有用,因为 brief 不再是另一个不断变化的变量。
如果把全局约束与各个镜头分开存储,storyboard 会更实用。
function buildStoryboard(input) {
const requestedCount = Number.parseInt(input.shotCount, 10);
const shotCount = Math.min(
6,
Math.max(3, Number.isFinite(requestedCount) ? requestedCount : 4)
);
const beats = [
"Establish the subject and environment",
"Move closer to reveal the defining details",
"Introduce a clear transformation or action",
"Show the strongest hero composition",
"Add a contrasting angle or supporting detail",
"Resolve on a clean final frame"
];
return {
aspectRatio: clean(input.aspectRatio) || "16:9",
totalDuration: clean(input.duration) || "12 seconds",
continuity: {
subject: clean(input.subject),
visualStyle: clean(input.style),
lighting: clean(input.lighting),
requirements: clean(input.requirements),
negativeConstraints: clean(input.negative)
},
shots: beats.slice(0, shotCount).map((purpose, index) => ({
shot: index + 1,
purpose,
visual: `${clean(input.subject)}; maintain the ${clean(input.style)} direction`,
camera: clean(input.camera),
transition:
index === shotCount - 1
? "hold on final frame"
: "clean motivated cut"
}))
};
}
这里有两项刻意设置的限制:
至少三个镜头,从而让输出具备开端、发展和收束;
最多六个镜头,避免一个简单概念演变成难以管理的制作项目。
这些数字并不是放之四海而皆准的标准。真正重要的是,让规则清晰可见,并且可以测试。
无需服务器,浏览器就能生成可下载的文件:
function downloadStoryboard(storyboard) {
const blob = new Blob([JSON.stringify(storyboard, null, 2)], {
type: "application/json"
});
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = "creative-storyboard.json";
link.click();
URL.revokeObjectURL(url);
}
这个 JSON 可以随项目一起存储,在 pull request 中接受审查,也可以在之后转换为其他工具所需的格式。
没必要针对 prompt 的每个字都编写 snapshot test,只需测试真正重要的规则:
import assert from "node:assert/strict";
import test from "node:test";
test("shot count is clamped to six", () => {
const storyboard = buildStoryboard({
subject: "a glass bottle",
shotCount: "12"
});
assert.equal(storyboard.shots.length, 6);
});
test("a subject is required", () => {
assert.throws(
() => buildPrompt({ projectType: "image" }),
/core idea is required/i
);
});
对于这种规模的项目,Node 内置的 test runner 已经足够。
这个 starter 并不是要取代图像或视频模型,而是为模型准备一套稳定的指令。
一个实用的工作流程如下:
在本地应用中就 brief 达成一致;
将 JSON 与项目一起保存;
使用 master prompt 完成第一次生成;
在保留 continuity 对象的同时,逐个生成镜头;
比较结果时,每次只修改一个变量。
如果需要集成式生成工作区,可以把完成后的 brief 用于 Vynyo AI Video Generator。
完整的零依赖 starter、测试和 Replit 配置,均可在公开的 Vynyo Creative Brief Starter 仓库中获取。
更重要的启示很简单:更好的生成结果,并不总是始于一个更加复杂的 prompt。很多时候,它始于一小组能够始终保持一致的决策。
如需采取进一步措施,你可以考虑屏蔽此人和/或举报滥用行为。