✨文末附开源仓库地址,做 AI 应用落地的同学可以直接拉下来跑。
本文为技术演示项目,仅供学习和交流参考,不建议直接用于生产环境。
当 LLM 遇见文生图、图生视频、TTS,如何把它们串成一个完整的产品?
前言
最近在关注多模型编排的工程化落地,发现很多团队在做 AI 产品时都会遇到类似的问题:
- 多个模型如何协同
- 长时异步任务怎么处理
- 某个环节失败怎么保证整体不崩
因此抽时间做了一套可运行的 Demo,把多模型链式调用、异步轮询、降级策略这些工程实践落地成代码。
把开发过程中遇到的真实问题在 Demo 中复现并给出解决方案,方便自己复盘总结,也给有需要的同学参考。
项目目标:为餐饮行业打造一套智能视觉内容生成系统,用户只需输入菜名,系统自动生成菜品图片和宣传视频。
技术挑战:
- 如何编排多个 AI 模型协同工作?
- 如何处理长时异步任务(视频生成需要几十秒)?
- 如何保证系统的健壮性(某个环节失败不能全盘崩溃)?
系统架构
整体设计
┌─────────────────────────────────────────────────────────────────┐
│ 前端 Vue 3 │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │
│ │ 图片生成页 │ │ 视频编排页 │ │ 拖拽排序 (vuedraggable) │ │
│ └─────────────┘ └─────────────┘ └─────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 后端 FastAPI │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 任务编排引擎 │ │
│ │ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────────┐ │ │
│ │ │ LLM │──▶│文生图│──▶│图生视频│──▶│ TTS │──▶│视频合并 │ │ │
│ │ └─────┘ └─────┘ └─────┘ └─────┘ └─────────┘ │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 阿里云百炼 API │
│ Qwen-Plus wan2.6-t2i wan2.7-i2v qwen3-tts-flash │
└─────────────────────────────────────────────────────────────────┘
核心流程
整个系统的核心是一个多模型链式调用流程:
- LLM 生成提示词:用户输入菜名,Qwen-Plus 自动生成 4 种不同风格的提示词
- 文生图:调用 wan2.6-t2i 生成菜品图片
- 用户选择:用户挑选满意的图片,编排视频顺序
- LLM 生成口播文案:根据菜名生成简短的宣传文案(≤20字)
- TTS 语音合成:调用 qwen3-tts-flash 合成口播音频
- 图生视频:调用 wan2.7-i2v,将音频作为 driving_audio 传入
- 视频合并:ffmpeg 拼接所有片段,添加字幕
使用演示
Step 1:输入菜名,批量生成图片
用户只需输入菜名(每行一个),系统自动调用 Qwen 大模型为每个菜名生成 4 种不同风格的提示词,然后批量生成图片:

如图:输入「宫爆鸡丁」和「尖椒鸡」两个菜名,系统自动计算
2 个菜品 × 4 种风格 = 8 张图片,右侧实时展示生成结果。
Step 2:挑选图片,跳转视频编排
生成完成后,用户勾选满意的图片,点击右上角「去编排视频」按钮进入视频编排页面:

如图:8 张图片全部生成完毕,用户勾选了宫爆鸡丁和尖椒鸡各一张,点击「去编排视频 (2)」即可进入下一步。
Step 3:编排顺序,一键生成宣传视频
在视频编排页面,用户可以拖拽调整视频顺序、编辑口播文案,点击生成后系统自动完成:口播文案生成 → 语音合成 → 图生视频 → 视频合并,最终输出一条带口播和字幕的完整宣传视频。

