PDF 转可编辑 PPT
这个技能解决什么
市面上的 PDF→PPT 只能导出整页图片:不能改字、不能换色、不能挪位置。
本技能按原版式重建:抽取 PDF 的文本、矢量矩形、图片与坐标 → 用 python-pptx
逐个画成原生元素 → 用近似渲染器自检 → 交付可直接编辑的 .pptx。
可编辑性分级(必须做到 1–3)
| 级别 | 元素 | 做法 |
|---|---|---|
| 1 | 文字 | 原生文本框 / 形状文字,逐段可改,字号颜色行距保留 |
| 2 | 图形 | 原生形状:矩形、圆、六边形、V 形箭头、方括号(freeform)、色带 |
| 3 | 表格 | 原生 pptx 表格,可增删行列 |
| 4 | 素材 | 背景纹理、logo、真实照片、截图 —— 保留为图片(它们是素材不是版式) |
工作流
第 0 步:探针(必做,不要先看 35 页图)
python scripts/pdf_probe.py "<input.pdf>" -o work/probe
产出 text.txt(纯文本)、layout.json(逐行 bbox/字号/颜色)、pages/(位图)、
montage/(3×3 拼图)、images/(去重图片,含透明通道)、profile.json。
先读 profile.json 和 text.txt,用拼图看整体风格;只在个别页需要看细节时才读单页
pages/pXX.png。这一步能把 vision 调用压到最低。
从 profile.json 取四个常量:
- suggest_pptx_pt → 画布尺寸(16:9 一般是 960×540)
- recurring_images → 哪个 xref 是背景(bbox 面积大)、哪个是 logo(右上角小图)
- title_size → 标题字号;body_size → 正文基准
- fill_colors → 主色/辅色(前 3 个基本就是主题色)
第 1 步:拆版式,列清单
按页写一张对照表(可写在临时 md 里):
页 | 类型 | 原文案 | 配方
1 | 封面 | ... | recipes §1
2 | 目录 5 项 | ... | recipes §2
4 | 定义 + 分组树 | ... | recipes §4
...
类型归到这些类:封面 / 目录 / 金句定义 / 法条引用 / 分组树 / 时间线 / 步骤条 /
步骤卡 / 编号网格 / 圆形步骤链 / 色条清单 / 双栏对比 / 对比表 / 密排文字 / 测评 / 结尾。
原文案一字不改。发现原件笔误(重复释义、错别字),保留原样并在交付说明里单独提示,
不要替用户改内容。
第 2 步:写 build_deck.py
import sys; sys.path.insert(0, r"<skill>/scripts")
from pptx_kit import *
按页写 s01_* … sNN_* 函数,main() 里顺序调用。每个函数只做「摆版式 + 填文案」,
复杂图形用 references/layout-recipes.md 里的配方,优先复用而不是新造。
写之前先定:
prs = new_deck(960, 540)
s = add_content(prs, "二、制定主体和内容", bg="assets/bg.png", logo="assets/logo.png")
第 3 步:渲染自检(关键质量闸门)
python scripts/render_check.py out.pptx -o preview
它做两件事:
1. 打印溢出审计(文字超出文本框、元素越界、表格单元格溢出);
2. 逐页出 PNG,用真实字体度量近似渲染,供肉眼比对。
要求:告警必须清零(误报可判断后忽略,但要在心里确认不是真溢出)。
逐页对照 PDF 原图检查:层级、对齐、颜色、断行位置。
本机没有 Office / LibreOffice 也能用;不要试图用 Kwpp.Application / PowerPoint.Application
的 COM 导出(沙箱会拦),也不要去装 LibreOffice,render_check.py 已覆盖需求。
第 4 步:交付
- 文件名用内容标题,加
_可编辑版 - 用
present_files打开 pptx - 说明三件事:页数/尺寸、可编辑性数字(文本框数、形状数、表格数)、哪些是图片素材
- 列出原件里的笔误(如有),说明"未擅自改动"
硬性要求
- 禁止整页截图;禁止把文字转成曲线;禁止把表格画成矩形拼块。
- 中文字体必须同时写
a:latin和a:ea(pptx_kit.set_run已处理),否则中文会掉回宋体。 - 所有形状
shadow.inherit = False(add_shape已处理)。 - 标题区固定在
x=30..730居中,右侧 186pt 留给 logo;≥18 字的标题用 36pt 会到 722,别再右移。 - 文本框高度按「行数 × 字号 × 1.32 × 行距」留 10% 余量。
常见坑
| 现象 | 原因 / 解法 |
|---|---|
| 形状全带灰边阴影 | 没关 shadow.inherit;add_shape 已关 |
| 中文变宋体 | 只设了 a:latin,补 a:ea typeface |
方括号画成 { |
花括号字形完全不对,必须用 add_bracket(freeform 折线) |
| 竖排文字不竖 | bodyPr vert="eaVert" 才生效;rotation 是另一回事 |
| 表格四条边没线 | python-pptx 不暴露边框,须手写 a:lnL/lnR/lnT/lnB 并插到 tcPr 最前 |
| 目录标签压住六边形 | 标签宽度按 字号×字数 估,左右各留 6pt |
| 密排页溢出 | 用 fit_size(text, w, h) 反算字号,低于 10.5 就拆页 |
| 提取的 logo 黑底 | JPEG+SMask 要 Pixmap(Pixmap(pix,0), mask) 合成,pdf_probe 已处理 |
| 文件体积大 | 每页重复贴背景/logo 是主因;20 页约 0.4MB,可接受。要更小就只在首页贴 |
文件索引
scripts/pdf_probe.py— PDF 探针,产出文本/坐标/图片/配色画像scripts/pptx_kit.py— 原语库:文本、形状、方括号、表格、竖排、字号自适应scripts/render_check.py— 无 Office 环境的渲染自检 + 溢出审计references/layout-recipes.md— 16 类版式的几何参数与代码(写版式前必读)
验收清单
- [ ]
render_check.py零告警 - [ ] 页数与原 PDF 一致
- [ ] 随机抽 3 页,双击文字能改、拖动能移、改字号不断行
- [ ] 表格是真表格(点进去有行列)
- [ ] 无整页截图
- [ ] 原文案逐字一致(含原有笔误,另行提示)