扫描版PDF转有声书

SKILL效率
效率 未标注权限 许可证不明确
安装这个技能

把扫描版 PDF(无文字层的图片型 PDF,如 Epson 扫描书稿)OCR 成文本,清洗纠错后合成为中文有声书音频;也支持复刻参考音视频的语速与停顿节奏。当用户要求"把 PDF 转成音频/有声书/朗读"、"扫描件转录"、"把书读出来"、"按这个语速/节奏读"时使用。覆盖 PDF 类型探测、PyMuPDF 渲染 + RapidOCR 中文识别、标题识别与分节、断行合并、领域术语纠错(命理/术数等形近字)、edge-tts 多音色逐句合成、停顿分级插入、ffmpeg 免安装合并、时长守恒校验全链路。

一句话选型结论

按资料字段整理

扫描版PDF转有声书是效率类的 Agent Skill,安装方式未标注,权限级别未标注,许可证不明确,有可直接复制的安装命令。技能本质是给模型读的说明书,效果取决于模型与客户端;装完先用一个小任务验证,再放进正式流程。

分类效率 安装方式未标注 权限级别未标注权限 许可证许可证不明确
累计安装 未标注 本周 未标注
GitHub 星标 未标注 仓库 未标注
下载量 未标注 技能市场下载数
权限级别 未标注权限 安装前请确认风险范围
许可证 许可证不明确 未说明

安装

未标注
在支持 Skills 的客户端里执行,装完问一句「你有哪些技能」验证
skillhub install user_321cba40/scanned-pdf-to-audiobook
  1. 1
    确认客户端支持

    确认你的客户端支持 Skills(Claude、Codex、Cursor 等),并升级到较新的版本。

  2. 2
    拿到技能文件

    执行上面的命令安装;也可以把仓库里的 SKILL.md 手动放进客户端的 skills 目录。

  3. 3
    刷新技能列表

    重新打开客户端,或刷新技能列表,让新放进来的技能被加载。

  4. 4
    验证是否生效

    问一句「你有哪些技能」,确认列表里出现它,再拿一个小任务试跑。

技能档案

效率
字段来自技能仓库与公开索引,中文说明由本站标注
作者 / 维护方user_321cba40仓库 未标注 · 版本 未标注
宿主客户端未标注技能可被这些客户端加载
安装方式未标注安装包 community
权限级别未标注权限安装前请确认风险范围
许可证未说明许可证不明确,商用前请自行确认条款
仓库可用性available技能仓库当前是否可访问
最近核验未标注上游最后核验时间 · 数据更新 1791734498
正文体量14.4 KBSKILL.md 原文大小,越大说明说明书写得越细

典型使用场景

3 类
按分类整理的常见用法,具体以 SKILL.md 为准
整理待办与日程

把零散任务收进清单,排出优先级。

批量处理重复任务

把固定动作做成模板,重复执行。

把流程写成清单

把口头流程整理成可复用的步骤。

选择建议

装之前先看这几条
按条目字段给出的判断,不替你决定用不用

值得选的地方

  • 有可直接复制的安装命令,不用自己翻文档找入口。

先想清楚的地方

  • 没有标注权限级别,实际能做什么要装好后确认。
  • 许可证不明确,商用或二次分发前先到仓库确认条款。
  • 没有做站内核验,内容以作者仓库为准。
  • 技能只是说明书,实际效果取决于模型与客户端,装完先用小任务试一遍。

更适合

  • 需要在效率场景里给模型补一套做法的人。
  • 愿意先读一遍 SKILL.md、确认它会让模型做什么的人。

不太适合

  • 对许可证要求很严、必须明确可商用的人。
  • 只想装完就自动变强、不打算看说明书的人。

同类对比

6 个同类
同分类里挑最接近的几条,字段以各自详情页为准
技能权限级别安装方式累计安装宿主客户端安装命令
扫描版PDF转有声书当前 未标注权限 未标注 未标注 未标注 有
Nano PDF 文档 联网访问 ClawHub 市场 424.9 万 OpenClaw 有
自动更新程序 浏览器控制 ClawHub 市场 296.4 万 OpenClaw 有
Gemini 助手 联网访问 ClawHub 市场 254.7 万 OpenClaw 有
word DOCX 文档 联网访问 ClawHub 市场 239.6 万 OpenClaw 有
Excel XLSX 前端 联网访问 ClawHub 市场 227.0 万 OpenClaw 有

