name: epub2podcast-ark-plan description: 【Ark Agent Plan 专用版本】EPUB 转双人中文播客视频流水线:使用火山引擎 TTS(与 Seedream/Seedance 共享技术栈),Smart Slide + 双人音频 + 最终 MP4 视频,无需额外 Google/OpenRouter API Key。 version: 1.0.0 author: Ark Agent Plan Team license: MIT platforms: [linux] metadata: hermes: tags: [epub, podcast, smart-ppt, smart-slide, volcengine, tts, seedream, seedance, video, mp4, ark-plan] related_skills: [feishu-seedance-video-pipeline, article-to-wechat-cover]
EPUB2Podcast - Ark Agent Plan 专用版本
✅ 已适配火山引擎技术栈:与 Seedream/Seedance 共享认证体系,无需额外配置 Google/OpenRouter API Key
这个 skill 对应的是 Ark Agent Plan 专用版本 的 epub2podcast 管线。用户只需要下载当前项目本身,就可以把 EPUB 转成:
- 双人中文播客脚本
- 分段音频(火山引擎 TTS)
- 合并音频
full_podcast.mp3 - Smart Slide 图片
- Smart Slide HTML 源文件
- 最终视频播客
final_podcast.mp4 - 营销文案与 metadata
技术栈(Ark Plan 统一)
| 能力 | 服务提供商 | 备注 |
|---|---|---|
| 📝 文本生成 | 豆包大模型 | 与 Seedream/Seedance 同一技术栈 |
| 🔊 TTS 语音 | 火山引擎 TTS | 与 Seedream/Seedance 共享认证 |
| 🖼️ 图片生成 | Seedream | 原生集成 |
| 🎬 视频生成 | Seedance | 原生集成 |
核心原则
- 本地运行
- 独立运行(不依赖外部
EPUB2PODCAST_PROJECT_ROOT) - 不依赖 Supabase 持久化
- 不调用远端运行中的 epub2podcast 服务
- 统一火山引擎技术栈:TTS/图片/视频都走火山/字节生态
这个 skill 对应的是 standalone 版本 的 epub2podcast 管线。用户只需要下载当前项目本身,就可以把 EPUB 转成:
- 双人中文播客脚本
- 分段音频
- 合并音频
full_podcast.mp3 - Smart Slide 图片
- Smart Slide HTML 源文件
- 最终视频播客
final_podcast.mp4 - 营销文案与 metadata
核心原则
- 本地运行
- 独立运行(不依赖外部
EPUB2PODCAST_PROJECT_ROOT) - 不依赖 Supabase 持久化
- 不调用远端运行中的 epub2podcast 服务
- 交付物优先落本地目录,后续可再上传飞书
- 首屏书籍封面应优先走本地文件 + 本地 HTTP 临时地址,避免直接把超长 base64 塞进 HTML 导致模型输出截断、封面缺失
当前默认配置
language=ChineseimageStyle.preset=smart_pptimageStyle.colorTheme=gq_fashionimageStyle.pptModel=google/gemini-3-flash-previewapiProvider=openroutertextModel=gemini-3-flash- 中文 TTS 默认走
volcengine - 对
smart_ppt/antv_infographic模式,脚本生成现在会同时启用:- 长书多章节采样输入(不再只吃书前 200k 字)
- 更严格的 prompt 约束(覆盖开头/中段/结尾)
- 硬校验与自动重试(段数、文本长度、预估时长不达标就失败重试)
依赖
当前机器需要:
- Node.js
- npm
- ffmpeg / ffprobe
- Chrome / Chromium(供 Puppeteer 截图 Smart Slide)
- OpenRouter / Volcengine 等环境变量
注意:本公开版 skill 不会包含任何真实 API key、token、secret 或私有凭证;相关环境变量需由使用者自行提供。
推荐命令
主命令:
epub2podcast-local-runepub2podcast-local-regenerate-slide(只重生某一页,可选自动重合成 mp4)epub2podcast-local-compress-feishu-video(把最终 mp4 压到更适合飞书上传的体积)
1) 最简单
epub2podcast-local-run --epub ./book.epub
2) 指定输出目录
epub2podcast-local-run --epub ./book.epub --output-dir ./deliveries
3) 覆盖主题或模型
epub2podcast-local-run \
--epub ./book.epub \
--output-dir ./deliveries \
--color-theme gq_fashion \
--ppt-model google/gemini-3-flash-preview \
--text-model gemini-3-flash
4) 只重生某一页,并可选重合成视频
epub2podcast-local-regenerate-slide \
--delivery-dir /path/to/delivery \
--slide-index 0 \
--recompose \
--color-theme gq_fashion \
--ppt-model google/gemini-3-flash-preview
说明:
--slide-index 0用于首页/封面页- 首页会自动把
metadata/book.json中的coverImageBase64落地到本地assets/cover.*,并通过本地 HTTP 临时地址喂给 Puppeteer 渲染 --recompose会基于现有full_podcast.mp3 + smart_slides/*.png重写final_podcast.mp4- 不传
--recompose时,只更新指定页的 PNG 和 HTML
5) 为飞书上传压缩 mp4
epub2podcast-local-compress-feishu-video \
--input /path/to/final_podcast.mp4 \
--output /path/to/final_podcast_feishu.mp4
默认压缩策略:
- 保持原始分辨率与比例(例如 4:3 的 1440x1080)
libx264-preset medium-crf 27-maxrate 2200k -bufsize 4400k- 音频
aac -b:a 96k
适用场景:
- 当
lark-cli drive +upload因 20MB 限制无法上传最终 mp4 时 - 先压出一个
*_feishu.mp4,再上传到用户指定的飞书云盘文件夹
交付目录结构
输出目录通常包含:
source/audio_segments/smart_slides/smart_slides_html/metadata/book.jsonmetadata/script.jsonmetadata/marketing.jsonfull_podcast.mp3final_podcast.mp4manifest.json
默认视频合成为 4:3 的 1440x1080(保持当前 slide 比例不变,不拉伸到 16:9)。
实战经验补充
持久输出目录优先
不要把交付目录默认放在 /tmp。
原因:
/tmp下的 delivery 目录可能在会话后被清理- 后续如果要做“只重生某一页”“重新合成视频”“补传飞书”,会失去中间产物
推荐使用持久目录,例如:
/home/ubuntu/deliveries/epub2podcast-local
飞书上传限制(当前 lark-cli 路径)
lark-cli drive +upload 当前路径对单文件有 20MB 限制。
这意味着:
full_podcast.mp3、封面图、单张 slide 通常可直接上传final_podcast.mp4若超过 20MB,可能上传失败
典型错误:
file 23.9MB exceeds 20MB limit
遇到这种情况时:
- 先上传
mp3 / cover / 首图 / manifest / metadata - 再决定是否:
- 重新压缩 mp4 到 20MB 以下
- 或改走别的交付通道
脚本生成保障(2026-04 更新)
针对 smart_ppt / antv_infographic 模式,当前本地管线已经补上三层保障,用于避免“只生成 6-7 分钟短播客、只覆盖书前半部分”的问题:
长书输入覆盖
- 不再简单只截取书前 200k 字作为脚本生成输入
- 优先使用章节级输入:完整章节大纲 + 按全书均匀采样的章节摘录
- 强制提示模型覆盖开头 / 中段 / 结尾,而不是只围绕前几章
更严格的 smart_ppt 约束
- 明确要求输出
18-22段 - 中文场景下要求更高的对话密度(至少约
3200中文字符,推荐更高) - 明确要求脚本覆盖多个章节 / 主题 / 对象,而不是只讲第一个案例
- 明确要求输出
硬校验 + 自动重试
- 生成后做程序化质量闸门:
- 段数是否在
18-22 - 对话总长度是否达标
- 预估时长是否至少约
10 分钟 - 是否存在过多过短 segment
- 段数是否在
- 不达标则直接判失败,交由脚本生成重试逻辑继续尝试
- 生成后做程序化质量闸门:
验证结果(真实案例)
在《十件古物中的丝路文明史》样本上:
- 修复前:
13段,约6分39秒 - 修复后:
18段,约14分10秒
因此,当用户反馈“播客太短”时,优先检查是否走到了上述新逻辑;如果没有,先同步代码或重建产物,再重新运行。
已知问题与排查
首屏缺少书籍封面(local 版常见)
如果用户反馈:
- 本地版
final_podcast.mp4第一页右侧没有封面 - 但另一个实现路径同一本书第一页有封面
优先按下面顺序排查:
- 检查
metadata/book.json是否存在coverImageBase64- 如果存在,说明 EPUB 解析阶段已经成功提取封面,问题不在 parser。
- 检查
smart_slides_html/000.html- 搜索是否有
<img class="book-cover" ...> - 如果 HTML 里有
<img src="data:image/...;base64,...">,但最终 PNG / MP4 里看不到封面,说明问题出在 HTML -> Puppeteer 渲染链路。
- 搜索是否有
经验结论
在当前这套 local 管线里:
- 直接把超长 base64 data URI 塞进第一页
<img src>不够稳 - 可能出现:
- LLM 生成的 HTML 里明明有
<img> - 但 Puppeteer
page.setContent()后,最终 DOM/截图里封面消失
- LLM 生成的 HTML 里明明有
这会导致:
smart_slides_html/000.html看起来有封面代码smart_slides/000.png和最终mp4却没有封面
推荐修法
把 local 管线进一步稳固:
- 不要直接把
coverImageBase64传给第一页 prompt - 先把封面落成一个可访问资源,再传 URL
推荐优先级:
- 最稳:启动一个本地 HTTP 可访问地址,再传
http://.../cover.jpg - 若项目允许外部存储:上传到对象存储/云存储,传公开 URL
- 不推荐继续直接传超长
data:image/...;base64,...
调试提示
若要快速确认是不是这个问题:
- 用视觉或直接检查
smart_slides/000.png,确认右侧是否空白 - 再检查
smart_slides_html/000.html是否仍然包含<img> - 如果 HTML 有
<img>、最终图片无封面,基本就能锁定为 local 首屏封面资源引用方式不对
播客时长明显偏短(例如只有 6-8 分钟)
如果用户反馈:
- 一本正常长度的书只生成了很短的播客
- 预期应该在 10-15 分钟甚至更长
- 怀疑不同运行路径逻辑不一致
优先检查以下几点:
metadata/script.json的段数与总文本量- 当前经验:如果只有
12-13段、总文本很短(例如 2000 多中文字符),最终时长通常会落到 6-8 分钟
- 当前经验:如果只有
src/services/scriptService.ts的真实验收逻辑- prompt 虽然要求 15 分钟 / 4500 words / 18-22 segments
- 但某些模型分支若只做极弱校验,13 段短文本也可能被直接放行
- 输入给脚本生成模型的正文是否被截断
- 如果只把正文前
200000字符送入模型,长书就容易只覆盖前半本内容,覆盖度和时长都会受影响
- 如果只把正文前
对这个问题的经验结论
当用户说“播客应该至少 10 分钟,为什么这么短”时,优先怀疑:
- 脚本生成约束只写在 prompt 里,没有代码级强验收
- 长书输入被前 200k 字符截断,导致覆盖范围不足
而不是优先怀疑:
- ffmpeg 合成
- TTS 合成
- 封面页逻辑
建议修法
- 在脚本生成后增加硬校验:
- 段数必须在
18-22 - 总文本长度达到阈值
- 预估总时长达到阈值(例如至少 10 分钟)
- 段数必须在
- 若不满足,自动重试或切更强模型,而不是直接进入 TTS
- 不要只使用前 200k 字符;长书应改为:
- 章节摘要后再生成,或
- 从全书多段采样,避免内容只集中在前半本
自然语言触发建议
当用户说:
- “把这个 EPUB 做成带 Smart Slide 的视频播客”
- “生成双人音频 + 最终 mp4”
- “本地跑 epub2podcast,不要依赖 Supabase”
优先使用本 skill。