关于 glmv-pdf-to-ppt
glmv-pdf-to-ppt 是将 PDF 转为多页 HTML 演示文稿的技能,面向需要把论文或其他文档整理成幻灯片的场景。它先逐页读取并规划内容,再裁剪本地图片、逐页生成 HTML,并输出摘要。
主要功能
- 01按顺序读取 PDF 页面
- 02生成结构化幻灯片大纲
- 03本地裁剪 PDF 页面图像
- 04逐页生成 HTML 幻灯片
- 05生成 Markdown 摘要
适用场景
- 01将论文 PDF 整理成演示文稿
- 02把文档内容转换为 HTML 幻灯片
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ zai-org/ glm-skills --skill glmv-pdf-to-ppt安装后在 Claude Code 中输入/glmv-pdf-to-ppt确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
.DS_Storescripts/crop.pygenerate_slide.pypdf_to_images.py详细介绍
PDF → HTML PPT 技能
将任意 PDF 转换为多页 HTML 演示文稿。页面会以 120 DPI 转换为图像,随后按顺序阅读以理解内容,然后保存结构化的 outline.json,在本地裁剪图像(不会上传到云端),逐页渲染幻灯片,最后生成 summary.md。
脚本位于: {SKILL_DIR}/scripts/
依赖项
Python 包(安装一次即可):
pip install pymupdf pillow
系统工具:curl(macOS/Linux 上已预装)。
适用场景
当用户要求根据 PDF 制作幻灯片或演示文稿时触发,例如: “根据 PDF 制作 PPT”、“将 PDF 转换为幻灯片”、“根据这篇论文创建演示文稿”、“根据pdf做ppt”、“根据论文做幻灯片”、“做PPT”、“做幻灯片”、“生成演示文稿”、“把这个pdf转成ppt”,或任何类似的中文或英文意图。
输出目录约定
所有输出均放在 {WORKSPACE}/ppt/<pdf_stem>_<timestamp>/ 下:
ppt/
└── <pdf_stem>_<timestamp>/
├── outline.json ← structured slide plan (SlidesPlan schema)
├── crops/ ← locally-saved cropped images
│ ├── slide3_method_crop.png
│ └── slide5_results_crop.png
├── slide_01.html
├── slide_02.html
├── ...
└── summary.md ← final summary document
<pdf_stem>= 不带扩展名的 PDF 文件名<timestamp>= 格式为YYYYMMDD_HHMMSS(例如20240119_143022)- 裁剪后的图像放在
crops/子文件夹中 - 每张幻灯片 HTML 均通过相对路径
crops/<name>.png引用图像
输入
$ARGUMENTS 是 PDF 文件的路径(本地路径)或 HTTP/HTTPS URL。
- 如果用户提供 URL:先用 curl 下载,然后再转换
- 如果用户提供 本地 PDF 路径:直接转换
工作流
阶段 0 — 创建输出目录
计算输出路径:
import os, datetime
pdf_stem = os.path.splitext(os.path.basename(pdf_path))[0]
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
out_dir = os.path.join(workspace, "ppt", f"{pdf_stem}_{timestamp}")
立即创建该目录:
mkdir -p "<out_dir>/crops"
记录 out_dir,后续所有阶段均使用该路径。
阶段 1 — 将 PDF 页面转换为图像(DPI 120)
如果输入是 URL,先下载:
pdf_stem=$(basename "$ARGUMENTS" .pdf)
curl -L -o "/tmp/${pdf_stem}.pdf" "$ARGUMENTS"
然后转换(传入下载后的路径或原始本地路径):
python {SKILL_DIR}/scripts/pdf_to_images.py "<pdf_path>" --dpi 120
JSON 输出到 stdout:
[{"page": 1, "path": "/abs/path/page_001.png"}, ...]
解析并保存完整的 page → path 映射。这些本地路径用于查看页面,并作为 crop.py 的 --path 输入。
阶段 2 — 按顺序阅读所有页面
在规划任何内容之前,依次查看所有页面图像。此处的目标只是理解文档:掌握其整体结构、内容、图表和论点。
阅读时,记录:
- 各页面上出现的图、图表或表格
- 整体脉络(论文的“引言 → 方法 → 结果 → 结论”,或其他文档类型的逻辑结构)
- 值得裁剪用于幻灯片的候选视觉素材(页码 + 大致区域)
暂时不要规划或撰写幻灯片——先阅读并理解所有页面。
阶段 3 — 规划大纲并保存 outline.json
阅读完所有页面后,规划 8–15 张幻灯片(非学术类文档可灵活调整)。
| 幻灯片 | 常见用途 |
|---|---|
| 1 | 标题、作者、所属机构、会议/期刊及年份 |
| 2 | 动机 / 问题陈述 |
| 3 | 相关工作(简述) |
| 4–N-2 | 方法 / 核心贡献(每张幻灯片介绍一个概念) |
| N-1 | 结果与实验 |
| N | 结论与未来工作 |
对于每张需要视觉素材的幻灯片,请确定:
- 素材来自哪一页(阶段 1 中的本地页面路径)
- 描述素材所展示的内容,以及它为何适用于这张幻灯片
将大纲保存为 <out_dir>/outline.json,并严格使用以下架构:
{
"presentation_title": "Paper Title Here",
"lang": "Chinese",
"total_slides": 10,
"slides_plan": [
{
"slide_index": 1,
"title": "Slide Title",
"main_content": "Key points and text content for this slide",
"template_id": null,
"required_crops": [
{
"url": "<page_image_url_from_phase1>",
"visual_description": "Figure 3: architecture diagram showing encoder-decoder",
"usage_reason": "Illustrates the core model structure for slide 4"
}
]
}
]
}
字段说明:
-
lang:"Chinese"或"English",与 PDF 语言一致 -
template_id:始终为null -
required_crops:如果该幻灯片不需要图像,则为空数组[] -
每个裁剪项中的
url:源页面图像的本地文件路径(来自阶段 1 的path字段),这是 crop.py 将打开并从中裁剪图像的路径 -
visual_description:描述视觉素材的内容;如有图表/表格编号,也应注明 -
usage_reason:说明该视觉素材为何适用于这张幻灯片 -
对于需要裁剪的图像,注明大致区域——确切的裁剪框将在阶段 4 中确定
使用 Write 工具将 outline.json 写入 <out_dir>/outline.json。
阶段 4 — 裁剪所需图片(定位 + 子 Agent)
重要:必须使用 Agent 工具将所有裁剪任务委派给一个干净的子 Agent。 到此阶段,你的上下文已经很长(包含所有页面图片和大纲),这会降低视觉坐标的准确性。只接收目标图片的新子 Agent 能生成精确得多的坐标。
重要:必须使用提供的 {SKILL_DIR}/scripts/crop.py 脚本裁剪所有图片。不得编写自己的裁剪代码,不得直接使用 PIL/Pillow,也不得使用其他方法。
读取 outline.json。收集所有所需的裁剪内容,然后针对每个源页面启动一个子 Agent(如果页面不同,也可以针对每个裁剪启动一个子 Agent)。子 Agent 使用定位式定位——查看图片、找到目标元素,并输出以 0–999 归一化坐标表示的精确边界框。
按如下方式使用 Agent 工具:
Agent tool call:
description: "Grounding crop page N"
prompt: |
You are a visual grounding and cropping assistant. Your task is to precisely
locate specified visual elements in a page image and crop them out.
## Grounding method
Use visual grounding to locate each target:
1. Read the source image using the Read tool to view it
2. Identify the target element described below
3. Determine its bounding box as normalized coordinates in the 0–999 range:
- 0 = left/top edge of the image
- 999 = right/bottom edge of the image
- These are thousandths, NOT pixels, NOT percentages (0–100)
- Format: [x1, y1, x2, y2] where (x1,y1) is top-left, (x2,y2) is bottom-right
- Example: [0, 0, 500, 500] = top-left quarter of the image
4. Be precise: tightly bound the target element with a small margin (~10–20 units)
around it. Do NOT crop too wide or too narrow.
## Source image
<page_image_path>
## Crops needed
For each crop below, first do grounding (locate the element), then crop:
1. Name: "slide<N>_<descriptive_name>"
Target: "<visual_description from outline.json>"
Context: "<usage_reason from outline.json>"
## Crop command
After determining the bounding box [X1, Y1, X2, Y2] for each target, run:
```bash
python <SKILL_DIR>/scripts/crop.py \
--path "<page_image_path>" \
--box X1 Y1 X2 Y2 \
--name "<crop_name>" \
--out-dir "<out_dir>/crops"
```
## Verification
After each crop, READ the output image to visually verify the correct region
was captured. If the crop missed the target or is too wide/narrow, adjust the
coordinates and re-run crop.py.
## Output
Report the final results as a list:
- crop_name: <name>, file: <output_filename>, box: [X1, Y1, X2, Y2]
将 <page_image_path>、<SKILL_DIR>、<out_dir> 和裁剪详情替换为上下文中的实际值。
crop.py 脚本会输出 JSON:{"path": "/abs/path/slide3_method_crop.png"}
收集所有子 Agent 的结果,并建立映射:slide_index → [crop filename, ...],以便在 HTML 中引用。文件名格式为 <name>_crop.png。
尽可能并行启动处理不同页面的子 Agent。 等待所有任务完成后再继续。
阶段 5 — 测量裁剪后图片的尺寸
裁剪后,获取像素尺寸:
python3 -c "
from PIL import Image; import os, json
d = '<out_dir>/crops'
sizes = {}
for f in sorted(os.listdir(d)):
if f.endswith('.png'):
w, h = Image.open(os.path.join(d, f)).size
sizes[f] = {'width': w, 'height': h, 'aspect': round(w/h, 2)}
print(json.dumps(sizes, indent=2))
"
使用宽高比为每张幻灯片选择布局:
| 宽高比 | 布局建议 |
|---|---|
| < 0.7(高而窄) | text + image 并排布局——图片设置 max-height: 600px |
| 0.7 – 1.3(接近正方形) | text + image——图片约占 50% 宽度 |
| > 1.3(宽图) | 图片放在顶部或底部,文本放在上方或下方 |
| > 2.0(特别宽,例如表格) | full-image——横跨完整的 1280px 宽度,说明文字放在下方 |
阶段 6 — 逐张生成幻灯片
对于每张幻灯片,编写 HTML、保存到临时文件,然后调用 generate_slide.py。
步骤 A — 编写 HTML 到 /tmp/slide_N.html
- 所有
<img src="...">都必须使用相对路径:crops/<name>_crop.png - 不要为裁剪后的图片使用绝对路径或 URL
- 导航基于点击区域——无需按钮:
- 点击幻灯片左半部分可跳转到上一张
- 点击幻灯片右半部分可跳转到下一张
- 在第 1 张幻灯片上,点击左侧无操作;在最后一张幻灯片上,点击右侧无操作
- 键盘
←/→箭头键也可导航 - 使用两个透明的
<div>覆盖层覆盖幻灯片画布的左右两半,并将其绝对定位
步骤 B — 保存幻灯片:
python {SKILL_DIR}/scripts/generate_slide.py \
--html-file /tmp/slide_N.html \
--index N \
--total <total> \
--title "<presentation title>" \
--out-dir "<out_dir>/"
重复以上步骤,直到保存所有幻灯片。
阶段 7 — 生成 summary.md
使用与幻灯片相同的语言(outline.json 中的 lang),编写 <out_dir>/summary.md。
包含:
- 文档标题和基本信息(适用时包括作者、会议或期刊、年份)
- 简短摘要或概述(2–3 句话)
- 逐张幻灯片的内容表:幻灯片编号、标题、1–2 句话的摘要
- 主要贡献或要点(项目符号列表)
- 指向
slide_01.html的链接,用于打开第一张幻灯片
示例结构:
# [Presentation Title]
> **来源 / Source:** [PDF filename] | **语言 / Language:** Chinese | **幻灯片数 / Slides:** 10
## 摘要
[2-3 sentence overview]
## 幻灯片概览
| # | 标题 | 主要内容 |
|---|------|---------|
| 1 | 标题页 | ... |
...
## 主要贡献
- ...
## 📂 打开演示文稿
[▶ 开始播放](slide_01.html)
HTML 幻灯片规范
每张幻灯片都是一个独立的 HTML 文件——完整的 <html>…</html>,仅内嵌 CSS。
**画布:**固定为 1280 × 720 px,overflow: hidden——页面不会滚动。
所有幻灯片的设计保持一致:
- 选择符合文档领域和基调的视觉风格——不限定配色或字体
- 如果用户指定了风格,就严格遵循;否则根据内容推断(例如,机器学习论文 → 简洁现代;历史报告 → 编辑风格的衬线字体;产品宣传 → 鲜明且具有品牌感)
- 所有幻灯片统一使用相同的字体、颜色和间距系统
- 每张幻灯片都显示:标题、页码(右下角)、演示文稿标题(低调地显示在页脚)
每张幻灯片的导航:
- 两个透明的可点击区域覆盖整张幻灯片的高度:左侧 50% → 上一张幻灯片,右侧 50% → 下一张幻灯片
- 在第 1 张幻灯片上,左侧区域不执行操作;在最后一张幻灯片上,右侧区域不执行操作
- 键盘
←/→箭头也可用于导航 - 无需显示按钮——可选择在边缘显示低调的
‹/›提示,并在悬停时淡入
布局模式:
title-card— 居中主视觉,大标题,下方显示作者/会议text-only— 结构化项目符号列表,最多 5–6 项,留白充足text + image— 图片置于右侧或左侧,文字置于另一侧full-image— 图片铺满画布,仅叠加少量文字grid— 2×2 或 3 列图片,并配有说明文字
图片:
- 使用相对路径:
crops/<name>_crop.png - 添加
style="object-fit: contain; max-width: 100%; max-height: 100%;" - 在图片下方添加小号斜体说明文字
请勿:
- 使用外部 JS 框架或图标 CDN
- 使用占位图/素材库图片——仅使用裁剪后的 PDF 图片
- 生成通用的白底紫色渐变幻灯片
- 让内容超出 720px 的高度
质量检查清单
- 输出目录命名为
<pdf_stem>_<timestamp>/ - 保存了符合 SlidesPlan schema 的有效
outline.json - 所有裁剪图片均保存到
crops/(仅本地保存,不上传到云端) - 每张幻灯片均适配 1280×720,不会溢出
- 所有幻灯片的主题风格一致
- 裁剪图片通过相对路径
crops/<name>_crop.png引用 - 每张幻灯片上都能看到页码和演示文稿标题
- 左右点击区域导航正常,键盘箭头也可正常使用
-
summary.md使用正确的语言编写,并链接到slide_01.html
语言
与 PDF 语言保持一致。中文 PDF → 中文幻灯片和摘要。英文 → 英文。不要混用语言。