技术选型思考
为什么选 FastAPI?
- 原生异步:视频生成是长时任务,需要异步处理
- 类型安全:Pydantic 自动校验请求参数
- 文档自动生成:Swagger UI 方便前后端联调
为什么前端用 Vue 3?
- Composition API:复杂状态管理更清晰
- 生态成熟:Element Plus 组件库开箱即用
- 拖拽交互:vuedraggable 实现视频编排排序
为什么用阿里云百炼?
- 模型齐全:LLM、文生图、图生视频、TTS 一站式配齐
- API 统一:一个 SDK 调用所有模型,降低集成成本
- 国内访问:无需翻墙,延迟低
核心代码实现
1. 异步任务轮询
视频生成是异步任务,需要轮询查询状态:
python
def _poll_task_status(task_id: str, max_wait: int = 600) -> dict:
"""轮询任务状态,最长等待 max_wait 秒"""
waited = 0
interval = 15 # 每 15 秒查询一次
while waited < max_wait:
response = dashscope.VideoSynthesis.async_fetch(
task_id=task_id,
api_key=DASHSCOPE_API_KEY
)
status = response.output.task_status
if status == "SUCCEEDED":
return response.output
elif status == "FAILED":
raise Exception(f"任务失败: {response.output.message}")
time.sleep(interval)
waited += interval
raise TimeoutError(f"任务超时: {task_id}")
2. 首尾帧控制
为了让视频片段无缝衔接,采用首尾帧模式:
python
def generate_video_from_first_last_frame(
first_frame_path: str,
last_frame_path: str,
prompt: str,
duration: int
) -> str:
"""
首尾帧模式:
- 第 1 帧 = first_frame(本段开始画面)
- 最后 1 帧 = last_frame(上一段结束画面,保证衔接)
"""
# 提取首帧 base64
first_frame_b64 = encode_image(first_frame_path)
# 提取尾帧 base64
last_frame_b64 = encode_image(last_frame_path)
payload = {
"model": VIDEO_MODEL,
"input": {
"media": [
{"type": "first_frame", "url": first_frame_b64},
{"type": "last_frame", "url": last_frame_b64},
],
"prompt": prompt,
},
"parameters": {"duration": duration}
}
# ... 调用 API
3. 口播音频集成
视频 API 支持传入驱动音频,实现画面与语音同步:
python
def generate_video_with_audio(
image_path: str,
prompt: str,
audio_url: str, # TTS 合成的音频 URL
duration: int
) -> str:
payload = {
"model": VIDEO_MODEL,
"input": {
"media": [
{"type": "image", "url": image_b64},
{"type": "driving_audio", "url": audio_url}, # 关键!
],
"prompt": prompt,
},
"parameters": {"duration": duration}
}
4. 降级策略
某个环节失败时,不能让整个流程崩溃:
python
# 口播生成失败,视频照常生成(无音频)
audio_url = ""
if dish_name:
try:
tts_result = generate_voiceover_for_dish(dish_name, duration)
audio_url = tts_result["audio_url"]
except Exception as e:
logger.warning(f"口播生成失败,视频将无音频: {e}")
# 首尾帧模式失败,降级为首帧模式
try:
result = generate_video_from_first_last_frame(...)
except Exception as e:
logger.warning(f"首尾帧模式失败,降级为首帧: {e}")
result = generate_video_from_first_frame(...)
踩坑记录
1. 万相 API 响应格式
问题 :response.output.image 报错 'dict' object has no attribute 'image'
原因:新版 SDK 返回的是 dict,不是对象
解决:
python
# 错误
image_url = response.output.image.url
# 正确
image_url = response.output["image"]["url"]
# 或兼容写法
image_url = response.output.get("image", {}).get("url")
2. ffmpeg drawtext 中文字幕
问题 :Windows 上 ffmpeg drawtext 报错 Fontconfig error: Cannot load default config file
原因:standalone ffmpeg 没有 fontconfig 配置
解决:显式指定字体路径,并转义冒号:
python
# Windows 路径的冒号需要转义为 \:
font_path = "C\\:/Windows/Fonts/msyh.ttc"
drawtext = f"drawtext=text='{text}':fontfile='{font_path}':fontsize=48"
3. subprocess 错误信息丢失
问题:ffmpeg 执行失败,但日志看不到具体错误
原因 :capture_output=True 捕获了 stderr,但异常时没有打印
解决:
python
try:
result = subprocess.run(cmd, check=True, capture_output=True, text=True)
except subprocess.CalledProcessError as e:
logger.error(f"ffmpeg 失败: {e.stderr}") # 显式记录 stderr
raise
工程化实践
1. 配置管理
python
# 支持 PyInstaller 打包后的路径
def _get_data_path():
if getattr(sys, 'frozen', False):
return getattr(sys, '_MEIPASS', os.path.dirname(__file__))
return os.path.dirname(__file__)
# API Key 从环境变量读取
DASHSCOPE_API_KEY = os.getenv("DASHSCOPE_API_KEY", "")
2. 日志系统
python
# 同时输出到控制台和文件
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s [%(name)s] %(levelname)s: %(message)s',
handlers=[
logging.StreamHandler(),
logging.FileHandler('logs/app.log', encoding='utf-8')
]
)
3. 前端交互
- 拖拽排序:vuedraggable 实现视频片段编排
- 实时进度:轮询后端接口,显示当前处理进度
- 预览弹窗:点击缩略图预览视频
- 历史管理:支持删除/清空生成的文件
性能数据
| 任务 | 耗时 | 说明 |
|---|---|---|
| LLM 生成提示词 | ~3s | 4 种风格 |
| 单张图片生成 | ~10s | 含网络传输 |
| 5秒视频生成 | ~45s | 异步轮询 |
| 口播文案生成 | ~3s | LLM 调用 |
| 语音合成 | ~2s | TTS 调用 |
| 视频合并(2段) | ~2s | 本地 ffmpeg |
完整流程:2 个菜品的宣传视频(含口播),总耗时约 2 分钟。
总结
这个项目让我对 AI 应用落地有了更深的理解:
- 模型编排是核心:单个模型能力有限,串联起来才能解决复杂问题
- 异步处理是必须:视频生成动辄几十秒,必须异步 + 轮询
- 降级策略很重要:生产环境不能因为某个环节失败就全盘崩溃
- 工程化决定成败:配置管理、日志、错误处理,这些决定了系统能否真正上线
如果你也在做 AI 应用开发,希望这些经验对你有帮助。
项目地址 :Gitee (欢迎 Star)
本 Demo 仅做技术复盘与学习演示,基于多模型编排工程实践经验提炼,后续还会持续迭代补充更多场景优化。