所有独立作品
Frame

VIBE CODING / DESKTOP / OPEN SOURCE

Frame 3.4.0 · 2026.11

Frame:从一个格式转换需求,
到一套本地媒体工作台

一次从真实问题出发,经由持续反馈完成的 Vibe Coding 实践。

Frame 3.4 的真实 Electron 界面,在 macOS 环境复拍;此图为无文件状态。

Frame 是一款面向设计与动效素材处理的本地桌面工具。它从「SVGA 能不能转成 PAG」这个具体问题开始,逐步扩展为支持动画转换、透明序列帧导出、音频与图片压缩的媒体工作台,并完成 macOS 与 Windows 打包及开源交付。

这个项目记录了我如何把需求交给 AI 实现,再通过实际使用、视觉判断和结果验证,让一个能运行的方案逐步变成可以使用的产品。

项目信息内容
类型个人产品实践 / Vibe Coding / 开源桌面应用
我的工作需求提出、产品范围、交互与视觉判断、素材效果验收
AI 协作技术方案、界面与转换代码、问题排查、验证及打包支持
案例快照Frame 3.4.0,2026 年 11 月
平台macOS 13+;Windows 10 / 11 x64 已提供构建产物,真机验证待完成
项目链接GitHub · 下载与版本记录
阅读目录 · 9 个章节

01 / 背景:从一份动效素材的交付问题开始

最初,我想解决的事情很简单:手里有一份 SVGA 动画,需要把它转换为 PAG。

这类需求看起来只是更换文件后缀,实际牵涉到不同格式的渲染与编码方式。画面是否清晰、透明背景能否保留、尺寸和帧率是否正确,以及生成文件能否被目标播放器正常读取,都需要逐项确认。

我希望把这些处理过程封装起来,让使用者添加素材、调整必要设置,就能得到可交付的结果。素材在电脑上处理,也能省去上传和下载的往返。

因此,项目最早的目标是:先跑通一条真实的转换链路,再把它做成一个可重复使用的工具。

02 / 从 0 到 1:先有可用链路,再形成产品

第一步,是验证 SVGA 到 PAG 的转换方式:通过本地播放器逐帧渲染动画,得到带透明通道的画面,再进行 PAG 编码。由此保留尺寸、帧率和透明背景,但原始图层会合并,输出也存在有损压缩。

最早的版本采用脚本和浏览器页面完成操作。它已经具备文件添加、批量处理、转换状态和输出位置等基础能力,但使用方式仍然带着工具脚本的痕迹。

在实际使用后,我提出了一个明确的要求:

「做成一个像是电脑 app 的那种。」

这次反馈改变了产品的方向。接下来需要解决的,是启动方式、预览、文件管理和重复导出等完整体验。用户应该能看懂当前状态,并知道下一步该做什么。

早期浏览器原型 / 源码复拍
按早期交付源码复拍的页面;输出位置使用演示文字。它展示的是桌面化之前的浏览器原型。
桌面工作台 / Frame 3.4
Frame 3.4 的真实 Electron 工作台,在 macOS 环境复拍。
产品阶段回顾;早期阶段来自交付记录,3.2 之后可对应公开仓库记录。

03 / 产品功能:把相邻的素材处理需求接进同一条流程

随着使用场景增加,Frame 逐步接入 GIF 导出、PNG 序列、MP3 压缩和图片压缩。新增功能围绕同一个目标展开:减少素材交付前反复切换工具、确认参数和查找结果的操作。

截至 3.4,Frame 包含 8 项工具:

工具解决的任务主要设置与边界
SVGA → PAG转换动效交付格式小体积—均衡;保留原尺寸、帧率与透明背景,图层合并
SVGA → GIF导出便于查看和分享的动画尺寸、帧率、背景、调色板质量
PAG → GIF将 PAG 画面转换为通用动画与 GIF 导出采用一致的设置逻辑
SVGA → PNG 序列提取透明画面,供后续制作使用原始全帧或指定帧率、尺寸、连续编号
PAG → PNG 序列逐帧导出 PAG 的实际渲染画面保留透明背景,支持尺寸和提取帧率调整
MP4 → PNG 序列从视频中提取连续画面提取帧率与输出尺寸;PNG 编码无损
MP3 压缩在文件大小和听感之间做选择可调音质;最高档保留原音频流,体积可能不变
图片压缩优化静态 JPG、PNG、WebPJPEG / WebP 画质、长边尺寸、格式选择及原图对比

多种能力共用一条操作路径:选择工具 → 添加文件 → 查看预览 → 调整设置 → 导出 → 检查结果。

文件可以拖入,也可以多选添加;队列支持搜索和状态筛选。转换过程中可以停止任务,完成后可以打开结果位置。调整设置后,能够重新导出;原结果保留,同名文件自动编号。

