mcpField
B
blog-audio

blog-audio

github.com/agricidaniel创意与媒体2.6k2.6k 次安装2 周前更新
代码仓库

关于 blog-audio

blog-audio 是将博客文章转换为 Gemini TTS 朗读音频的技能,支持口述摘要、全文朗读和双人对话。它提供预设音色选择,并可生成 HTML5 音频嵌入指导。

主要功能

  1. 01摘要、全文和对话模式
  2. 02Gemini TTS 语音生成
  3. 03预设音色选择
  4. 04长文本分块并限制数量
  5. 05HTML5 音频嵌入指导

适用场景

  1. 01制作文章的简短音频摘要
  2. 02将全文制作成朗读音频
  3. 03生成双人播客风格版本
  4. 04在博客中添加音频播放器

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/agricidaniel/claude-blog --skill blog-audio

安装后在 Claude Code 中输入/blog-audio确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
voices.md
scripts/
__init__.py
generate_audio.py
requirements.lock
requirements.txt
run.py
runtime_paths.py
setup_environment.py

详细介绍

博客音频:使用 Gemini TTS 为博客文章配音

以下捆绑路径使用主机 Markdown 对 ${CLAUDE_SKILL_DIR} 进行替换; 它不是导出的 shell 变量。执行前先解析路径并为路径加引号, 并拒绝非绝对路径的覆盖值。将从 ${CLAUDE_SKILL_DIR}/../blog/references 解析出的 blog_reference_root、从 ${CLAUDE_SKILL_DIR}/../blog/templates 解析出的 blog_template_root 以及所需的同级根目录传递给 Agent。 加载项目上下文前,先阅读主参考文件 orchestration-details.md; 只将其由 helper 围栏限定的输出传递给下游 Agent。

使用 Google 的 Gemini TTS 为博客内容生成专业的音频配音。 提供三种模式:摘要(200-300 字的口语概述)、全文朗读,或双人播客对话。 Gemini 3.8 Flash TTS 支持 30 种预置语音和 130 多种语言(Flash-Lite 支持 100 多种语言;Google 的语音生成页面,核查日期为 2026-10-12),并输出 HTML5 嵌入内容。

费用与授权门槛(必读)

此技能会消耗用户的 Google AI 额度并写入音频文件。

  • 费用说明: 每个文本块会调用一次付费 Gemini TTS。长文本会拆分成多个文本块,因此全文朗读会产生多次调用。脚本的 --max-chunks 标志会限制每次运行的文本块数量(默认值为 12);未告知用户新的最高费用前,绝不能调高此值。
  • 费用依据: 音频输出每秒消耗 25 个 token。2026-10-12,https://ai.google.dev/gemini-api/docs/pricing 列出的价格为:gemini-3.8-flash-tts 每 100 万个音频 token 收费 $9.00(每 10 秒约 $0.00225),gemini-3.8-flash-lite-tts 收费 $6.00(每 10 秒约 $0.0015);这两个价格均适用至 2026-12-31,2027-01-01 起所列价格更高。先运行 --dry-run --json,查看脚本的费用估算。
  • 写入内容: 写入 audio/ 下的音频文件(或写入 --output 指定的位置),并且仅在设置时写入托管的 .venv。
  • 授权: 会话中的首次付费调用前,先说明模式、模型、文本块数量和预估费用,然后等待用户明确同意。同意仅适用于本次运行。用户撰写博客文章不代表同意生成音频。
  • 禁止无上限支出: 付费调用不得超过上限后重试或循环;遇到暂时性错误时可重试一次,然后报告结果。
  • 跳过情形: 如果用户拒绝、缺少密钥或未完成设置,则跳过,并返回一行内容供协调器填写在“回退与跳过”摘要中,例如“音频:未设置 API 密钥,已跳过”。

快速参考

命令功能
/blog audio generate <file>为博客文章生成音频配音
/blog audio voices显示可用语音及其特点
/blog audio setup检查/配置 Gemini TTS 的 API 密钥

