别再熬夜做 PPT 了!输入一个主题,AI 帮你把整套幻灯片做好,还能随便改字

1. 一句话:这是要做什么?

你有没有过这种经历:老板丢来一个主题,让你今晚出一套 PPT。你打开 PowerPoint,从空白页开始,一页一页排版、调字号、找配图......两小时过去了,才做了 5 页。

我们想做一个新东西,让这件事变得像「点外卖」一样简单:

你只要输入一个主题、或者丢进来一份文档,AI 就帮你把整套幻灯片生成好。生成之后,你可以在网页里像用 PowerPoint 一样自由编辑,改字、挪框、换图都行。最后,一键导出成能继续编辑的 .pptx 文件,或者发给别人看的 .pdf。

简单说:以前是「PPTX 进 → 视频出」,这次是「内容进 → PPTX 出」。我们不做配音、不做数字人讲解,就专注做好两件事:让你编辑得爽,导出得准。


2. 为什么我们自己造轮子,不直接用现成的?

你可能想问:网上不是有很多开源工具吗?直接拿来用不就行了?

我们认真调研了一圈,结论是:能用的零件我们都有,缺的那一环,外面要么是坑、要么是锁。

2.1 三条路,各有各的坑

市面上做「AI 生成 PPT」的,基本就三条技术路线:

路线 听起来 实际体验
A. 网页排版 → 转成 PPT 排版最自由,想怎么摆怎么摆 转换容易错位,一页好看,下一页就乱了
B. 套模板 → 填内容 最稳,不容易出错 视觉中规中矩,但胜在「真能编辑」
C. 生成一张图 → 拆成图层 图最好看,还能「选中文字」 是假的!字和背景是两层贴上去的,一放大就重影,改一个字都费劲

路线 C 最迷惑人------它生成的图确实漂亮,但「可编辑」是事后硬拆出来的,就像把一张照片里的字「抠」出来,看着能选,其实一改就露馅。这种方案适合「只要好看、能改几个字」的场景,当不了正经产品的地基。

2.2 两个必须避开的「坑」

调研时我们还发现两个大坑,差点踩进去:

坑一:大厂官方的 PPT 生成工具,居然不是开源的。 有个知名 AI 公司官方出的 PPT 生成代码,看着很香,但它的授权协议明确写了:不能商用、不能复制、不能改、不能分发。我们做的是正经商业产品,碰都不能碰。

坑二:一个很火的 9000 星开源项目,核心功能是「锁起来」的。 它表面上是开源的,但真正负责「把网页转成 PPT」的核心代码,是编译好的、看不到源码的二进制文件。也就是说,最关键的「可编辑」那一环,恰恰是人家藏起来不给你看的。

结论: 我们自己手里已经有 80% 的零件(导出工具、渲染引擎、账号体系都有了),唯一缺的那一环,外面要么是坑、要么是锁。所以,自己造。


3. 我们是怎么设计的?几个关键决定

这一节是这篇文章的「干货」,但我会尽量用人话讲。这几个决定,直接决定了这个产品好不好用、能不能做好。

3.1 关键决定一:AI 只负责「想」,不负责「画」

很多人以为 AI 生成 PPT 是 AI 直接在一张白纸上画格子、写字。如果真这么做,出来的东西一定是灾难:字叠在一起、跑出页面、字号忽大忽小。

我们的做法是分工明确:

  • AI 只做两件事:① 想出这一页写什么内容(标题、要点、数据);② 决定这一页用什么版式(比如「大标题 + 三张卡片」还是「左边图、右边文字」)。
  • 一个「排版引擎」负责把版式变成精确的坐标,像搭积木一样,把 AI 想好的内容稳稳地放到页面上。

这样,AI 负责「聪明」,排版引擎负责「靠谱」。而且,排版引擎只在生成初稿时起作用,生成之后,你想怎么拖、怎么改,完全自由。