SKILL.md 全文

14.4 KB
模型实际读到的说明书原文,来自技能仓库

扫描版 PDF → 中文有声书

把扫描书稿变成「分节 + 完整版」的有声书,并支持精确对齐参考音频的语速节奏。

核心原则(先读这几条,能省掉大部分返工)

  1. 术语纠错必须放在「段落合并之后」。OCR 会把「巳火」断成两行(上行以「已」结尾、下行以「火」开头),行级替换匹配不上,会静默漏改上百处。散文类稿件实测:行级无匹配、段落级命中 400+ 处。
  2. 标题必须自成一个「已终止」的段落。若标题末尾不补句号,下一步的拼接逻辑会把标题和紧随正文粘成一段,导致分节判据(要求整段 ≤26 字)失效、小节全部消失。
  3. 水印可能在行中间。扫描水印常与正文并成一行(…看不见了。更多最新资料微信WORK12311),只在行首判定会漏掉,水印会被 TTS 念出来。必须先 sub() 剔除片段再判断剩余内容。
  4. 规则匹配必须用 re.search,不能用 old in p。规则可能是正则(如 王(?=[癸水…])),字面子串判断永远为 False,会让整条规则被静默跳过——症状是「规则命中 0 处」但文本里明明有错字。这是最隐蔽的一类 bug,曾导致 59 处漏改。
  5. 替换表必须保持「长串优先」并做前缀冲突自检。如 己已土 必须排在 己已 之前,否则「己已土」会被当成「己巳+土」。改完表后跑一次前缀冲突检测(见 book_text.py 注释)。

适用场景与路线

用户给出 PDF 并要求转成音频。先探测类型:

python scripts/probe_pdf.py <input.pdf>
  • 输出 TEXT(有文字层)→ 直接 pypdf 提取文本,跳到「清洗」
  • 输出 IMAGE(纯图片,如 Producer: Epson Scan 2)→ 走 OCR 流程

环境准备(Windows 本机)

PY="C:/Users/<user>/.workbuddy/binaries/python/versions/3.13.12/python.exe"
"$PY" -m venv "C:/Users/<user>/.workbuddy/binaries/python/envs/default"
PIP="C:/Users/<user>/.workbuddy/binaries/python/envs/default/Scripts/python.exe"

★ 必须显式指定官方源——本机全局 pip.ini 指向的清华源已失效(报 from versions: none):

"$PIP" -m pip install --index-url https://pypi.org/simple --no-cache-dir \
    pypdf pymupdf rapidocr-onnxruntime edge-tts imageio-ffmpeg
# 需要复刻参考节奏时再加: faster-whisper
  • imageio-ffmpeg 是免安装获取 ffmpeg 的最省事途径:imageio_ffmpeg.get_ffmpeg_exe()
  • 本机 Bash 的 coreutils 不可用(ls/tail 报 command not found,exit 127)。一切读写走 Python 脚本,不要用管道。

全流程(4 步)

Step 1 — OCR

python scripts/ocr_pdf.py <input.pdf> <ocr_dir> [start] [end] [dpi]

逐页写出 pNNN.txt(已按视觉行合并、还原阅读顺序)。默认 200dpi、约 2.7 秒/页。
已存在的页自动跳过(断点续跑);FORCE=1 强制重做。

★ RapidOCR 返回结构陷阱:res 元素为 [box, text, score],且 score 是字符串。
不要用 isinstance(x, str) 去猜哪个是文本字段——会把 score 当文本。
正确写法:box, txt, sc = item[0], item[1], float(item[2])。

Step 2 — 清洗 / 纠错 / 分节(先 DRY 验证)

DRY=1 python scripts/build_audiobook.py <ocr_dir> <out_dir> \
      --pages 7 165 --book "<书名>" --page-header-key "<页眉关键片段>"

