AI 故事短片平台后端全链路复盘:从故事生成到分镜生图
前面写的很多东西——ComfyUI、Python、.NET、后台分层、接口和表设计——其实都还偏阶段性的学习和局部问题。到了 vchoo 这里,这些东西才第一次比较完整地被串成一条真实业务链:用户输入一个想法,系统生成故事,拆分分镜,再把分镜继续推进到生图。
所以这篇不再是纯学习笔记,而是一次完整一点的后端复盘,主要记这条链路当时是怎么在项目里被接起来的。
1. 先说背景:它不只是生图功能,后面还拖着一整条业务链
只把 vchoo 讲成“一个 AI 生图网站”,其实会把它说浅了。
真正麻烦也更有意思的,是后面那套完整流程:
- 用户输入一个创意或者主题
- 系统先生成故事内容
- 再把故事拆成分镜
- 每个分镜继续生成画面描述
- 最后进入生图环节,把分镜变成图像
图像生成只是最后一环。
前面其实已经有一整条文本链、任务链、状态链在跑了。
回想前段时间做这个项目的经历时,会觉得它对我影响很大。因为我第一次接触到的,不仅是孤立的某个模型调用
怎么把大模型、工作流、生图、业务状态和后端接口接成一套能让用户真正用起来的系统。
2. 这条链最开始看起来很顺,真正拆开以后其实每一段都不简单
最开始如果只用一句话描述这个系统,会觉得很流畅:
先生成故事,再拆分镜,再生成图。
但真正把它落到后端实现里以后,我很快就发现,这句话下面其实藏着很多完全不同类型的问题。
比如:
文本侧的问题
- 用户输入怎么收
- 故事生成结果怎么存
- 分镜拆分结果是什么结构
- 每个分镜的提示词怎么继续往下传
图像侧的问题
- 生图工作流怎么接
- 一个故事下会对应多少张图
- 批量生成时任务怎么追踪
- 某一张图失败了要怎么处理
系统侧的问题
- 整条链当前跑到哪一步了
- 用户能不能取消
- 失败以后能不能重试
- 前端怎么知道现在进度到哪里了
所以这条链难的不是某一个模型会不会调。难的是:
不同模态、不同步骤、不同耗时的任务,怎么被后端接成一条连续可追踪的流程。
3. 我当时最先意识到的一件事是:故事、分镜、生图,其实是三种不同粒度的对象
这点是我后来回头看,觉得当时挺关键的一个认识。
一开始如果不仔细想,很容易把整个流程都当成“一次生成任务”。
但真做起来以后会发现不行。
因为这三层东西的粒度其实完全不一样:
故事
它是一整次创作任务的上层结果。
分镜
它是故事往下拆出来的一组中间对象。
生图任务
它是落到某一个具体分镜上的执行任务。
一个用户请求进来以后,不会只落成一个结果,后面还会把一个大任务继续拆小。
这对后端的直接影响就是:
- 数据结构不能只按“一个请求一条结果”去想
- 状态跟踪不能只记录“完成 / 失败”这么简单
- 存储关系也不能只存一层
我后来慢慢会把这条链理解成:
- 故事是主任务
- 分镜是主任务下面的一组子对象
- 生图是子对象继续派生出来的执行任务
这个拆法一旦想清楚,后面的表关系、状态设计和接口设计都会顺很多。
4. 从后端视角看,这个项目的入口,其实是一条创作任务
这个地方我一开始其实也容易被结果带偏。
因为用户最直观看到的是图片,所以人会本能觉得系统的入口是生图。
可一旦落到后端实现,整个系统更像是从这里开始的:
用户发起一次完整创作任务。
这件事一旦这样定义,后面的很多东西就能统一起来。
因为这次创作任务里会包含:
- 用户原始输入
- 故事生成结果
- 分镜拆分结果
- 每个分镜的处理状态
- 生图任务进度
- 最终图像结果
后端不是在接一堆零散动作,而在维护一次完整创作流程的生命周期。
这个理解对我后来做接口很重要。
因为它让我更在意:
- 这次任务有没有唯一标识
- 当前是第几步
- 中间数据要不要保留
- 哪些结果应该立刻返回,哪些应该异步处理
5. 故事生成这一步,看起来像文本调用,实际上已经决定了后面链路好不好接
只看表面,故事生成像是最“轻”的一步。
毕竟它不像生图那样要排队、要跑工作流、要等图出结果。
但真往后接,我才发现故事生成这一块很关键。
因为它并不是决定一段文本,后面整条链的基础质量都依赖他。
如果故事结构太散,后面拆分镜就很乱;如果分段不稳,后面每个分镜的提示词也会跟着飘;如果文本结果本身不够可控,后面再接图像时问题会越来越放大。
所以从后端角度看,这一步虽然是调 LLM,但不能只当成“调一下模型拿个字符串回来”。
它更像是在生成后续所有子任务的上游输入。
所以我后来会更在意:
- 返回结果结构能不能稳定一点
- 后面拆分镜时好不好继续用
- 用户重试时该复用哪一层结果
6. 分镜拆分这一步,真正把“文本结果”推进成了“可执行对象”
对我来说,分镜拆分是这条链里一个特别有意思的阶段。
因为到这里,系统开始从“生成内容”转向“组织内容”。
故事还是一整块文本的时候,它更像一个结果。
但一旦拆成分镜,每个分镜就不再只是内容片段了,而是一个后面要被继续处理的对象。它会有自己的:
- 顺序
- 文本描述
- 图像提示
- 独立状态
- 生图结果
从这一步开始,后端不再只是存储结果,而是在维护一组后续还能继续流转的节点。
我觉得这也是这个项目很像“工作流系统”而不只是“AI 功能站”的原因。
因为系统从这里开始,已经天然具备了任务拆分和子任务管理的味道。
7. 生图不是最后一步那么简单,它其实是最重的一层执行链
到了生图这一步,前面很多学习笔记里碰到的问题基本都被集中放大了。
比如:
- ComfyUI 工作流怎么接
- 一个故事会拆出多个分镜,生图就变成批量任务
- 图像任务耗时长,不能同步卡死接口
- 失败不可能当作整次任务直接报废
- 用户会关心进度,不是只关心最终有没有图
所以把生图这一层聚焦成:
一组需要异步执行、可追踪、可重试、可取消的重任务。
这个定义一出来,后端很多动作就变明确了:
- 不能简单同步返回
- 要能查状态
- 要能记录每个分镜各自的结果
- 要能处理局部失败
所以我后来在这个项目里,对任务调度、状态记录、进度查询这些东西越来越敏感。
因为到这一步发现,用户真正感知到的“产品体验”,很多时候就落在这些后端细节上。
8. 把这条链接顺以后,我明白:后端更多是在维护状态机
这个认识很重要。
因为一开始接这类项目时,很容易把主要注意力都放在:
- 模型好不好用
- prompt 写得对不对
- 工作流稳不稳
这些当然都重要。
但项目真做下去以后,我发现后端的大头工作并不在“调模型”上,更多是在盯状态。
比如:
- 一次创作任务当前到哪一步了
- 故事有没有生成成功
- 分镜拆出来了没有
- 哪些分镜已经进生图队列
- 哪些分镜成功了,哪些失败了
- 用户现在能不能重试、取消或者继续操作
这时候你就会发现,这条链已经很像一套状态机了。
而后端的职责,就是把这些状态维护清楚,不然前台和用户那边看到的就会是一团糟。
9. 这也是我第一次比较完整地体会到:异步任务本身也是系统主干
前面做一些小接口的时候,异步更像是“某个功能需要就补一下”。
可到了 vchoo,异步任务已经不是顺手补上的配角了,它本来就在主线上。
因为故事生成、分镜处理、生图执行,这几层都不适合简单同步堵在那里等。
尤其是生图,一旦批量起来,接口不可能傻等。
所以从系统设计上看,这个项目本身就在逼着后端接受一件事:
很多核心能力,天生就要放在异步任务里跑。
这件事一旦接受,后面很多设计都会跟着变:
- 返回值不会只是一句成功失败
- 要有任务 Id
- 要有状态查询
- 要有进度反馈
- 要有异常恢复
我现在回头看,这其实是我第一次真正开始接触“任务型系统”的感觉。
10. 这条链能跑起来,是因为每一层都没掉链子
回头看这段经历,我其实不太想把它写成“某个技术点攻克了什么难关”。
因为 vchoo 这类项目最有代表性的地方,不在单点,而在整合。
这条链能跑起来,靠的是这几个环节都得站住:
- 用户输入得先接住
- 故事生成结果得能落下来
- 分镜得拆得出结构
- 每个分镜得继续往生图推进
- 生图任务得能追踪
- 最后的图得能回到系统里
这几步少一层都不行。
所以这项目留下来的收获,很大一部分都在这条链里。我是第一次从头到尾走进这样的后端实现:
从文本到图像、从同步接口到异步任务、从单点功能到整条业务链的后端实现。
11. 这段经历带给我最大的变化,是我开始换个角度看问题
如果只从“做了什么”来看,这段经历可以总结成很多关键词:
- LLM
- 分镜拆分
- ComfyUI
- 生图工作流
- .NET 后端
- 异步任务
但如果只停在关键词上,我觉得会把这段经历说浅。
真正留下来的变化,是我看问题时会更自然地往系统层去想。
以前我更容易问:
- 这个接口怎么写
- 这个工作流怎么接
- 这个字段怎么存
到了 vchoo 这里,我开始更经常去想:
- 这条链的上游和下游是什么
- 这一步失败以后,后面还能不能继续
- 用户现在看到的状态和系统真实状态是不是一致
- 一次任务拆成多层以后,数据和状态怎么收
这个变化对我来说挺关键。
因为它意味着,我开始不只是写一个功能,而是开始试着去理解:
一个 AI 业务系统到底是怎么被后端接住的。
12. 这篇先记一个阶段结论
如果让我给 vchoo 这条线现在先下一个阶段性结论,我会记这几条:
- AI 故事短片平台难不难,关键不在某个模型,而在整条链能不能接顺
- 故事、分镜、生图得分开看,它们本来就是三层对象
- 生图只是最后一环,前面的文本结构已经在决定后面好不好做
- 这类项目后端最核心的工作之一,就是维护状态和任务流转
- 异步任务、进度查询、局部失败处理,直接就是主干能力
这篇先写到这里。
现在回头看,vchoo 对我来说更像一个起点。我是从这里开始,认真理解“AI 能力怎么被接成业务系统”的。