3.2 关键决定二:让「一键换风格」成为可能

你有没有想过,为什么很多 PPT 工具换主题色,换完总有几个地方颜色不对?

因为很多工具存的是「这个字是 24 号、这个颜色是 #1a1a1a」这种写死的数值。换风格的时候,它得从数值反推「这个字是标题还是正文」,推不准就换不干净。

我们的做法是:每个元素不存「具体长什么样」,而是存「它是什么角色」。比如「这是标题」「这是正文」「这是卡片标题」。换风格的时候,系统只要把「标题」对应的新样式套上去,就完事了。你手动改过的地方,单独存一份「覆盖记录」,不会被换风格冲掉。

一句话:我们存「语义」,不存「像素」。 这是「一键换风格」能不能做成的分水岭。

3.3 关键决定三:模板不是「一整页」,而是「积木」

传统 PPT 模板是「一整页一整页」的,比如「模板 A 的第 3 页长这样」。这种模板的坏处是:每加一套新风格,所有页面都要重新画一遍,维护成本爆炸,而且用户改不动。

我们的做法是拆积木:

  • 风格(比如商务蓝、科技暗色、杂志风)------ 5 到 10 套,用户选。
  • 版式组件(比如标题、三卡、对比、时间线)------ 25 到 40 个,排版引擎自动选。

用户看到的「模板」= 风格 × 组件。10 套风格 × 30 个组件,视觉上像几百套模板,但我们的维护量只是 10 + 30。而且用户改起来更灵活。

3.4 关键决定四:字体,我们「锁死」了

这是个很现实的问题:我们的服务器上只有 1 个中文字体,而你的电脑上有 99 个。如果服务器用它的字体生成 PDF,你打开一看,字全变了。

我们的解决方案是:生成端只允许用一套白名单字体(思源黑体,免费、可商用、可嵌入),服务器也装上它。这样:

  • 导出的 PDF 是100% 保真的,因为是在服务器渲染的,不依赖你电脑的字体。
  • 导出的 PPTX 里,如果你电脑没装思源黑体,会自动用系统默认的黑体(微软雅黑/苹方)替代------都是黑体,观感非常接近,是代价最小的选择。

代价是:你不能在生成端随便换字体。这是主动放弃,我们会写进产品说明。

3.5 关键决定五:质量检查,只查「结构」,不查「像素」

生成完 PPT,我们要检查它好不好看。但这里有个系统性的难题:服务器渲染的字形,和你电脑上渲染的字形,天生就有细微差别。所以,我们不追求「逐像素相同」,只检查「结构性错误」:

我们能查 我们查不了
元素有没有重叠 文字实际断行位置
有没有跑出页面边界 行距的像素级差异
文字有没有溢出容器 你电脑上的最终观感
图片有没有缺失、变形

唯一 100% 保真的交付格式是 PDF。PPTX 的保真度天花板就是「结构正确 + 字体替换后观感接近」。

3.6 关键决定六:导出不排队

我们的服务器上,可能同时有一个 90 分钟的数字人渲染任务在跑。如果用户这时候点「导出 PPTX」,不能让它排在那个大任务后面等 90 分钟。

所以,我们给「导出」单独开一条快速通道,并发数卡在 1-2 个。反正导出是秒级任务,排队也没感觉,但能防止一群人同时导出把服务器挤爆。

3.7 关键决定七:只做「单向导出」

「在网页里编辑」和「在 PowerPoint 里编辑」是两件事。我们只做从网页导出到 PPTX,不做「你在 PowerPoint 里改完再传回来同步」------那是个无底洞,我们不做。


4. 这个产品到底能做到什么?边界在哪?

4.1 能做到的

生成

  • 输入:主题 / 大纲 / 上传文档(doc、pdf、txt)→ 一次出整套
  • 版式:由组件库决定,排版引擎按内容量自动选
  • 配图:AI 生图 / 图库 / 用户上传
  • 风格:一键换配色与字体方案

