AI可编辑PPT产品线技术方案调研与落地思考

文章目录

    • 前言
    • 一、先看看外面那些「可编辑PPT」都怎么玩
      • [1. 三条技术路线](#1. 三条技术路线)
      • [2. 路线C的坑,得单独说](#2. 路线C的坑,得单独说)
      • [3. 两个必须知道的许可陷阱](#3. 两个必须知道的许可陷阱)
      • [4. 调研结论:一个外部仓库都不引](#4. 调研结论:一个外部仓库都不引)
    • 二、回头翻自家仓库,发现好东西还真不少
      • [1. 能直接复用的零件](#1. 能直接复用的零件)
      • [2. 不能复用的:现有编辑器压根不是PPT编辑器](#2. 不能复用的:现有编辑器压根不是PPT编辑器)
    • 三、七个决策,改起来代价最大的先定死
      • [1. 不让LLM直接吐坐标](#1. 不让LLM直接吐坐标)
      • [2. Layer存「语义角色+token」,不存绝对样式](#2. Layer存「语义角色+token」,不存绝对样式)
      • [3. 模板=风格×组件,不做「整页模板」](#3. 模板=风格×组件,不做「整页模板」)
      • [4. 字体:生成端锁死+服务器装字体](#4. 字体:生成端锁死+服务器装字体)
      • [5. 回渲QA放生成侧,只查结构性错误](#5. 回渲QA放生成侧,只查结构性错误)
      • [6. 导出走独立队列,别和渲染共用慢池](#6. 导出走独立队列,别和渲染共用慢池)
      • [7. 导出是单向投影](#7. 导出是单向投影)
    • 四、能力边界:哪些能吹,哪些只能看看
      • [1. 能做到的](#1. 能做到的)
      • [2. 打折扣的(能做,但别期待满分)](#2. 打折扣的(能做,但别期待满分))
      • [3. 做不到的](#3. 做不到的)
      • [4. 产品文案的红线](#4. 产品文案的红线)
    • 五、实施方案
      • [1. 模块划分](#1. 模块划分)
      • [2. 核心数据模型](#2. 核心数据模型)
      • [3. 落库](#3. 落库)
      • [4. 接口](#4. 接口)
      • [5. 导出映射](#5. 导出映射)
      • [6. 里程碑](#6. 里程碑)
      • [7. 机器资源](#7. 机器资源)
    • 六、风险清单

P.S. 无意间发现了一个巨牛的人工智能教程,非常通俗易懂,对AI感兴趣的朋友强烈推荐去看看, 传送门https://blog.csdn.net/qq_34419312

前言

改个PPT里的字有多难,干过的人都知道。你把文件发给客户,客户说"把第二页那个'明天'改成'后天'"。你打开一看,那是个图片。那一刻你终于理解了什么叫薛定谔的PPT------你以为你能改,打开才知道能不能。

今天聊的就是这事儿。在现有「数字人讲PPT」之外,我们准备加一条独立产品线:输入主题/文档 → 生成整套幻灯片 → 网页里自由编辑 → 导出能改字的 .pptx / .pdf。

一句话说清楚跟老产线的区别:老产线是「PPTX进,MP4出」,这条是「内容进,PPTX出」。一个是把菜端给你,一个是把菜谱给你,你自己炒。

本版不做三件事:不做TTS/讲稿配音,不做视频导出,页面上保留notes字段做纯文本存续但不接合成链路。范围就俩字:编辑、导出。

一、先看看外面那些「可编辑PPT」都怎么玩

1. 三条技术路线

路线 代表方案 视觉质量 真可编辑 稳定性
A. HTML自由排版→DOM量测→原生对象 Design-Arena/html-to-pptx、Anthropic html2pptx、DeepPresenter自由模式 最高 中(转换有损) 低,排版易错位
B. 模板槽位→结构化spec→原生对象 PPTAgent模板模式、Presenton标准管线 中 最高 高
C. 生图→逆向拆图层 gpt-image2-ppt-skills editable模式 最高 假 中

路线A:视觉最好,但转换有损,排版容易错位。属于「看着能吃,夹起来就散」。路线B:视觉一般,但稳定,真能编辑。属于「丑但实在」。路线C:视觉最好,「可编辑」最假。

2. 路线C的坑,得单独说

这条线听着最香:图好看,还能「编辑」。但它的可编辑性是事后补出来的------先生成整页图,再拆成「干净底图+文本框+形状+图片层」叠回去。字是能选了,但和底图上的原字错位,放大就重影。

这就像美颜相机。远看是个美女,放大全是糊的。拿来骗甲方行,拿来当产品底座不行。它还得配一台LibreOffice/Keynote做回渲QA,伺候成本不低。适合「要好看、能改几个字」,不适合当服务底座。

3. 两个必须知道的许可陷阱

**第一个:Anthropic官方那个pptx skill,不是开源。**人家根目录故意不放LICENSE,许可下沉到子目录。document-skills下那四本是 source-available, not open source,LICENSE里写得清清楚楚:禁止商用、复制、衍生、分发、逆向。

翻译成人话:看着是开源,其实是「只可远观,不可亵玩」。做商用服务碰了就是给自己埋雷。同仓的example-skills才是Apache 2.0,但不含pptx能力------人家把门焊得死死的。

**第二个:Presenton的导出核心闭源。**主仓Apache-2.0、9k+ star,听着很香对吧?但它的scripts/sync-presentation-export.cjs会从GitHub Releases拉一个预编译tarball进node_modules。真正的binary→OOXML转换在@presenton/export-core,源码仓只有一个README。

你看,「可编辑度」恰好是被藏起来的那一环。就像相亲,照片发的是「可编辑版本」,真人不给看。能当对标,不能当底座。

4. 调研结论:一个外部仓库都不引

理由特别朴素:我们自己已经有80%的零件,唯一缺的那一环------矢量页面模型+导出器------外面要么闭源、要么许可受限、要么架构不匹配。我们是绝对定位画布,根本不需要DOM量测那一套。

外部仓库降级成参考清单:

仓库 许可 参考什么
presenton/presenton Apache-2.0(导出核心除外) PptxPresentationModel的TS/Python双端同构设计
icip-cas/PPTAgent Apache-2.0 generate→render→review→fix自省环
Design-Arena/html-to-pptx MIT 仅当将来要做「LLM自由排版HTML」时才用

二、回头翻自家仓库,发现好东西还真不少

1. 能直接复用的零件

python-pptx在worker依赖里躺着(sse/utils/ppt_utils.py),导出器直接拿来用;LibreOffice headless在做回渲QA和PDF导出;页级派发/账单/OSS的骨架照抄;配额和冻结直接接;拖拽缩放的交互代码搬到新编辑器;逐像素验收方法从shotcraft那条线搬。

总结:家底还行,缺的不是零件,是组装。

2. 不能复用的:现有编辑器压根不是PPT编辑器

这句结论是有证据的,不是拍脑袋。src/views/ppt-detail/index.vue,它不叫PPT编辑器,叫「数字人形象版式标注器」。

(1)底图是栅格PNG。

drawBaseImage把上传的PPTX经 soffice→PDF→PyMuPDF 渲成一整页图,全屏贴上去。isCanvasBaseLayer的判据就是「图层URL==页面底图URL」。这种结构下想导出可编辑pptx?最多得到「一张整页图+几个框」。就好比你在照片上叠了几个便利贴,然后说这是可编辑文档。

(2)Layer没有排版模型。

字段就type/content/renderUrl/x/y/width/height/isAvatar/pageIndex。没有字号、字体、颜色、对齐、行距、项目符号、透明度、旋转、z-index。图层类型只有text|image|video三种。

(3)文字图层是残的。

drawTextLayer写死16px Arial纯黑,无换行、无样式。设计师看到这行代码,血压能直接拉满。好看的排版都在worker的ffmpeg overlay里------也就是说,是「画」上去的,不是「排」上去的。

(4)没有页面CRUD。

全文件搜不到addPage/deletePage/duplicatePage/movePage。页数由上传的pptx决定。你想加一页?对不起,没有这个按钮。

(5)API里零pptx导出。

ppt.ts里19个接口,产物一律是MP4/音频。

结论:新建模块,不改造。现有编辑器和目标模型正交------就像你想把自行车改成电动车,不如直接买辆新的,别折腾那俩轮子了。

三、七个决策,改起来代价最大的先定死

1. 不让LLM直接吐坐标

「网页里自由编辑」不等于「LLM自由排版像素」。你要让模型直接吐每个文本框的绝对坐标,出来必是垃圾:重叠、出界、字号乱。我见过AI画的PPT,字叠字,跟早高峰地铁似的。

正确分工:LLM只干两件事 ------①出内容(标题/要点/数据/配图语义);②选版式意图(「这页是大标题+三卡」还是「左图右文」)。确定性排版器把版式意图算成绝对坐标,按栅格落成Layer\[\]。

这跟shotcraft是同一个DNA:LLM挑组件、填props,坐标由排版器一处定死。出口仍是绝对坐标,用户接着随便拖。确定性只作用于初稿,不限制后续编辑。说白了:AI负责想,排版器负责画,用户负责乱改。

2. Layer存「语义角色+token」,不存绝对样式

js 复制代码
// 错误示范:存死样式
{ "fontSize": 24, "color": "#1a1a1a", "fontFamily": "PingFang SC" }
// 正确示范:存角色 + token 引用
{ "role": "title", "style": { "colorToken": "fg-primary", "sizeStep": 3 } }

这是「一键换风格」能不能做成的分水岭。存绝对像素的话,用户换风格时你得从像素反推语义角色------推不准就换不干净,换出来跟精神分裂似的。

用户手改过的地方存userOverrides覆盖层,就是CSS的层叠:token基线+用户覆盖。推论:组件里不许硬编码任何颜色和字号,只能引用token。这就好比装修:你先定风格,再配家具,不能先买十个不同风格的沙发摆家里。

3. 模板=风格×组件,不做「整页模板」

分三层:风格 (整体视觉语言,商务蓝/科技暗色/杂志风/手绘风,5-10套);主题token (配色、字体对、圆角、间距刻度、阴影层级,每套风格一套);版式组件(标题、三卡、对比、时间线、数据页、引用、结尾,25-40个)。

用户看到的「模板」=风格×组件。10套风格×30个组件,视觉上像几百套模板,实际维护量是10+30。

不做「模板A的第3页长这样」那种整页模板:每加一套风格要重画所有页面,维护量变成风格数×页数,而且用户改不动。这正是Presenton那条路,长期会变成谁都不敢碰的资产。就像衣柜里塞了三百件搭配好的套装,看着多,其实你只穿最外面那件。

4. 字体:生成端锁死+服务器装字体

先看现状(已核实):worker服务器aiserver0只有1个中文字体------DroidSansFallbackFull;开发机macOS有99个,苹方宋体黑体随便挑。99比1,这差距比我们公司和ChatGPT的用户数差距还大。

而且不同环节对字体的要求完全不同,必须分开处理:

环节 服务器字体够不够 原因
导出.pptx ✅ 不依赖 只写字体名,不渲染,由用户端PowerPoint解析
生成侧回渲QA ❌ 不够 渲出来是Droid fallback,跟用户看到的不是一个字形
导出.pdf ❌ 不够 PDF在服务器渲染,字体就是Droid

所以必须给服务器装字体,否则PDF导出不可用、QA没意义。选什么?Noto Sans CJK SC(思源黑体,OFL协议):免费、可自由分发、可嵌入。用户端没装会fallback到微软雅黑/苹方------同为黑体,观感接近,是代价最小的选择。

为什么不做字体嵌入?技术上要手写OOXML,真正的墙是授权------可嵌入的中文字体只有思源系列这类,苹方、微软雅黑不允许嵌入。

代价:牺牲用户的字体自由度,生成端只允许白名单字体,用户不能改。这是主动放弃,要写进产品说明。就像某些餐厅:菜单是固定的,你想加菜?对不起,我们主动放弃了这项服务。

5. 回渲QA放生成侧,只查结构性错误

导出链路里最重的一步是LibreOffice回渲:单页0.5-2秒,40页要1-2分钟。策略是:生成初稿时回渲一次验证布局(低频);导出时只把验证过的IR落成pptx,纯python-pptx,秒级,不需要soffice。

但它有个系统性误差:服务器即使装了Noto Sans CJK,用户端用的也可能是微软雅黑/苹方,字形和度量本就不同。所以QA判据只能是结构性错误:

QA能查 QA查不了
元素重叠 文字实际断行位置
超出页面边界 行距的像素级差异
文本溢出容器 用户端的最终观感
缺图/图片比例失真

这里有个扎心的事实:唯一100%保真的交付格式是PDF(服务器渲染,不依赖用户字体)。PPTX的保真度天花板就是「结构正确+字体fallback后观感接近」。PPTX说白了就是:能保证不散架,不保证长一样。

6. 导出走独立队列,别和渲染共用慢池

设想这个场景:一个90分钟的数字人渲染正占着慢池线程,用户点「导出PPTX」就要排在它后面。秒级任务被分钟级任务堵死------这不是概率问题,是必现的产品事故。

就像你去取外卖,前面那位在店里堂食了一顿90分钟的正餐。解决方案:新增导出池,并发硬卡1-2。秒级任务排队无感,但能防住一批人同时导出把soffice进程堆爆。

7. 导出是单向投影

「网页里编辑」和「PowerPoint里编辑」是两件事。前者编辑IR,后者编辑pptx。只做单向导出,不做双向同步------用户在PowerPoint里改完传回来,网页编辑器看不懂,这是无底洞。「用户上传自己的PPTX反解成可编辑图层」也不做,或放到很后面。现有soffice→PDF→PNG只出栅格页,反解要啃pptx逆向解析,工作量是另一个量级。

翻译:分手就是分手,别指望回心转意。双向同步的坑,谁挖谁知道。

四、能力边界:哪些能吹,哪些只能看看

1. 能做到的

生成:

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

编辑:

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

导出:

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

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

复杂视觉(渐变、阴影、混合模式、图标字体)→降级成图片层。看着对,但在PowerPoint里改不了。图表:简单图表可做原生chart,定制样式退回图片。表格:基础表格可以,合并单元格、条件格式、排序不行。导出保真:「看着差不多」,不是逐像素相同。字体:只能给白名单。

3. 做不到的

PPTX格式的天花板,再努力也绕不过:动画与切换效果 (python-pptx和PptxGenJS都不支持创建)、SmartArt (同上)、字体嵌入 (授权问题)、公式OMML。这四项只有一条出路:Aspose.Slides,商业授权,按部署收费。要不要为了动画买它?纯商业决定,我这种码农说了不算。

架构上明确不做的:用户上传PPTX反解成可编辑图层;与PowerPoint双向同步;多人实时协作(技术上能做,单机也扛得住,但要加CRDT+长连接,纯工作量问题,可后加)。

4. 产品文案的红线

别写「导出的PPT可以随意编辑」。用户一试形状和动画就会觉得被骗。准确说法:「导出的PPTX里,文字都能直接改。」

这条红线建议裱起来挂墙上。你能想象用户兴冲冲拖一个形状,发现拖不动,然后去应用商店给你一星吗?我能。

五、实施方案

1. 模块划分

编辑器页面:manteng-ai/src/views/deck/(新建),矢量画布编辑器+风格/版式面板;渲染层:manteng-ai/src/views/deck/components/,组件库(25-40个版式组件);主题:manteng-ai/src/.../themes/,token表,5-10套;后端:aigc-backend/src/main/java/org/aigc/deck/(新建),增删改查+生成编排+导出派发;排版器:aigc-backend或worker,LLM内容+版式意图→Layer\[\];导出器:artificial-intelligence-notebook/sse/handlers/deck_handler.py(新建),IR→python-pptx;QA环:worker,生成侧回渲比对。

2. 核心数据模型

设计空间统一1920×1080(不用现有编辑器的768×432)。换算干净:导出时 pt = px / 2。

js 复制代码
// 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表(每套风格一份):

js 复制代码
{
  "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" }
}

3. 落库

沿用现有「整体保存一页」的模式(同/ppt/update_page存material数组):ppt_deck、ppt_slide两张表,layers存jsonb,整页保存不拆表。编辑器自动保存本来就是一页一提交。

几个坑记一下:写jsonb必须显式转型?::jsonb(连接串无stringtype=unspecified);SimpleJdbcInsert必须指定usingColumns,否则缺列被绑成NULL,DDL默认值不生效;DDL无迁移框架,需手动ssh+psql应用。

4. 接口

js 复制代码
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. 导出映射

IR PPTX
box.x/y/w/h(1920设计px) Inches(px / 144) ------ 1px = 1/144 in,1920px = 13.333in
sizeStep → scale.size-stepsstep 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只写latin,中文会退回主题默认字体。必须额外写ea/cs(东亚字体是ea),顺序是latin→ea→cs。

(2)空effectLst挡不住LibreOffice的投影。

add_shape/add_connector会带一个引用主题的p:style,里面有effectRef idx=2(主题投影)。按OOXML规范,显式空effectLst应该覆盖它,PowerPoint也认------但LibreOffice不认,照样渲出投影。而回渲QA和PDF导出都走LibreOffice,所以必须把p:style整个删掉。lnRef/fillRef同理,会让「没设描边的形状」长出一条主题色的边。

这条我要多嘴一句:规范说「应该覆盖」,PowerPoint说「行」,LibreOffice说「我就不」。三个裁判三个口径,你只能把整段删了。跟甲方改需求一样,你以为有个标准,其实没有。

6. 里程碑

阶段 内容 验收
M1 IR schema + 导出器(手工JSON → pptx) 导出的pptx与预览图逐页对照,肉眼无差异
M2 编辑器(矢量画布 + 存/取) 能建页、拖框、改字、存回、刷新后一致
M3 生成端(LLM内容 + 版式意图 → 排版器) 给主题出一套,无重叠/出界/字号乱
M4 主题与组件库(风格 × 组件) 一键换风格,内容不动,每套都好看
M5 QA回环 + 验收矩阵(组件 × 风格全量渲染比对) 改一次token全量重渲无回归
M6 PDF/PNG导出、配额计费、导出池 导出不排队;扣费与报价一致

**先做M1。**导出保真度是整条链路风险最高的地方,先用手工JSON把「IR→pptx→回渲→对照」这条路走通,再往上叠东西。地基不打牢,楼盖得再高也是危楼。

7. 机器资源

保存图层:每次拖拽,一次JSON写库。导出pptx(40页):每次点导出,秒级,纯CPU。回渲QA:每次生成初稿,20-80秒,CPU+磁盘。每页PNG(150 DPI):1-3MB/页,走OSS,临时文件要清。

重点:零GPU依赖。「编辑+导出」这条线4核/16GB就够。真正让单机吃紧的是并发导出×soffice进程数,并发卡1-2即可。临时文件清理要单列任务------CosyVoice3那边已经吃过临时分片残留的亏。垃圾不扔,早晚长蟑螂。

六、风险清单

风险 影响 缓解
导出保真度不达标 产品核心承诺落空 M1先做,手工JSON走通再叠功能
组件 × 风格组合爆炸 某些组合丑/撞色 自动验收矩阵,M5
服务器只有1个中文字体 PDF导出难看、QA无意义 给服务器装Noto Sans CJK SC
字体在目标机器缺失 排版散架 生成端锁字体,写进产品说明;PDF才是保真交付格式
导出与渲染抢worker 用户点导出没反应 独立导出池
用户预期「完全可编辑」 差评 文案红线
Aspose动画需求 商业授权成本 先不做,观察需求

最后总结一下这条线的脾气:能用外部方案的我们全自己写,能降级的复杂效果全降级成图片,能不做的东西全不做,只把「编辑+导出pptx/pdf」这一件事做到位。听起来很怂?不,这叫边界感。

就像我开头说的,你只需要记住一句话:**PPTX里,文字都能直接改。**别的,等用户真的需要了再说。

P.S. 无意间发现了一个巨牛的人工智能教程,非常通俗易懂,对AI感兴趣的朋友强烈推荐去看看,传送门https://blog.csdn.net/qq_34419312

相关推荐
KKKlucifer1 小时前
数据安全管控平台运营化关键技术:从策略下发到闭环治理
大数据·人工智能·产品运营
我喜欢就喜欢1 小时前
DeepSeek 大模型多场景落地应用指南
人工智能·系统架构
火山引擎和TA的超级拍档们1 小时前
产品情报局 06 | 短剧 Agent:多 Agent 协同,重塑 AI 短剧工业化生产流程
人工智能
可涵不会debug1 小时前
机器人行业的下一道门槛,不是更大模型,而是更短的数据闭环
人工智能·机器人
隔窗听雨眠1 小时前
小模型大分工:小语言模型如何重塑RAG系统的架构逻辑
人工智能·语言模型·架构
马剑威(威哥爱编程)1 小时前
【HarmonyOS 7 小艺智能体实战】02:动工前的清单——账号、资质、工具链一次备齐
人工智能·华为·harmonyos
IT_陈寒1 小时前
为什么你应该学习React?
前端·人工智能·后端
誰能久伴不乏1 小时前
AI 时代,我们该怎么正确地学习编程
人工智能·学习