前提条件

  • Python 3.11+;托管虚拟环境由显式设置操作管理
  • GOOGLE_AI_API_KEY 或 GEMINI_API_KEY 环境变量(blog-image 使用 GOOGLE_AI_API_KEY;音频脚本接受任意一个)
  • FFmpeg(用于将 WAV 转换为 MP3;缺少时回退到 WAV)。绝不能隐式安装;告知用户并由用户自行安装

持久运行时目录

CLAUDE_BLOG_RUNTIME_DIR 可选,用于指定一个可信的绝对持久化根目录。此集成使用 <root>/blog-audio/.venv;NotebookLM 还会使用 <root>/blog-notebooklm/data 存储其资料库、身份验证和浏览器状态。未设置此覆盖项时,继续使用现有的技能本地默认路径。 Google 的共享凭据配置/令牌路径保持不变。不会自动复制或迁移任何状态,常规运行也绝不会执行设置。

保留现有且已验证的运维人员覆盖项。对于没有覆盖项的插件,在设置时以及每次后续运行器调用时,都显式传入由宿主替换的 ${CLAUDE_PLUGIN_DATA}/claude-blog-runtime 路径。这是 Markdown 替换,不是导出的 shell 变量。只有在路径已解析为绝对路径后才执行。单引号会让未解析的占位符保持原样,从而使校验拒绝该路径,而不是将其展开为不同的 shell 路径:

CLAUDE_BLOG_RUNTIME_DIR='${CLAUDE_PLUGIN_DATA}/claude-blog-runtime' python3 "${CLAUDE_SKILL_DIR}/scripts/setup_environment.py" --check --json
CLAUDE_BLOG_RUNTIME_DIR='${CLAUDE_PLUGIN_DATA}/claude-blog-runtime' python3 "${CLAUDE_SKILL_DIR}/scripts/run.py" generate_audio.py --help

只有不带 --check 的显式设置才会安装依赖。独立用户继续使用默认路径,除非他们显式选择一个绝对运行时根目录。相对路径、未解析路径或链接的托管子目录都会被安全拒绝。更改根目录会选择独立的状态;这绝不授权迁移或清理旧根目录。插件持久数据遵循宿主的卸载保留规则;如果卸载时仍需要这些数据,请显式保留。

使用已安装的 run.py 包装器

