从视频到文章:AI 自动生成美食教程
前言
记录把一条美食教学视频整理成一篇可以阅读、复做、发布到博客的结构化文章项目的实现流程。
例如 YouTube 视频、本地视频、本地 rmvb/mp4/mkv 文件等。它会先把视频里的内容转成文字,再用大模型整理成菜谱文章,最后生成 AI 封面并上传到图床。最终产物可以直接复制到 Hexo博客里发布。
目前核心功能包括:
- 处理单条 YouTube 视频。
- 批量展开 YouTube 频道、播放列表、频道 videos 页面。
- 处理单个本地视频或音频。
- 批量扫描本地视频目录。
- 优先读取 YouTube 字幕,没有字幕时自动下载音频并转写。
- 支持 FunASR 和 Whisper 两种 ASR 路线。
- 用提示词把转写稿整理成结构化文章。
- 为文章生成 AI 封面图。
- 上传封面到 EasyImage 图床,并回写文章
cover字段。 - 支持断点续跑、批量报告、局部问题提示。
- 支持从已有
raw.md补跑文章,或者只重生成封面。
它不是单纯的“视频摘要工具”,而是偏向“内容生产流水线”:输入视频,输出博客文章和配套静态资源。
它适合处理这类场景:
- 视频内容有价值,但不方便反复看。
- 视频步骤很多,需要整理成可查阅文档。
- 视频标题和封面信息太杂,需要生成干净博客文章。
- 想把公开视频、本地课程或资料视频批量整理成知识库。
- 想把内容发布到静态博客,而不是只留在本地文件夹。
我现在把它用于“一览美食”博客:把美食教学视频整理成可复做菜谱,让读者不必在视频里来回拖进度条,也能快速看到食材、步骤和关键技巧。
演示地址:https://cook.yilanapp.com
用到的模型
项目里模型分三类:语音转文字、文章整理、封面生成。
语音转文字
默认使用 FunASR:
1 | { |
模型文件默认缓存到项目目录下:
1 | models/ |
第一次使用 FunASR 转写时,如果本地没有模型,会通过 ModelScope 自动下载到这个目录。后续再次运行时,项目会优先使用本地已有模型目录,尽量避免因为 ModelScope 临时超时而影响转写。换电脑时也可以把 models\funasr 整个目录迁移过去,减少首次下载等待。
可替代方案:
paraformer:同样属于 FunASR 路线,可以作为中文 ASR 备选。whisper:项目里支持tiny/base/small,通过faster-whisper调用,更适合作为备选或对照。
如果主要处理中文教程视频,优先选 FunASR + SenseVoiceSmall;如果是多语言视频,或者 FunASR 对某些音频表现不稳定,再考虑 Whisper。
文章整理
文章整理使用大模型的 Chat Completions 接口。配置示例是 OpenAI 兼容接口:
1 | { |
AI 封面生成
封面生成支持两条路线。
配置模板里默认是 ModelScope:
1 | { |
也支持 OpenAI 兼容生图接口:
1 | { |
封面生成的重点不是照搬视频封面,而是根据菜品主体重新生成一张干净的成品菜图。项目会尽量避免文字、水印、拼贴图、视频缩略图风格,目标是适配博客 16:9 封面。
如果原始缩略图本身比较干净,项目会把它作为菜品主体参考,在构图、光线、质感上重新生成。如果原图有大字、水印、拼贴或视频感很重,就只参考食物主体,不保留原封面上的文字元素。
生成后的图片会保存到本地,并可以上传到 EasyImage:
1 | { |
数据处理流程
整体流程可以理解成下面这条链路:
1 | 视频链接 / 本地视频 |
输入
支持的输入包括:
- YouTube 单条视频 URL。
- YouTube 频道、播放列表、频道 videos 页面。
- 本地视频文件,例如
mp4、mkv、mov、webm、rm、rmvb。 - 本地音频文件,例如
mp3、wav、m4a。 - 批量清单文件,每行一个视频路径或 URL。
中间产物
项目会把中间文件分类保存,避免根目录混乱。
运行数据在 data:
1 | data/ |
YouTube 音频如果已经下载过,后续重跑会优先复用本地 mp3,不必重新从 YouTube 下载。这样下载成功但 ASR、大模型或封面生成失败时,可以直接从中间产物继续补跑。
文章产物在 output:
1 | output/ |
也就是说,YouTube 单条视频会按“平台 / 频道 / 视频”保存,本地批量视频会按“平台 / 批次目录 / 菜品”保存。旧版本生成的平铺目录仍可读取,但新的输出会尽量按来源归档。
每个视频目录里常见文件包括:
1 | 视频目录/ |
其中:
raw.md是原始转写稿,后续补跑文章时可以直接复用。文章标题.md是最终可发布文章。cover-ai.jpg是本地 AI 封面图。cover-ai.json记录生图、上传、回写结果。metadata.json、thumbnail.jpg主要出现在 YouTube 视频目录。_batch_reports保存每次批量处理报告,也会在文章被移动走时辅助判断是否曾经生成成功。
输出
最终最重要的输出是 Markdown 文章。以美食视频为例,文章会包含:
- Hexo front-matter。
- 分类、标签、菜系、菜品类型、烹饪方法。
- 一句话摘要。
- 做法速览。
- 食材与配方表。
- 制作流程 timeline。
- 关键技巧。
- 易错点与处理。
- 营养与食用提醒。
- 批量制作与出餐建议。
- AI 封面图链接。
这类结构适合直接发布到 Hexo / 安知鱼主题,也方便后续搜索、分类和归档。
批量处理和断点续跑
常见命令类似:
1 | python transcribe.py --batch "data\local\中国八大菜系之川菜-100道\videos.txt" --prompts snack_recipe --limit 10 --skip-existing |
几个参数的作用:
--limit 10:本次只处理 10 个。--skip-existing:跳过已经完整处理过的条目。--dry-run:只预览,不实际处理。--from-raw:已有raw.md时,只补跑大模型整理。--regen-cover:只重新生成封面。
批量计划现在会把状态分得更细:
1 | output 完整:raw.md 和正式文章都存在,文章结构校验通过 |
这里的 _batch_reports 不会替代输出文件判断,也不会去扫描 Hexo 博客目录。它只在一个场景下辅助判断:raw.md 还在,但正式文章已经被移动到博客目录,报告能证明这个视频曾经生成过文章。这样批量续跑时不会反复把同一个视频当成未完成。
批量结束后会生成报告,记录成功、失败、局部问题和补救命令。局部问题包括封面生成失败、图床上传失败、文章缺 cover 等。
常见补救命令有两类。
如果 ASR 已完成,但大模型整理失败,可以从 raw.md 补跑:
1 | python transcribe.py --from-raw "output\local\批次目录名\菜品名\raw.md" --prompts snack_recipe |
如果文章已经生成,但 AI 封面或图床上传失败,可以只补封面:
1 | python transcribe.py --regen-cover "output\local\批次目录名\菜品名\文章标题.md" |
这两个命令都不会重新处理视频。前者复用原始转写稿,后者只处理封面生成、上传和文章 cover 回写。
提示词如何扩展
项目的提示词放在:
1 | prompts/ |
现在美食文章主要使用:
1 | prompts/snack_recipe.md |
如果要扩展到其他类型视频,不需要重写主程序,优先新增提示词即可。
例如:
1 | prompts/tutorial_note.md # 教程视频整理 |
然后运行:
1 | python transcribe.py --url "视频地址" --prompts tutorial_note |
提示词里需要定义:
- 输入转写稿如何理解。
- 输出文章结构。
- 是否需要 front-matter。
- 是否需要表格、步骤、清单。
- 哪些内容不能编造。
- 哪些不确定内容要标注。
也就是说,项目底层是通用的视频转写和内容整理管线,美食只是当前最完整的一套提示词模板。
可以扩展到哪些方向
视频平台扩展
当前代码已经区分了:
YouTubeBilibiliLocalUnknown
YouTube 已经支持字幕提取、频道/播放列表展开、cookies 登录态。B 站目前有搜索入口,后续可以继续补全单视频下载、合集展开等能力。
如果要加新平台,大致需要补:
- 平台识别规则。
- 元数据提取。
- 音频下载或字幕提取。
- 批量列表展开。
- 失败诊断和 cookies 处理。
视频类型扩展
除了美食视频,还可以扩展到:
- 编程教程。
- 软件教学。
- 课程视频。
- 会议纪要。
- 访谈整理。
- 家庭影像回忆总结。
- 产品测评。
- 读书视频笔记。
扩展的关键不是改 ASR,而是改提示词和输出结构。
例如教程视频可以输出:
- 学习目标。
- 前置知识。
- 操作步骤。
- 命令清单。
- 常见错误。
- 复习提纲。
访谈视频可以输出:
- 嘉宾观点。
- 时间线。
- 关键引用。
- 主题归纳。
- 延伸问题。