编辑

  • 自由画布:拖拽、缩放、旋转、栅格吸附、参考线
  • 图层:文字、图片、形状、图标、线段
  • 页:新增 / 删除 / 复制 / 排序
  • 文本:字号、颜色、粗斜体、对齐、行距、项目符号
  • 图片:上传、裁剪、圆角、替换
  • 图层树:层级、锁定、隐藏、编组
  • 撤销重做、对齐分布、备注栏

导出

  • .pptx:原生文本框 + 形状 + 图片,能改字、能挪框、能换图
  • .pdf、每页 PNG

4.2 打折扣的(能做,但别期待满分)

能力 现实 原因
复杂视觉(渐变、阴影、混合模式) 降级成图片层。看着对,但在 PowerPoint 里改不了 PPTX 没有对应原语
图表 简单图表可做原生;定制样式退回图片 工具库图表 API 有限
表格 基础表格可以;合并单元格、条件格式不行 同上
导出保真 「看着差不多」,不是逐像素相同 PowerPoint 与浏览器对换行、行距的计算本就不同
字体 只能给白名单 不锁死就必然错位
主题 / 母版 能做 token 级主题,做不了 PowerPoint 的 Slide Master 继承 概念映射不完整

4.3 做不到的(再努力也绕不过)

A. PPTX 格式的天花板

  1. 动画与切换效果 ------ 工具库不支持创建
  2. SmartArt ------ 同上
  3. 字体嵌入 ------ 授权问题
  4. 公式(OMML)

→ 这四项只有一条出路:商业授权组件。要不要为了动画买它,是纯商业决定。

B. 架构上明确不做的

  1. 用户上传 PPTX 反解成可编辑图层
  2. 与 PowerPoint 双向同步
  3. 多人实时协作(技术上能做,但工作量巨大,可后加)

4.4 产品文案的红线

别写「导出的 PPT 可以随意编辑」。 用户一试形状和动画就会觉得被骗。

准确说法:「导出的 PPTX 里,文字都能直接改」。


5. 我们打算怎么把它做出来?

5.1 模块划分

模块 做什么
编辑器页面 矢量画布编辑器 + 风格/版式面板
渲染层 组件库(25--40 个版式组件)
主题 token 表,5--10 套
后端 增删改查 + 生成编排 + 导出派发
排版引擎 AI 内容 + 版式意图 → 精确坐标
导出器 内部模型 → pptx
QA 环 生成侧回渲比对

5.2 核心数据模型

设计空间统一 1920×1080 。换算干净:导出时 pt = px / 2。

jsonc 复制代码
// Deck
{
  "id": "...",
  "title": "...",
  "themeId": "business-blue",
  "designW": 1920, "designH": 1080,
  "slides": [ /* Slide */ ]
}

// Slide
{
  "id": "...",
  "index": 0,
  "layout": "three-cards",          // 版式组件名,用于「换版式」
  "background": { "token": "bg-base" },   // 或 { "image": "oss://..." }
  "notes": "这一页的讲稿",
  "layers": [ /* Layer */ ]
}

// Layer ------ 注意这里只有 token 引用,没有绝对样式
{
  "id": "...",
  "kind": "text" | "image" | "shape",
  "role": "title" | "body" | "caption" | "card-title",
  "box": { "x": 120, "y": 80, "w": 800, "h": 120 },
  "rotation": 0,
  "z": 3,
  "locked": false,
  "visible": true,

  "style": {                         // 全部是 token / 刻度引用
    "colorToken": "fg-primary",
    "fontToken": "font-display",
    "sizeStep": 3,                   // 字号刻度,不是 px
    "weight": "bold",
    "align": "left",
    "lineHeight": 1.4
  },
  "overrides": { },                  // 用户手改,覆盖 token

  "text": "...",                     // kind = text
  "src": "oss://...",                // kind = image
  "shape": "rounded-rect"            // kind = shape
}

