倬懿影坊 · 功能与实现

一个 AI 修图小程序是怎么搭起来的

技术栈是 UniApp(Vue2)+ 微信小程序,零 npm 依赖,纯 HBuilderX 工程。 后端提供人脸与图像处理能力,小程序负责上传、参数交互和结果展示。

整体架构

小程序 → 对象存储(源图 / 结果图) → 后端服务 → 算法服务 → 结果图 URL

小程序只做三件事:把照片传到对象存储、把对象 key 交给后端、把后端返回的结果图展示出来。 所有算法都在服务端跑,端上不承载模型。

有意思的一点是,后端五个处理接口名字都带 _ws 后缀,但对外其实是普通 HTTP POST: 后端内部通过 WebSocket 调算法服务,拿到结果后同步返回。所以小程序侧按普通请求调用即可, 不需要维护连接和心跳。

上传:走直传,不经过后端

一次上传分三步,照片文件不经过自己的服务端:

// 1. 取一次性上传凭证
GET /file/qiniu/uploadkey?type=6   → { uploadkey, prefix }

// 2. 直传对象存储(华南 zone2)
uni.uploadFile({
  url: 'https://upload-z2.qiniup.com',
  formData: { token: uploadkey, key: 'temp/<时间戳>_<随机>.jpg' }
})

// 3. 以后端返回的真实 key 为准,再调处理接口
POST /image/beauty_ws  { "key": "temp/..." }

五个处理接口

统一约定 { code, msg, data },code === 0 视为成功,返回 data.<功能>.url。

功能接口主要参数
AI 换脸 POST /image/swap_face_ws key、photo_id(母片,选填)
换天空 POST /image/sky_ws key 或 photo_id、sky_key(天空素材,选填)
抠图换背景 POST /image/matting_ws key、bg_key(选填,不传返回透明 PNG)、scale/left/top/right/bottom
深度美颜 POST /image/retouch_ws key、max_faces(GFPGAN + CodeFormer)
经典美颜 POST /image/beauty_ws key、smooth/whiten/slim_face/enlarge_eye/slim_nose(0–1)、style、style_strength

一套页面服务五个功能

五个功能的参数表单完全不同,但我只写了一个处理页 pages/process/process.vue。 做法是把功能差异抽成一份元信息配置,页面按 ?type= 读配置渲染:

// utils/features.js
beauty: {
  title: '经典美颜',
  api: 'beauty',
  needBg: false,        // 抠图才需要选背景
  needStyle: true,       // 美颜才有风格选项
  needStrength: true     // 美颜才有强度滑块
}

几个页面上的实现细节

首页:会动的功能盘

五个功能按钮沿着一个半圆形排布,中间是带 HOT 标记的 AI 换脸,5 秒自动轮播一次。 顶部背景视频会随着当前选中的功能切换素材,下方扫描器的颜色也跟着变。

首页:投影光柱怎么算

按钮到中心的光柱需要长度和旋转角。先用固定布局做一次确定性计算, 再用 createSelectorQuery 实测 DOM 位置修正,用 atan2 求角度、hypot 求长度。

预览页:长按看原图

默认显示 AI 效果图,长按切换到原图,松手复原,用来对比前后差异。

预览页:保存到相册

网络图必须先 downloadFile 再 saveImageToPhotosAlbum。 失败时如果错误里带 auth / deny,就弹窗引导用户去设置页开权限。

相册:批量上传串行化

一次最多选 9 张,用 reduce 串成 Promise 链逐张上传, 带 n/total 进度提示。并发上传很容易把存储打爆,也拿不到稳定的进度。

请求层:统一收敛

request.js 里约定 statusCode 200 且 code === 0 才 resolve, 并且只 resolve data;其余情况直接 reject 出 msg,页面统一 Toast 展示。

额度与订单:不在回调里认定到账

小程序用的是微信虚拟支付。这里最容易出问题的地方是: 不能在支付的 success 回调里就认为钱到账了。

wx.login → code
  → POST /pay/login        // 换 token
  → POST /pay/create       // 拿签名与订单号
  → wx.requestVirtualPayment
  → POST /pay/confirm      // 服务端向微信查单后发货

踩过的坑

这些都是真机调试时一个个撞出来的,记下来免得下次再踩一遍。

交流

对实现细节感兴趣,或者也在做类似的东西,欢迎一起聊聊。

hello@gearingsoft.com

粤ICP备17155525号 | 本站为个人学习与技术记录网站,不涉及经营性活动