自定义与扩展
换模型、加语言、加工具 —— 代码结构上该怎么动。
代码结构
src/
├── lib/
│ ├── ort/ 两个工具共用的 ONNX Runtime 层
│ │ ├── runtime.ts 运行时准备(wasm 路径、线程数)
│ │ └── modelCache.ts 权重下载 + Cache Storage 缓存
│ ├── upscaler/ AI 放大:模型表、会话、张量、瓦片
│ ├── cutout/ AI 抠图:模型表、预处理、会话、合成
│ ├── models.ts 放大模型注册表
│ └── types.ts 共享类型
├── components/
│ ├── compress/ 压缩工作区
│ ├── upscale/ 放大工作区
│ └── cutout/ 抠图工作区
├── hooks/ useUpscaler / useCutout 状态机
└── i18n/ 中英文案
一个刻意的设计:推理层不写任何面向用户的文案。
进度只产出结构化的 { phase, ratio, detail },错误只抛带 code 的错误对象,
结果附注产出结构化的 note。文案全部由 i18n 渲染 —— 这样加语言不用碰算法代码。
换成别的放大模型
在 src/lib/models.ts 里加一条,并把 .onnx 放进 public/models/:
{
id: 'my-model',
label: '显示名称',
url: '/models/my-model.onnx',
scale: 4,
approxBytes: 0,
inputRange: 'unit', // 'unit' = 0–1,'byte' = 0–255
inputName: 'image', // ONNX 图里的输入张量名
outputName: 'upscaled_image',
fixedInputSize: 128, // 固定输入边长;动态形状填 null
license: 'BSD-3-Clause',
}
单个文件别超过 25 MiB,否则 Cloudflare 会拒绝部署。
模型说明文案放在 i18n 的 upscaleModels 下,按 id 取用。
换成别的抠图模型
在 src/lib/cutout/models.ts 里加一条:
{
id: 'my-matting-model',
label: '显示名称',
variants: {
webgpu: { url: 'https://…/model_fp16.onnx', approxBytes: 0, dtype: 'fp16' },
wasm: { url: 'https://…/model.onnx', approxBytes: 0, dtype: 'fp32' },
},
inputSize: 512,
inputName: 'input_image',
outputName: 'output_image', // 写错会报 tensor-missing
outputIsLogits: true, // 输出是否需要过 sigmoid
license: 'MIT',
}
如果模型输入不是 512 而是别的方形尺寸,改
inputSize 即可,预处理会跟着走。
但预处理里的 ImageNet 均值方差是写死的(models.ts 的
IMAGE_MEAN / IMAGE_STD),换模型时要一起核对。
输出张量名有容错。注册表里的名字对不上时,会退到「唯一输出」,
多输出时按形状挑最像遮罩的那张(最后一维最小的空间张量)。
全都认不出才会报 tensor-missing,并把图里实际有哪些输出名带上。
加一种语言
-
在
src/i18n/locales/下新建一份语言文件,参照en.ts的结构。 类型是Translation = typeof en,所以漏翻会在编译期报错。 - 在
src/i18n/index.ts里注册这门语言。 -
复制 HTML 入口:
index.html、upscale/index.html、cutout/index.html各来一份带语言前缀的副本,改好canonical与hreflang。 - 在
vite.config.ts的rollupOptions.input里加上新入口。
加一个新工具
-
在
src/lib/下建推理层(如果这个工具需要模型)。 运行时与缓存直接复用src/lib/ort/,不要引入第二份 ONNX Runtime。 - 在
src/hooks/下写状态机,约定同上:不碰面向用户的文案。 - 在
src/components/<tool>/下写组件。 -
在
src/App.tsx里加进Tool类型、PATHS映射与TOOLS列表 —— 标签页和路由会自动跟着走。 - 新建 HTML 入口(含英文版),加进
vite.config.ts的DIR_INDEX与input。 - 补 i18n 文案、sitemap 条目,以及文档站里对应的页面。
已知限制
| 限制 | 说明 |
|---|---|
| 放大输出上限 6400 万像素 | 按倍率折算,4× 约能处理 2000×2000 的源图。超出需要先裁切或缩小。 |
| 放大与抠图是单张处理 | 压缩可以批量,这两个是重计算任务,且需要逐张确认效果。 |
| 抠图遮罩上限 512×512 | 源图更大时边缘精度受遮罩分辨率限制,结果面板会给出附注。 |
| 无 WebGPU 的机器体验有限 | 会降级到 WASM,且抠图要下载 192 MB 而非 94 MB。 |
| 抠图只找最显著的主体 | 多对象图只抠最突出的那个;纯风景图可能判定为「无主体」并报错。 |
本地开发
npm run dev # 开发服务器(已带 COOP/COEP 头)
npm run build # 生产构建
npm run typecheck # 只做类型检查
npm run lint # ESLint
npm run preview # 预览构建产物
开发服务器也带跨域隔离头(
vite.config.ts 的 server.headers 与
preview.headers 共用同一份常量),保证本地与线上行为一致 ——
不然多线程 WASM 在本地测不出来。