务必先跑 DRY=1。它会输出:术语纠错命中数(每条都要看)、残留可疑扫描、分节清单与各节字数,并落盘清洗后的全文。确认无误再实跑合成。

book_text.py 内含可复用的清洗内核,要点:

环节 关键做法
页眉页脚 短行含书名,或纯页码行 ^[\s\-—_·]*\d{1,3}[\s\-—_·]*$
水印 行内 sub 剔除(见核心原则 3);正则用 \S* 吞掉无空格后缀如 微信WORK12311
标题判据 分隔符必须用「非汉字非字母数字」——[^\u4e00-\u9fa5A-Za-z0-9],因 OCR 会把「、」认成「。」「.」「,」
断行合并 中文行末若无 。!?;:”』】) 则与下行直接拼接(不加空格)
标题尾码 re.sub(r'[\s\-—–..·。,,、]*\d+$', '', t)
段落级纠错 合并之后再做替换(核心原则 1)
分节 一级标题(中文数字开头)切分,过滤正文 <30 字的伪小节

★ 术语纠错表写法:长串优先、互不重叠、逐条打印命中数。

FIXES = [(&quot;王癸水&quot;, &quot;壬癸水&quot;), (&quot;丁王合&quot;, &quot;丁壬合&quot;), (&quot;甲己&quot;, &quot;甲己&quot;), (&quot;已土&quot;, &quot;己土&quot;), ...]
hits = {old: 0 for old, _ in FIXES}
for old, new in FIXES:
    if old in s:
        hits[old] += len(re.findall(old, s)); s = re.sub(old, new, s)

命中 0 说明没匹配上(多半是被前一条短串先吃掉了,或本书确无此错字)——必须回头确认,否则以为改了其实没改。脚本会单独列出「未命中规则」供判定。

★「已」是最大坑,必须逐条按上下文判定,禁用宽泛正则:

上下文 正字 例
已 + 土 己 已土→己土、戊已土→戊己土
已 + 火/金/水/木 巳 已火→巳火 ← 最高频,实测单本 100+ 处
已 + 地支字 巳 已午→巳午、已酉丑→巳酉丑
X已Y 固定搭配 巳 寅已穿→寅巳穿(实测 18+ 处)、已和申、禄在已、已为心、纳已、已向、加已、被已合、辰已空
天干 + 已 + 自合 巳 辛已自合→辛巳自合
甲 + 已 + 合 己 甲已合→甲己合(五合之一,不是甲巳合)
自已 自己 OCR 常见,须单独列规则
副词 不动 万不得已、情非得已、已经、而已、不鸣则已

⚠ 反面教训(实际踩过):用 (?&lt;=[甲乙丙丁…])已 → 巳 这类宽泛 lookbehind,
会同时造成两类错误——把「甲已合」错改成「甲巳合」,又漏掉前面是标点的「已火」。
实测一次误改产生 9 处新错、漏改 105 处。

改完必做「残留扫描」(book_text.scan_residue),按小节逐条人工判定,能同时抓出漏改与误改。命理类高频错字:王→壬、葵→癸、千→干、卵→卯、奎刚→魁罡、戍→戌、绯蚌→诽谤、羊人→阳刃、丁任→丁壬。

Step 3 — 合成

两条路线,按是否需要复刻参考节奏选:

A. 常规分块合成(默认,速度快)

python scripts/build_audiobook.py &lt;ocr_dir&gt; &lt;out_dir&gt; --pages 7 165 \
       --voice zh-CN-YunjianNeural --rate -22% --pitch -4Hz
  • 分块约 360 字,按 (?&lt;=[。!?])(?![”』】)]) 切句后累积;无标点长句按逗号硬切(180 字)
  • 并发 4 较稳;分批 40 块提交,每块重试 5 次(指数退避)
  • 崩溃救场:合成中断后用 MERGE_ONLY=&lt;临时目录&gt; ... 复用已合成块,直接进合并,省去重跑(实测省 7 分钟)

B. 逐句合成 + 分级停顿(用于精确对齐参考音频节奏)

