feat(h5): apply fourth feedback and tighten local capture validation

This commit is contained in:
xsl
2026-10-12 20:16:41 +08:00
parent e53c809522
commit 92a3965b7d
33 changed files with 3758 additions and 1385 deletions
+6 -4
View File
@@ -62,14 +62,16 @@ node server.js # 默认 8080,可用 PORT=xxx 修改
三步严格按顺序,本步拍到合格照片才进入下一步(左右一律以用户本人为准):1/3 正对屏幕(target `front`)→ 2/3 右脸出镜(用户头向自己的左侧转,target `right`,产物作 `right_image`)→ 3/3 左脸出镜(头向自己的右侧转,target `left`,产物作 `left_image`)。送检前 `photosByView` 按 target 重排为 [正, 左, 右]。页面内没有返回按钮,微信/浏览器返回键经 History API 回到档案页并释放摄像头。
- **取景蒙版**:内联 SVG(`#cam-mask`)按步骤切换轮廓——正脸步为正脸剪影(含耳部),侧脸步为对应方向的侧脸剪影;**轮廓路径由 Figma 拍照示意图(`design/assets/images/*-拍照示意.png` 的 alpha 镂空区)逐像素描摹生成**,坐标为 Figma 375×812 整帧,viewBox 只取 y 86–812;框外 85% 黑,轮廓线 2.5px 半透明白。检测运行时轮廓内有自上而下的扫描带(`#cam-clip` 由 app.js 复制轮廓生成);未检测到人脸时轮廓呼吸动画;条件合格时轮廓变绿。
- **预览缩小 15%**:`#cam-video` 按 `scale(.85)` 显示,手机离脸近一些也能把脸装进轮廓;距离阈值随之按 1/0.85 换算(人脸框高/视频高 <0.30 提示「请靠近一点」、>0.68 提示「请远一点」)。
- **动态提示**(一次一条,优先级:无人脸 > 距离 > 居中 > 角度 > 光线):「未检测到人脸」「请靠近一点 / 请远一点」「请将脸部移入取景框」(人脸中心偏离中线 >18% 屏宽)、角度类「请向左转头 / 请向右转头 / 请略微抬头 / 请略微低头」(正脸阈值 |yaw|≤15°、|pitch|≤18°,超出时按超出比例更大的一项给方向;侧脸 yaw 28°–75°、|pitch|≤20°)、光线类「请到光线充足处 / 光线过强,请避开强光」(脸部平均亮度 <65 或 >235)。
- **合格即拍**:上述条件全部合格并连续维持 450ms(滤掉一闪而过的合格帧,防运动模糊)立即白屏补光抓拍,**无倒计时、无手动快门**。
- **预览铺满**:`#cam-video` 保持现有 `object-fit:cover` 铺满与镜像策略,第四轮不改取景视觉,仅收紧下述本地门限。
- **动态提示**:第四轮收紧本地判定,单人、检测置信度≥0.5、人脸框高占原始画面 34%~64%、水平中心偏离≤12% 屏宽、完整入镜且距原始帧边缘≥2%。正脸 |yaw|≤10°/|pitch|≤12°,侧脸转头幅度 35°~65°/|pitch|≤15°,两者 |roll|≤10°;脸部平均亮度 75~225。参数集中在 `js/capture-quality.js` 与 `js/head-pose.js`,均为经验初值,不等价于服务端质量分。
- **合格即拍**:连续稳定至少 650ms 且至少 3 个合格检测帧,漏检、姿态/位置漂移或帧间隔超过 2 秒均重置稳定累计;白屏抓拍后在本地复验实际 JPEG,合格才推进。**无倒计时、无手动快门**(已有降级模式除外)。
- **两张之间停顿**:正脸、右脸拍完后中央弹出停顿卡约 2s(「正脸拍摄完成 / 下一张:右脸出镜,请向左转头」),停顿期间不检测,结束后再切到下一步并播下一步引导,让用户对下一张有心理预期。
- **实时检测**:face-api 从本地 `vendor/faceapi/` 加载(`tinyFaceDetector` + `faceLandmark68Net`),进入拍照页开始加载(状态提示「检测引擎加载中…」)。检测循环 ~150ms 一帧,特征点取自原始帧(预览 CSS 镜像不影响),个别前置帧已镜像的机型由侧脸自校准翻转 `sideYawFlip`;连续漏检 ≥3 帧才报「未检测到人脸」。
- **镜像策略**:前置镜头预览镜像(照镜子习惯);后置预览不镜像,侧脸轮廓随之翻转(`.cam-mask.flip`)。**抓帧一律不镜像**,三张照片都是摄像头原始视角。
- **白屏补光**:全屏纯白覆盖层瞬间点亮,~300ms 后抓全分辨率帧(原始视角 + 最长边 1280 JPEG),保持 ~300ms 再淡出,同步 `navigator.vibrate(30)`。
- **快门只在无法实时识别时出现**:系统相机降级(getUserMedia 不可用/被拒,如手机走局域网 HTTP)、face-api/模型加载失败、`?mock=1` 调试。降级与相册选图拿到的照片会先用 face-api 校验(有人脸、正脸/侧脸转头幅度对;系统相机是否镜像因机型而异,侧脸不校验左右),不合格提示重拍、停在本步;模型不可用时放行,由服务端兜底。
- **快门只在无法实时识别时出现**:系统相机降级、face-api/模型加载失败、`?mock=1` 调试。文件照片共用同一套本地单人/距离/完整入镜/角度/光线校验,不合格停在当前步;系统照片可能已镜像,侧脸不判断左右,并标记 `direction_checked:false`。本地模型加载中最多等 8 秒;确实不可用时保留原有降级通路,但后台明确记录 `unchecked/model-unavailable`,不冒充检查通过。服务端质量结果仅记录,不新增重拍阻断。
- **报告等待与质量留痕**:原 PSD 画面增加约 1 秒上下往返扫描;成功跳转等待至少一次实际动画循环,错误/取消立即恢复。拍摄质量备注不在用户报告展示,后台列表、详情和 CSV 保留侧脸质量状态与前端参数版本。前端诊断为客户端自报,仅供校准,不作为服务端质量真值。
- **相册选图**:相机页「相册」按钮可选当前步的图片,与降级拍照同管线(压 1280 → 校验 → 推进)。
- **语音播报**:步骤引导/姿态提示/拍摄完成/分析中/失败,文案与文件名契约见 `../docs/语音播报内容设计文档_V1.0.md`。新增的提示(居中、抬头/低头、光线)暂无音频,清单缺失的条目静默跳过,只显示文字。
- **无进展提示**:单步 12s 仍未拍到,底部浮出「识别不到?请正对镜头,并到光线充足处」(不阻塞流程)。