PNG 序列使用帧率和尺寸设置,不呈现没有实际意义的有损质量滑块。
使用为本案例新建的几何演示图片,实际转换为 WebP。图中体积仅对应该素材,不代表产品的平均压缩率。

04 / 设计:让一个工具具有桌面应用的使用秩序

围绕任务组织信息

桌面化之后,界面形成了稳定的工作区:侧栏负责切换工具,文件队列负责管理任务,中央区域负责查看画面,右侧负责文件信息与导出设置。

这个布局把「处理哪个文件」「画面是什么样」「要怎样输出」放在相邻的位置。功能扩展时,用户可以沿用已经理解的操作方式。

视觉上,界面采用浅色底、清晰的分区和紫色操作强调。大部分区域保持克制,把注意力留给素材预览、状态变化和主要操作。

空状态也要说明当前任务

早期不同工具沿用了同一张 SVGA → PAG 配图。切换到 GIF 或音频压缩后,画面表达与功能不符。我据此提出:

「空状态的配图要根据选项的功能来。」

随后,每种工具都有了对应的输入输出图示、说明文字和选文件按钮。SVGA → GIF 展示格式变化,PAG → PNG 展示帧序列,图片压缩展示原图与压缩后,MP3 则使用音频语义。

用户还没有添加文件时,页面就已经开始解释这个工具的作用。

相同的工作台结构,配合不同的功能语义。

为 Frame 建立独立的视觉标识

Logo 探索了三种简洁、具有科技感的方向,最终选择 C 方案。正式图标以折叠的金属 F 为主体,搭配黑色圆角底,强调字母识别和空间层次。

图标进一步整理为可用于应用的 PNG 与 macOS 图标资源,让项目从页面标题延伸到桌面图标和应用身份。

A / 探索方案
B / 探索方案
C / 最终选定

三种 Logo 探索方向;C 为最终选定方案,后续整理为正式应用图标。

完成后,仍然可以继续调整

第一次导出后,设置仍然可以修改。界面会标明「设置已调整,上次结果保持不变」,用户再按当前设置导出新文件。结果对比、重新选择参数和保留旧文件因此连成一条流程。

结果区域呈现完成状态、体积信息、设置变化提示与再次导出的入口。

05 / 一个关键取舍:为什么去掉 PAG 的「高质量」档

在转换能力稳定后,我注意到部分 PAG 输出不够清晰,于是提出加入质量选择,并允许完成后调整设置重新导出。

早期尝试了低、中、高三个档位。但用同一份 SVGA 对比输出后,我发现:文件体积差距很大,肉眼感受到的画面改善却不明显。

「如果差异并不显著我建议去掉【高】选项。」

检查实现后,问题逐渐明确:当时不同档位使用了不同的存储策略。压缩视频可以利用相邻画面的重复信息;逐帧位图方案则会保存更多独立的画面数据。即使都在播放相同尺寸、相同时长的动画,体积也可能相差很大。

编码方式带来的数据增加,不一定会转化为同等明显的视觉收益。原素材已有的细节上限,也无法通过提高输出档位补回来。

因此,后续版本将 PAG 输出统一到视频压缩路径,移除了体积代价过大的逐帧无损「高」档,保留「小体积—均衡」的选择范围。界面同时明确:滑块表达编码取舍,改善幅度取决于素材。

定性决策复盘,不是压缩率或画质评分图。

这次迭代也影响了其他功能的参数设计。PNG 使用无损编码,无需套用统一的画质滑块;GIF 受调色板与透明能力限制;JPEG / WebP 的质量档位,也不应解释为原图保真率。

我更关心的是:每一个选项是否对应用户能理解、也值得承担的成本与收益。

06 / 技术实现:把渲染、编码与文件交付连起来

Frame 的界面之下,是一条本地媒体处理链路:读取文件并检查基本信息,调用对应播放器或解码器,生成画面,再编码并写入输出文件。不同格式使用适合自己的路径。

结构示意;两端目前为独立宿主,并非一套源码直接跨平台编译。
层次实现方式
macOS 宿主Swift / AppKit,结合 WebKit 承载工作台与本地渲染;音视频相关能力使用系统框架
Windows 宿主Electron + Node,处理桌面交互、文件任务和转换流程
动画渲染SVGAPlayer-Web / libpag,在本地还原输入素材的画面
PAG 编码macOS 使用 PAG 转换组件及编码桥接;Windows 实现便携的视频型 PAG 写入路径
媒体与图片FFmpeg 处理音视频任务;图片使用浏览器编码能力与本地 WebAssembly 编解码器
输出交付状态反馈、取消、同名编号、设置变更识别与重新导出