BLOG_SKILLS_DIR="${CLAUDE_BLOG_SKILLS_DIR:-${CLAUDE_SKILL_DIR}/..}"
case "$BLOG_SKILLS_DIR" in /*) ;; *) echo "ERROR: skills dir must be absolute" >&2; exit 1 ;; esac
AUDIO_RUN="$BLOG_SKILLS_DIR/blog-audio/scripts/run.py"
python3 "$AUDIO_RUN" generate_audio.py --text "..." --voice Charon --model flash38 --json

常规的 generate 和 voices 命令会执行不修改状态的功能检查。如果托管环境不存在,则返回需要设置的结果。只有 /blog audio setup 可以创建 .venv 或安装依赖。切勿从当前项目的 scripts/ 目录解析包装器。

API 密钥检查(门控模式)

生成音频前,检查 API 密钥(脚本会先读取 GOOGLE_AI_API_KEY,再读取 GEMINI_API_KEY):

if [ -n "${GOOGLE_AI_API_KEY:-}" ] || [ -n "${GEMINI_API_KEY:-}" ]; then echo "API key is set"; else echo "API key is not set"; fi
  • 如果其中一个已设置:继续执行同意门控,然后生成
  • 如果两者都未设置:引导用户: “生成音频需要 Google AI API 密钥。请前往 https://aistudio.google.com/apikey 获取。 然后在 shell 中导出该密钥:export GOOGLE_AI_API_KEY=your-key(或 GEMINI_API_KEY)。 这可以与 /blog image 使用同一个密钥。”
  • 内部调用时(来自 blog-write):如果缺少密钥,返回一行跳过说明(说明跳过什么以及原因),供调用方写入最终摘要。绝不阻止写作工作流。

设置

对于 /blog audio setup:

  1. 检查环境中是否设置了 GOOGLE_AI_API_KEY 或 GEMINI_API_KEY
  2. 如果 blog-image 使用项目 .mcp.json,确认其中引用的环境变量已导出
  3. 如果没有,引导用户前往 https://aistudio.google.com/apikey
  4. 经用户同意后,创建或刷新托管环境。这是唯一会安装依赖的步骤: python3 "$BLOG_SKILLS_DIR/blog-audio/scripts/setup_environment.py" (添加 --check --json 可在不安装的情况下进行检查)
  5. 使用试运行进行验证(不调用 API): python3 "$AUDIO_RUN" generate_audio.py --text "Test" --dry-run --json

语音选择

对于 /blog audio voices:

加载 ${CLAUDE_SKILL_DIR}/references/voices.md,并向用户展示语音目录。

询问用户偏好的语音,或根据内容类型进行推荐:

  • 文章旁白:Charon(Informative)或 Sadaltager(Knowledgeable)
  • 教程/操作指南:Achird(Friendly)或 Sulafat(Warm)
  • 新闻/分析:Rasalgethi(Informative)或 Schedar(Even)
  • 生活方式/健康:Aoede(Breezy)或 Vindemiatrix(Gentle)
  • 对话主持人:Puck(Upbeat)或 Laomedeia(Upbeat)
  • 对话专家:Kore(Firm)或 Charon(Informative)

生成工作流

对于 /blog audio generate <file>:

步骤 1:读取博客文章

读取文件并提取:

  • 标题(来自 H1 或 frontmatter)
  • 完整内容(Markdown 正文)
  • 大致字数
步骤 2:选择模式

询问用户(如果用户指定了 --mode,则自动选择):

模式适用场景输出
Summary快速音频概览(1-2 分钟)200-300 词的口语化摘要
Full完整朗读(5-15 分钟)将全文改写为自然口语
Dialogue播客风格(3-8 分钟)两人围绕文章展开对话
步骤 3:准备文本

由 Claude 准备文本;脚本只负责 TTS。

Summary 模式: 撰写一份 200-300 词的文章口语化摘要。规则:

  • 写得像自然对话,而非书面文字
  • 以文章的关键发现或答案开篇
  • 涵盖 3-5 个主要要点
  • 以可执行的建议收尾
  • 不要使用 Markdown,不要写“In this article...”,也不要添加元评论
  • 使用对话式过渡语(“重点在于……”“关键发现是……”)

Full 模式: 将 Markdown 内容整理为干净、适合朗读的文本:

  • 将标题改写为自然过渡语(“接下来,我们来看看……”)
  • 将链接改为纯文本(删除 URL,保留锚文本)
  • 图片和图表:省略或简要描述(“从数据中可以看出……”)
  • 代码块:用口语描述(“这段代码使用了一个 for 循环……”)
  • 将列表改写为自然句子
  • 删除 frontmatter、schema 标记和 HTML 标签
  • 添加简短开场白:“本文是[标题],发表于[日期]。”

Dialogue 模式: 围绕文章撰写双人对话脚本:

  • Speaker1 = 主持人(充满好奇,善于提问)
  • Speaker2 = 专家(知识渊博,回答清晰)
  • 每行格式为:Speaker1: 这里最重要的启示是什么?
  • 以对话形式涵盖文章的主要内容
  • 进行 15-25 轮对话(生成约 3-8 分钟的音频)
  • 表达自然,不要生硬(使用“这是个很好的观点”,而不是“确实,正如研究所表明的那样”)
步骤 4:选择语音

如果用户选择了语音,则使用该语音。否则,根据模式推荐:

  • Summary/Full:默认使用 Charon(Informative)
  • Dialogue:默认使用 Puck(Host)+ Kore(Expert)
步骤 5:生成音频

将准备好的文本写入工作目录下的文件,然后调用:

# Single voice (summary or full mode)
python3 "$AUDIO_RUN" generate_audio.py \
  --text-file blog_audio_prepared.txt \
  --voice Charon \
  --model flash38 \
  --output audio/post-slug.mp3 \
  --json

# Two voices (dialogue mode)
python3 "$AUDIO_RUN" generate_audio.py \
  --text-file blog_audio_dialogue.txt \
  --voice Puck \
  --voice2 Kore \
  --model flash38 \
  --output audio/post-slug-dialogue.mp3 \
  --json

模型选择(使用明确的 3.8 ID):

  • flash38:gemini-3.8-flash-tts,稳定的通用模型,也是上述示例中使用的模型。支持 130 多种语言。
  • flash-lite38:gemini-3.8-flash-lite-tts,成本更低的稳定模型。支持 100 多种语言;少数语言(例如芬兰语和泰语)仅 Flash 支持。
  • 旧版别名 flash、flash31、pro、legacy-flash25、legacy-pro25 分别映射到 gemini-3.1-flash-tts-preview、gemini-2.5-pro-preview-tts 和 gemini-2.5-flash-preview-tts。Google 的弃用页面(于 2026-10-12 核查)列出的最早停用日期为 2026-11-17,因此不要将它们用于新工作。开始处理前,请在 --dry-run --json 输出中确认解析后的模型 ID。

3.8 别名已通过离线 SDK 模式和 WAV 解析检查;通过身份验证后的可用性和语音质量仍需通过服务提供商测试。使用 3.8 时,请传入逐字稿,不要嵌入旁白指示。Dialogue 必须使用明确的 Speaker1: 和 Speaker2: 行;辅助程序不会推断说话人。费用估算采用截至 12 月 31 日经过核实的 2026 年费率,以及从 1 月 1 日起公布的 2027 年费率。这些仍是估算,并非账单报价。

步骤 6:交付

向用户提供结果:

  1. 文件路径:音频的保存位置
  2. 时长:便于阅读的格式(例如“3:42”)
  3. 嵌入代码:可直接粘贴的 HTML5 audio 标签
  4. 费用:预估 API 费用
  5. 放置建议:建议在博客文章中的插入位置

嵌入指南

标准 HTML(Hugo、Jekyll、静态网站)
<audio controls preload="metadata">
  <source src="audio/post-slug.mp3" type="audio/mpeg">
  Your browser does not support the audio element.
</audio>
MDX(Next.js、Gatsby)
<audio controls preload="metadata">
  <source src="/audio/post-slug.mp3" type="audio/mpeg" />
</audio>
WordPress
[audio src="audio/post-slug.mp3"]
放置位置

将音频播放器插入引言之后(第一个 H2 标题下方),或放在文章最顶部,并添加标签:“收听本文”或“音频版本”。

内部 API(用于 blog-write)

从 blog-write 内部调用时:

输入:

  • text:准备好的文本(已由 Claude 清理)
  • voice:语音名称(默认:Charon)
  • voice2:对话中的第二种语音(可选)
  • model:flash38(新任务的默认值)或 flash-lite38;旧版别名(flash、flash31、pro、legacy-*)最早将于 2026-11-17 停用
  • output_path:保存文件的位置

输出:

### Audio Narration
- **Path:** /path/to/audio/post-slug.mp3
- **Duration:** 3:42
- **Voice:** Charon
- **Embed:** `<audio controls preload="metadata"><source src="audio/post-slug.mp3" type="audio/mpeg"></audio>`

**优雅回退:**如果未设置 GOOGLE_AI_API_KEY 和 GEMINI_API_KEY,或用户拒绝费用确认,则立即返回,不报错,并向调用方的最终摘要提供一行跳过说明。写作工作流会在没有音频的情况下继续。音频生成不可用时,绝不要阻止 blog-write。

错误处理

错误解决方法
未设置 API 密钥(GOOGLE_AI_API_KEY 或 GEMINI_API_KEY)在 https://aistudio.google.com/apikey 获取密钥
未找到 FFmpeg回退为 WAV 输出。告知用户;不要替他们安装。
请求过多等待并重试。在 https://aistudio.google.com/rate-limit 查看限制
文本过长(>8,192 个输入 token)拆分为约 7,800 个 token 的片段;脚本会对准备好的文本分块并拼接,每次运行最多处理 --max-chunks(默认值为 12)个块。超过上限时,停止并在提高上限前询问用户
未知语音名称运行 /blog audio voices 查看有效选项
API 错误检查密钥有效性和模型可用性
API 密钥缺失(内部调用)返回一行跳过说明:写作工作流将继续并报告此情况

参考文档

按需加载:启动时不要加载全部内容:

  • ${CLAUDE_SKILL_DIR}/references/voices.md:完整的 30 种语音目录、按内容类型划分的推荐及对话配对

评论

支持 Markdown