DRY=1 python scripts/synth_rhythm.py &lt;text_file&gt; &lt;out.mp3&gt; \
      --rate -22% --gap-comma 0.22 --gap-stop 0.42 --gap-title 0.70

先 DRY 看预估的总语速与停顿占比,调到贴近参考音频再实跑。

中文男声(edge-tts):

音色 特点 参数建议
zh-CN-YunjianNeural 云健 浑厚磁性男中音,讲书首选 rate -12%~-22%, pitch -4Hz
zh-CN-YunyangNeural 云扬 新闻播音腔,稳重 rate -6%, pitch -2Hz
zh-CN-YunxiNeural 云希 年轻清朗 rate -6%
zh-TW-YunJheNeural 云哲 台湾低音 rate -8%

女声:zh-CN-XiaoxiaoNeural(温暖)、zh-CN-XiaoyiNeural(活泼)。
建议先为用户生成 4 个候选音色的试听样本(同一段正文),再批量合成。

Step 4 — 校验交付

python scripts/verify_delivery.py &lt;out_dir&gt; --sections &quot;一、五行论,二、...&quot; --asr

最重要的验收标准:分节时长之和 == 完整版时长(证明无遗漏、无重复)。
另含文件清单、异常短节告警、文本首末段与小节齐全性、manifest 参数、(--asr)抽查术语读法。

复刻参考音频的语速与节奏(量化流程)

用户给出参考音视频("按这个语速和节奏")时,按下面的量化流程做,不要凭感觉调。

1. 测参考音频

python scripts/measure_rhythm.py &lt;reference_audio_or_video&gt;

输出四组指标,后续逐项对齐:总语速(汉字/总时长×60,最可靠口径)、净语速、停顿占比、停顿中位。

2. ★ VAD 的 speech_pad_ms 陷阱(必读)

from faster_whisper.vad import get_speech_timestamps, VadOptions
ts = get_speech_timestamps(audio, VadOptions(min_silence_duration_ms=200,
                                            speech_pad_ms=0))   # ★ 必须设 0!

speech_pad_ms 默认 400,会在每段语音前后各扩展 400ms,把任何短于 800ms 的停顿全部吞掉——
实测让停顿占比从真实的 10.8% 掉到 0.0%,从而误判"音频没有停顿"。脚本已强制设 0,并用 silencedetect 交叉验证(参考音频有背景声时 silencedetect 会失效,以 VAD 为准)。

3. ★ edge-tts 每段自带 0.5–0.7s 头尾静音

逐句合成时这些会叠加:189 段实测额外多出 127s,停顿占比从预期 6% 飙到 16.3%。
必须裁剪(脚本已内置,ThreadPoolExecutor(max_workers=6) 并行约 1 分钟):

ffmpeg -i seg.mp3 -af &quot;silenceremove=start_periods=1:start_threshold=-45dB:start_silence=0.02,\
areverse,silenceremove=start_periods=1:start_threshold=-45dB:start_silence=0.02,areverse&quot; \
  -ar 24000 -ac 1 -c:a libmp3lame -b:a 48k out.mp3

4. 分级插停顿

单元末尾 静音 说明
逗号/顿号/分号 0.20–0.28s 句内换气
句号/问号/叹号 0.40–0.55s 句间停顿
小节标题 0.70–0.90s 章节留白

长句(>28 字)先在逗号处再切一刀(每段 ≤24 字),否则停顿密度不够。
静音片段规格须与语音一致:ffmpeg -f lavfi -i anullsrc=r=24000:cl=mono -t 0.25 -c:a libmp3lame -b:a 48k sil.mp3(mp3 静音约 -91dB 属正常)。

5. 经验值

  • edge-tts 逐句合成的净语速约为分块合成的 0.8 倍。rate=-20% 逐句合成净语速约 215 字/分,rate=-22% 约 200 字/分
  • 交付前回测成品,与参考逐项对齐(总语速 / 停顿占比 / 停顿中位)
  • 中文 48kbps 约 4.6 分钟/MB,250 字/分钟(用于估算)

局部返修(只重做某一节)

用户反馈"某节某个词读错了"或"这节节奏不对"时,不要全量重跑:

python scripts/fix_section.py &lt;ocr_dir&gt; &lt;out_dir&gt; --section 三、 --pages 27 34 --dry
  1. 先 --dry:调出该节文本,逐字审查(人工过一遍,不要只依赖正则)
  2. 看每条纠错规则的命中数,命中 0 的必须查明原因
  3. 单字逐处确认(已/己 会命中「万不得已」等正常词,属正常保留)
  4. 覆盖前自动备份原音频到 &lt;out_dir&gt;/_backup/
  5. 合成后用 ffmpeg 比对时长,应与原版接近(差值来自被剔除的水印行)
  6. 注意:分节音频更新后,00_全书完整版 仍是旧版;如需同步则用 MERGE_ONLY 重跑,或重跑全书

合并与产物

concat demuxer + -c copy,失败退回重编码 -ar 24000 -ac 1 -b:a 64k:

[ff, &quot;-y&quot;, &quot;-f&quot;, &quot;concat&quot;, &quot;-safe&quot;, &quot;0&quot;, &quot;-i&quot;, listfile, &quot;-c&quot;, &quot;copy&quot;, out]

list.txt 写 file &#x27;&lt;绝对路径,正斜杠&gt;&#x27;(-safe 0 允许绝对路径)。

&lt;out_dir&gt;/
  00_全书完整版_&lt;书名&gt;.mp3
  01_&lt;小节标题&gt;.mp3  ... NN_&lt;小节标题&gt;.mp3
  _全文文本.txt        清洗后全文(便于用户核对与二次利用)
  _manifest.json       书名/音色/语速/节名/时长/大小/字数
  _backup/             局部返修时的原音频备份

常见问题

现象 原因与处理
from versions: none pip 源失效,加 --index-url https://pypi.org/simple
文本全是 0.83… 这类数字 OCR 结果里 score 被当成 text,用 item[1] / float(item[2])
小节全部消失 / 只有 1 节 标题末尾未补句号,与正文粘连致分节判据失效(核心原则 2)
术语改了但没生效 在行级而非段落级替换,术语被断行拆开(核心原则 1);或用 old in p 而非 re.search,正则规则被静默跳过(核心原则 4)
某条规则命中 0 处 先怀疑核心原则 4(正则被字面判断跳过);再查是否被同前缀短串抢先(核心原则 5)
音频里念出水印 水印在行中间没被剔除(核心原则 3)
替换后出现新错字 前缀冲突:长串被短串先吃掉,调整 FIXES 顺序(长串优先)
--rate -22% 报 expected one argument argparse 把负值当选项;脚本已内置改写为 --rate=-22%,自定义脚本需自行处理
停顿占比测成 0% speech_pad_ms 默认 400 吞掉短停顿,设 0
停顿占比异常偏高 edge-tts 片段头尾静音未裁剪(约 +10 个百分点)
命令 rc=127 无输出 用了 tail/ls 等 coreutils,本机不可用,改用 Python
合成中途崩溃 MERGE_ONLY=&lt;块目录&gt; 复用已合成块直接合并

常见问题

5 问
答案由本站依据条目字段整理
扫描版PDF转有声书怎么安装?

在支持 Skills 的客户端里执行:skillhub install user_321cba40/scanned-pdf-to-audiobook。安装方式为未标注。装完刷新技能列表或重开客户端。

扫描版PDF转有声书支持哪些客户端?

资料没有标注宿主客户端,但只要客户端支持 Skills(Claude、Codex、Cursor 等),一般都能加载。

扫描版PDF转有声书权限高吗,安全吗?

权限级别为未标注权限。安装前先看它会读取或写入哪些内容。

扫描版PDF转有声书收费吗?

本站不代收费用,也没有标注具体价格。是否收费取决于技能本身和所用的模型或客户端,正式使用前按作者说明确认。

扫描版PDF转有声书用什么许可证?

许可证标注为 未说明(许可证不明确)。商用或二次分发前请到仓库确认条款原文。

热门专题

按场景挑技能
全部专题 →

技能内容以作者仓库为准;分类、权限级别与许可证状态的中文说明为中文整理,最近核验 未标注。