mcpField
G
glmv-pdf-to-ppt

glmv-pdf-to-ppt

github.com/zai-org文档处理47558 次安装28 周前更新
代码仓库

关于 glmv-pdf-to-ppt

glmv-pdf-to-ppt 是将 PDF 转为多页 HTML 演示文稿的技能,面向需要把论文或其他文档整理成幻灯片的场景。它先逐页读取并规划内容,再裁剪本地图片、逐页生成 HTML,并输出摘要。

主要功能

  1. 01按顺序读取 PDF 页面
  2. 02生成结构化幻灯片大纲
  3. 03本地裁剪 PDF 页面图像
  4. 04逐页生成 HTML 幻灯片
  5. 05生成 Markdown 摘要

适用场景

  1. 01将论文 PDF 整理成演示文稿
  2. 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_Store
scripts/
crop.py
generate_slide.py
pdf_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 → 中文幻灯片和摘要。英文 → 英文。不要混用语言。

评论

支持 Markdown