主题 token 表(每套风格一份):

jsonc 复制代码
{
  "id": "business-blue",
  "colors": {
    "bg-base": "#ffffff", "bg-accent": "#f1f5f9",
    "fg-primary": "#0f172a", "fg-secondary": "#64748b",
    "brand": "#2563eb", "brand-fg": "#ffffff"
  },
  "fonts": { "font-display": "Source Han Sans", "font-body": "Source Han Sans" },
  "scale":  { "size-steps": [14, 18, 24, 32, 44, 60], "space-steps": [8,16,24,40,64] },
  "shape":  { "radius": 12, "shadow": "sm" }
}

5.3 落库

沿用现有「整体保存一页」的模式:

bash 复制代码
ppt_deck   (id, user_id, title, theme_id, status, version, created_at, updated_at)
ppt_slide  (id, deck_id, idx, layout, background, notes, layers jsonb, version)
  • layers 存 jsonb,整页保存,不拆表。编辑器自动保存本来就是一页一提交。
  • 写 jsonb 必须显式转型 ?::jsonb。
  • 用 SimpleJdbcInsert 时必须指定 usingColumns,否则缺列会被绑成 NULL。
  • DDL 无迁移框架,需手动 ssh + psql 应用。

5.4 接口

bash 复制代码
POST   /deck/create            生成整套(异步,返回 taskId)
POST   /deck/get               取整套
POST   /deck/update_slide      保存单页(整页 layers)
POST   /deck/add_slide         新增页
POST   /deck/delete_slide      删除页
POST   /deck/reorder_slides    页排序
POST   /deck/apply_theme       换风格(只换 themeId,前端重渲染)
POST   /deck/relayout_slide    单页换版式(重跑排版引擎)
POST   /deck/export            { deckId, format: pptx | pdf | png }
GET    /deck/themes            风格列表

5.5 导出映射

内部模型 PPTX
box.x/y/w/h(1920 设计 px) Inches(px / 144) ------ 1px = 1/144 in,1920px = 13.333in
sizeStep → scale.size-steps[step] Pt(px / 2)
kind: text add_textbox,关闭 autofit,word_wrap = True
kind: image add_picture
kind: shape add_shape(圆角矩形 / 椭圆 / 直线)
colorToken 查主题表 → RGBColor
fontToken 写字体名(白名单)。同时设 latin + eastasian,主题字体也一并设
复杂视觉层 降级为图片层

两个 python-pptx 的坑

  1. 中文字体要写三处。 run.font.name 只写 <a:latin>,中文会退回主题默认字体。必须额外写 <a:ea> / <a:cs>(东亚字体是 <a:ea>),且顺序是 latin → ea → cs。

  2. 空 <a:effectLst/> 挡不住 LibreOffice 的投影。 python-pptx 的 add_shape / add_connector

相关推荐
吴凡wudianmei1 小时前
每调一次模型都花钱?如何用工程手段把调用压到最少?
前端·后端·架构
李元_霸1 小时前
基于 AI 的 Web 与 App 端到端测试实践
前端·人工智能
欣欣之王来了1 小时前
Vue3项目脚手架:Vite vs Vue CLI怎么选?
前端·学习·架构·项目·vue3教程
用户2788607285671 小时前
别把 tool.completed 当成业务成功:AI 工具权限审计的四层事件链
前端
陆柒1452 小时前
跟着 Webpack 配置学习前端工程化
前端
用户6353300254792 小时前
Day 1|HTML5:一个商城首页的骨架,从 DOCTYPE 到语义化
前端
平凡的阿泽2 小时前
我用 Trae 实现了AI辩论赛
前端
对空六课2 小时前
指标口径生效时间的版本查询实现
大数据·服务器·前端·算法·数据分析
对空六课2 小时前
RFM分层边界变化的回溯计算
大数据·服务器·前端·数据库·人工智能·算法·数据分析