自定义与扩展

换模型、加语言、加工具 —— 代码结构上该怎么动。

代码结构

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.tsIMAGE_MEAN / IMAGE_STD),换模型时要一起核对。

输出张量名有容错。注册表里的名字对不上时,会退到「唯一输出」, 多输出时按形状挑最像遮罩的那张(最后一维最小的空间张量)。 全都认不出才会报 tensor-missing,并把图里实际有哪些输出名带上。

加一种语言

  1. src/i18n/locales/ 下新建一份语言文件,参照 en.ts 的结构。 类型是 Translation = typeof en,所以漏翻会在编译期报错。
  2. src/i18n/index.ts 里注册这门语言。
  3. 复制 HTML 入口:index.htmlupscale/index.htmlcutout/index.html 各来一份带语言前缀的副本,改好 canonicalhreflang
  4. vite.config.tsrollupOptions.input 里加上新入口。

加一个新工具

  1. src/lib/ 下建推理层(如果这个工具需要模型)。 运行时与缓存直接复用 src/lib/ort/不要引入第二份 ONNX Runtime
  2. src/hooks/ 下写状态机,约定同上:不碰面向用户的文案。
  3. src/components/<tool>/ 下写组件。
  4. src/App.tsx 里加进 Tool 类型、PATHS 映射与 TOOLS 列表 —— 标签页和路由会自动跟着走。
  5. 新建 HTML 入口(含英文版),加进 vite.config.tsDIR_INDEXinput
  6. 补 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.tsserver.headerspreview.headers 共用同一份常量),保证本地与线上行为一致 —— 不然多线程 WASM 在本地测不出来。