我用 AI 做了一个"会自己导戏"的短剧生成器
更新日期: 2026-04-23
技术栈: Next.js 14 / Fastify / PostgreSQL / OpenRouter
预计阅读时间: 12 分钟
难度: 中级(熟悉 Node.js 即可)
老板某天甩了一句:"我们能不能做个东西,输入一段文字就能生成漫剧视频?"
"短剧"这两个字现在很热,但真正从零做一套的人知道里面有多少坑——找演员、搭场景、录音、剪辑……每个环节都要人。我们想做的是把这条链路全部 AI 化。
六周后,DirectorAI 上线了。输入一个创意,三分钟后拿到一段带配音、字幕、BGM、片头片尾的完整视频。
这篇文章是复盘。不是"我做了个很厉害的东西"的宣传稿,而是讲清楚:为什么要用这套架构、哪些地方踩了坑、最后跑通的关键到底是什么。
为什么不直接调 API 了事
最直接的做法是写个脚本:调 Claude API 生成剧本,调图像 API 出图,拼一拼发出去。我们最初也是这么干的。
结果如下:
生成质量完全看运气。同一个 prompt,可能出来"凌晨三点的办公室,主角盯着报错信息,头发又少了三根",也可能出来一段废话连篇的流水账。Claude 很聪明,但它不知道"这是一个短剧脚本"意味着什么——三秒钩子、情绪节拍、镜头语言,这些它懂,但不会主动用。
第二个问题是角色一致性。A 场景的"李明"是短发男生,B 场景变成了卷发。图像 API 没有跨请求的记忆,每次生成都是独立的。
第三个问题是音画同步。生成五段视频,每段时长不一样,配音也是独立生成的,拼在一起要么错位要么有空白。
每个问题单独解决都不难,合在一起就是个系统工程。DirectorAI 是我们对这个工程的回答。
核心设计:让两个 AI 互相"对骂"
普通方案是让 AI 生成一次,人来 review。我们的方案是让两个 AI 互相 review,人只看最终结果。
具体来说,Sonnet 4.6 是创作者,Opus 4.7 是导演。
第一轮:Sonnet 写初稿,Opus 以"有 20 年经验的严苛导演"身份拆它,输出结构化批评(冲突强度 / 角色动机 / 节奏问题 / 视觉可实现性)。
第二轮:Sonnet 拿着批评重写,Opus 再审。通过则输出最终版,不通过则打回。
这套机制的核心不是"两个模型比一个好",而是强迫创作过程有明确的评审标准。Opus 的 system prompt 里有具体的评审维度,这些维度本身就是在告诉 Sonnet"什么叫好的短剧脚本"。
代码结构很简单:
// adversarial-reviewer.ts const CRITIC_MODEL = 'anthropic/claude-opus-4-7'; // Opus — 导演 const CREATOR_MODEL = 'anthropic/claude-sonnet-4-6'; // Sonnet — 创作者 async function runAdversarialReview(content: string, dramaType: DramaType) { // Round 1: Sonnet 生成 → Opus 评审 const draft = await generateWithSonnet(content, dramaType); const critique = await critiqueWithOpus(draft, dramaType); // Round 2: Sonnet 修改 → Opus 终审 const revised = await reviseWithSonnet(draft, critique, dramaType); const finalReview = await critiqueWithOpus(revised, dramaType); return finalReview.approved ? revised : draft; }
你不用记这个实现细节。重要的是理解:对抗评审解决的是"生成质量的下限"问题,让差的结果变少。
五种风格,五套逻辑
生成短剧有个很容易忽略的点:不同类型的短剧,需要完全不同的提示词策略。
我们支持五种类型:
真人漫剧:强调角色面部表情的戏剧张力,提示词里必须有"漫感"关键词(ink outline / cel shading),配音要自然口语化
3D 漫剧:必须先描述环境光线(方向、色温、强度),善用长镜头建立空间感,材质细节很重要(subsurface scattering)
2D 漫剧:构图要考虑前景/中景/背景分层(为视差动效),日系高饱和度色彩
沙雕漫剧:表情描述必须夸张("瞳孔地震"、"下颌掉落"),台词每句控制在 15 字以内,快速节奏
解说漫剧:数据图表优先,信息流设计,旁白比重远大于对话
每种类型有自己的 prompt 模板、评审维度、视频滤镜参数,这些不是手工调的,是从大量生成结果里归纳出来的。
十步流水线
从用户输入到最终视频,后台跑十步:
几个值得重点说的节点:
第 2 步——角色三视图:用 GPT-5.4 Image 2 生成角色的正面 / 侧面 / 背面三张图,后续所有场景图片都引用这三张作为参考。这是解决角色一致性问题的核心手段。不是完美的,但比每次独立生成好得多。
第 4 步——视频生成的分叉:2D 漫剧用 Ken Burns 效果(对静图做缩放平移,制造运动感),其他类型走 Seedance 2.0 生成真实视频。这个分叉很重要,因为 Ken Burns 速度快且成本低,适合不需要角色运动的场景。
第 6 步——情绪驱动调色:根据场景的 emotionalBeat 字段决定滤镜。喜悦场景加暖黄色,悲伤场景冷蓝调,愤怒用高对比红,紧张压低饱和度。这是对 FFmpeg 的直接调用,没有 AI,但效果明显。
第 8 步——字幕烧录:不是在播放器层面加字幕,而是用 libass 直接烧入视频。这样 CDN 分发后字幕不会丢,在任何播放器里都能看到。
三层音轨
音频是最容易被忽略但最影响体验的部分。
我们做了三轨混音:
BGM(12%音量):情绪底色,全剧常驻。不同类型用不同风格:真人漫剧用管弦乐,沙雕用卡通铜管,解说用紧张节奏
SFX 音效(60%):ElevenLabs 按场景生成,用 FFmpeg adelay 精确对位到场景时间轴
人声配音(100%):MiniMax 语音合成,支持声音克隆(你可以上传自己的声音样本)
有个细节:Seedance 生成的视频有时自带音轨,有时没有。我们用 ffprobe 先探测,有音轨才加入混音链,否则跳过。漏掉这步会让 FFmpeg 报错中断整个流程。
如何搭建 环境要求 Node.js 20+ PostgreSQL 15+ pnpm 8+ ffmpeg(本地音视频处理) 快速启动 git clone github.com/your-org/di… cd directorai pnpm install
配置环境变量
cp apps/api/.env.example apps/api/.env
编辑 .env,填入 OpenRouter API Key 和数据库连接
cd apps/api pnpm db:migrate # 初始化数据库 schema pnpm db:generate # 生成 Prisma Client pnpm dev # 启动后端(默认 :4000)
新终端
cd apps/web pnpm dev # 启动前端(默认 :3000)
访问 http://localhost:4000/health 验证后端正常:
{ "status": "healthy", "uptime": 12.3, "version": "2.0.0" } 最小配置(只需两个密钥) 密钥 用途 获取地址 OPENROUTER_API_KEY Claude / GPT-5 / 其他模型 openrouter.ai DATABASE_URL PostgreSQL 连接 本地或云数据库
其他密钥(Seedance、MiniMax、ElevenLabs)是可选的,没有时会降级到本地处理或跳过对应步骤。
三层安全防护
如果你要把这套系统对外开放,安全不能将就。
第一层——JWT 认证:所有 API 路由都经过 authenticate 中间件。NEXTAUTH_SECRET 至少 32 位,未登录请求直接 401。
第二层——速率限制:用 Fastify rate-limit 插件,每个用户 15 分钟内最多 100 次请求。生成视频会调很多下游 API,一个用户恶意刷可以快速消耗你的额度。
第三层——所有权校验:编辑或查看剧本时,检查 screenplay.userId === 当前用户。不匹配返回 403,用户之间数据完全隔离。
没有任何系统能 100% 防住所有攻击,但这三层能挡住绝大多数非故意的滥用。
实际使用场景 场景一:创作者快速出片
输入:"两个高中生考前崩溃,最后互相打气,真人漫剧风格"
三分钟后得到:带背景音乐、配音、字幕的 60 秒视频。角色造型在三个场景里保持一致。
这种使用方式最多,也是设计时的主要 persona。
场景二:品牌内容批量生产
一家电商品牌需要为不同产品线生产短视频。他们的工作流是:维护一个产品特性列表,每次生成时传入产品名和核心卖点,系统自动套入对应的剧情模板。
DirectorAI 支持场景级编辑:如果某一个场景不满意,可以单独重新生成,不用全部重来。
场景三:小说改编
有人用它把自己的网文改编成视频。做法是把章节摘要当 userInput 传进去,让系统提取角色和情节,生成分镜。不是完美翻译,但能快速验证改编方向。
几个没想到的问题
FFmpeg 的稳定性比想象中差:在处理某些 Seedance 输出的视频时,ffprobe 探测会超时。我们加了重试逻辑和回退路径,但这个问题到现在还偶发。
OpenRouter 的模型降级:OpenRouter 会在主模型不可用时自动切换到备用模型,这很方便,但有时切换的模型能力差别很大,导致生成质量波动。我们后来加了模型锁定选项,让用户可以选择"只用 Opus"或"只用 Sonnet",禁止自动降级。
角色一致性远没有解决:三视图技术能缓解问题,但没有根治。如果用 Seedance 生成的视频角色有动作,脸部细节的一致性会明显下降。这是当前图像生成技术的瓶颈,不是工程问题。
用户对"等待"的容忍度:三分钟对我们来说已经很快了,但用户第一次用时普遍觉得"太慢"。我们加了实时进度条和步骤说明("正在生成角色形象…"),同样三分钟,体验明显好了。等待本身不是问题,不知道在等什么才是问题。
复盘总结
做 DirectorAI 最大的收获不是技术,而是对"AI 工具的正确姿势"有了更清楚的认识。
AI 很擅长生成,不擅长自我评估。对抗评审是我们找到的一个还算有效的方法——让它生成,让另一个实例评估,循环。这个思路可以用在很多地方,不只是剧本生成。
第二个认识是流程标准化的价值。一旦你把每一步的输入输出定义清楚(剧本是 JSON,图片是固定分辨率,视频是固定时长),整个系统就有了测试的基础。否则每一步都是黑盒,调试起来会很痛苦。
第三个认识是用户感知比技术指标更重要。角色一致性是我们觉得最重要的技术问题,但用户最多的反馈是"配乐太好了"和"等待进度条做得好"。有时候工程师认为最难的部分,用户根本感知不到。
如果你也在做类似的 AI 应用,可以参考我们的 GitHub 仓库 和这篇文章里的代码片段。有问题欢迎在评论区讨论。
DirectorAI 还在持续迭代。下一个版本计划加入实时协作编辑和多语言配音支持。如果你有具体需求,可以留言。