为了在 Windows 上保留相近的产品流程,需要重新适配宿主和编码链路。透明 PAG 输出还需要处理颜色与 alpha 信息,并通过播放器解码结果确认它们能被正确还原。

这些细节决定了应用生成的文件能否真正进入下一步制作流程。

代码细节一:压缩后更大,就保留原图

图片压缩不能只以「编码成功」作为完成标准。对已经优化过的图片,再编码可能让文件变大。

Frame 在同格式、同尺寸的情况下判断实际输出大小。如果没有得到更小的结果,就保留原始图片,并说明原因。

js仅供阅读
// 来自图片处理实现,展开排版以便阅读。
const keepOriginal =
  format === info.imageFormat &&
  factor === 1 &&
  encoded.length >= bytes.length;

这让「压缩」的行为与用户预期保持一致,也避免把更大的文件包装成优化结果。

代码细节二:屏幕上看着正常,还要检查实际像素

PNG 序列导出曾遇到 Retina 环境中的尺寸问题:屏幕缩放比例可能进入渲染过程,造成导出像素尺寸偏离原始设置。后续在 PAG 渲染视图中显式关闭自动缩放,并检查实际输出尺寸。

图片无损优化也采用类似的验收方式。针对 PNG 原格式、不缩放的优化路径,测试会解码输出文件,并逐像素比较 RGBA 数据:

js仅供阅读
// 来自图片压缩集成测试,变量名沿用源码。
assert.equal(decoded.width, png.width);
assert.equal(decoded.height, png.height);
assert.deepEqual(decoded.data, png.data);

视觉检查与数据检查分别回答不同的问题:前者判断效果是否合适,后者确认尺寸、透明和像素等承诺是否成立。

07 / Vibe Coding 的工作方式:把反馈变成下一版的验收条件

Frame 的需求是在使用中逐步明确的。每次得到可运行版本后,我会检查结果、提出具体问题,再让 AI 把这些判断转成界面或代码上的修改。

实际反馈对应的产品或工程调整
使用起来像脚本,希望像电脑 App转向桌面工作台,补齐预览、队列与导出管理
想在导出前选择质量,完成后还能再调整增加质量设置、设置变化提示和重新导出
高档体积增加很多,画面改善有限检查编码策略,收窄 PAG 质量范围
不同工具都显示同一张空状态配图为每种工具匹配图示、说明和操作入口
希望支持图片压缩扩展现有工作流,并验证透明、方向、尺寸与原图保留

在这个过程中,我负责说明需求、判断结果、决定取舍;AI 负责提出实现方案、编写和调整代码,并协助完成验证与打包。

有效的协作往往来自具体的描述。例如,「画质不好」需要进一步变成同一素材的结果对比;「不好用」需要落到缺少预览、状态不清晰或导出后不能继续调整等问题上。

每一次反馈,都在帮助下一版形成更明确的验收条件。

08 / 交付:让项目能被下载、理解和继续维护

Frame 后续完成了公开仓库、版本发布、macOS 应用包、Windows 安装器与便携包,以及使用、构建和第三方组件说明。

版本迭代也逐步变得可追溯:3.2 整理跨平台开源交付;3.3 增加 SVGA / PAG 的 PNG 序列导出并完善空状态;3.4 增加图片压缩及相应验证。

验证覆盖实际转换、透明通道、尺寸与帧率、取消、重复导出和同名不覆盖等路径。图片压缩还检查了 PNG 像素一致性、WebP 透明、JPEG 方向,以及动态或损坏图片的拒绝处理。

当前交付也保留明确边界:Windows 构建产物已完成静态检查,共享实现已在 macOS 的 Electron 环境中验证;Windows 真机的安装、运行与卸载仍待验证。应用尚未进行商业代码签名,macOS 包未公证。

Frame 自有源码采用 MIT,播放器、编码器等第三方组件保留各自许可。

09 / 回看这次实践

这次项目让我看到,AI 协作可以把需求转化为可运行的版本,也让持续试用和快速调整变得更容易。与此同时,产品仍然需要有人判断:结果是否可接受、参数是否有意义、功能是否容易理解,以及完成到什么程度才算可以交付。

Frame 最有代表性的进展,是这些判断逐渐进入了产品:空状态解释当前任务,质量选项承认格式的限制,重新导出保留旧结果,图片压缩在没有收益时保留原图。

从一个 SVGA 转换问题出发,最终留下了 8 项工具、一套连贯的桌面操作流程,以及可以查看源码、下载版本和继续迭代的项目。

提出真实问题,交付可用版本,通过实际结果做下一次判断。 这是我在 Frame 中形成的 Vibe Coding 工作方式。

查看 Frame 源码 · 下载 Frame · 查看 3.4 版本

返回所有独立作品