① 一句话结论
拍照这一条路是行业顶级的(苹果满血管线 + 零确认页 + 快门即定格),功能面比 WhatsApp 多(DUAL 双摄、视频留言、实时滤镜/特效/背景、弱光键);但有四个"看不见的洞":①默认发出去的照片只有 1600 像素、视频只有 720p(满血画质到不了对方手机,除非点 HD);②Android 引擎只有拍照没有录像/闪光/滤镜;③引擎不听系统"相机被抢走/出错"的信号;④一个打点都没有,谁用了相机、用了哪档,没人知道。
建议顺序:先补"看得见"(打点 + 一份 as-built 图纸),再补"不会坏"(中断监听 + Android 明示),最后再谈"更多功能"(网格 / 计时器 / 画幅 / 4K)。画质参数一条都不动。
② 现在长什么样(as-built)
三层
| 层 | 文件 | 干什么 |
|---|---|---|
| 原生引擎(iOS) | app/ios/Runner/HoopCamera.swift 2722 行 | AVFoundation 会话 + CoreImage/Metal 实时渲染链(滤镜/特效/背景/美化)+ Vision(人脸 / 证件框)。为什么自建:苹果 Deep Fusion / Smart HDR 只在 AVCapturePhotoOutput 的 quality 管线下给第三方,现成 Flutter 相机组件吃不到;系统相机采集页必弹 Retake 页 |
| 原生引擎(Android) | HoopCameraPlugin.kt 847 行 | CameraX:预览 / 拍照 / 翻转 / 变焦 / 证件框 / 人脸。没有录像、闪光、滤镜、DUAL、弱光、美化(grep 各 0 处) |
| Flutter 屏 | lib/screens/hoop_camera_screen.dart 1840 行(State 从 151 行到文件尾) | 四档 PHOTO / VIDEO / DUAL / NOTE、底排、魔术棒三档面板、胶卷条、竖屏锁、生命周期 paused/resumed |
| 接线 | chat_screen.dart ≈5600–5740 | 「+」一颗 Take photo & video → 一次 push 两套接法(拍照落 _EditorCaptionSendScreen,录像落 VideoEditorSendScreen);引擎起不来 → 回落微信相机 + 病历 snackbar |
功能清单(有 / 没有)
| 有 | 出处 |
|---|---|
| 四档:PHOTO / VIDEO / DUAL(前后同拍 + 双摄录像)/ NOTE(圆形视频留言 60s) | v1.511 / v1.562 / v1.512 / v0.860;录像上限 180s |
| 变焦 0.5 / 1 / 2 / 5 + 捏合,连点不重建相机、平滑过渡;0.5× 整机切超广角真设备(Jeff 定,不用虚拟双摄) | v1.513;HoopCamera.swift:163,500;守卫 camera_zoom_smooth_test |
| 点按对焦、闪光 auto/on/off、前后翻转不推倒重建(不让用户看新镜头找曝光) | focus() / setFlash() / swapCamera();v1.588 |
实时取景滤镜 45 款(和编辑器同一份 presetFiltersList,不抄第二份) | v1.044;camera_filter_strip.dart:14 |
| 特效 6(bloom / vignette / noir / comic / crystal / kaleido)+ 背景 4(虚化 / 单色 / 暗 / 丛林图);id 两端契约有守卫 | camera_look_options.dart:34–58;camera_look_ids_test |
| 弱光键:LowLightBoost + EV +1.5 + 帧率下限放到 12fps(暗处每帧多收 1.5 档光) | HoopCamera.swift:682–706 |
| 美化:皮肤检测 + 磨皮提亮,滑杆连续值,默认 0.5 | beauty_filter.dart;v0.847 |
| 快门即定格 + 2K 预览秒出(找 ISP 白要一张)+ 满血后台洗;零快门延迟 / 响应式拍照 / 快拍优先三开关 | HoopCamera.swift:932–975;锁参守卫 |
| 横拍出横片(UI 锁竖不锁片)、前摄镜像、竖屏锁带计数(相机+编辑器嵌套不误解锁) | hoop_camera_screen.dart 抬头 |
| 胶卷条(最近照片)+ 相册 HD 徽章;拍完直落编辑器(画笔/文字/裁剪/滤镜/表情,视频加 trim) | v0.666 / v1.603;video_editor_send_screen.dart |
| 引擎起不来自动回落微信相机,并把原因亮在 snackbar 上 | chat_screen.dart:5710–5716 |
热管理:人脸/分割算法按 thermalState 降频(critical 每 6 帧算一次) | HoopCamera.swift:2293–2300 |
| 震动反馈 11 处;切后台自动停采集、回来再开 | hoop_camera_screen.dart:365–376;v1.273 |
| 没有(iOS 系统相机 / WhatsApp 有的) | 备注 |
|---|---|
| 网格线、计时器、画幅切换(4:3 / 16:9 / 1:1) | 引擎里已有 aspect169 变量(HoopCamera.swift:930),Dart 端没有 UI —— 加 UI 不碰画质参数 |
| 4K / 60fps 录像、HEVC | 录像锁 .hd1920x1080(锁参守卫钉着);DUAL 录像 h264。属于画质参数区,要 Jeff 点头 |
| 人像模式(深度)、夜景、Live Photo、RAW、慢动作、延时、全景 | 夜景是苹果私有;人像需要深度数据链;其余是"要不要做"的产品问题 |
| 曝光滑杆(取景框旁那根)、HDR 开关 | 没有;EV 固定 +0.3(对齐原生取景亮度),弱光键 +1.5 |
| 扫码合在相机里 | 扫码在别处(加好友),相机内没有 |
无障碍:相机屏 Semantics 0 处 | VoiceOver 用户在相机里等于盲操作 |
③ 画质真相链 —— 拍到的和对方收到的不是同一张
这是这次评估里最该让你知道的一条。不是 bug,是三处各自合理的取舍串起来的结果。
| 环节 | 实际 | 出处 |
|---|---|---|
| 拍照 | 48MP(4032×3024 起,满血分辨率)、JPEG、每张用 .balanced 而不是 .quality:quality 在 48MP 每张要跑 1–3 秒深度融合(Jeff「转几圈」的真凶),balanced = 细节全保留、眨眼级,只让掉弱光深融合(WhatsApp 同款取舍) | HoopCamera.swift:940–943;抬头写的「Deep Fusion 只在 .quality 生效」指的是输出上限 maxPhotoQualityPrioritization,逐张是 balanced |
| 照片发送(默认) | 缩到最长边 1600、JPEG 80;点了 HD 才发原图 | chat_screen.dart:4234–4250;HD 走 original: r.hd |
| 录像 | 1080p30、稳像 auto、.mov | HoopCamera.swift:253,1013 |
| 视频发送 | 压到 720p(MediumQuality 在 iOS 是 ~480p,Jeff 实测「素质非常差」的根因,已避开);HD 对视频不生效,只有视频留言不压 | chat_screen.dart:4253–4263, 5289 |
意思是:Jeff 调到完美的 48MP,默认路径对方拿到的是 1600 像素;1080p 录像对方拿到 720p。WhatsApp 也是这么做的(默认压、HD 才原图),所以这是"和对标一样",不是"比对标差"。但视频那条 HD 不生效,和照片不一致 —— 用户点了 HD 发视频,拿到的还是 720p。这条值得修,而且不碰引擎。
④ 健壮性
| 项 | 现状 | 判断 |
|---|---|---|
| 权限 | authorizationStatus / requestAccess 有;Info.plist 三条文案中英双语 | ✅ |
| 切后台 / 回前台 | Dart 生命周期 paused 停、resumed 重开(hoop_camera_screen.dart:365);群通话那边 09-02 也补了后台停摄像头 | ✅ |
| 系统中断(来电、别的 App 抢相机、系统 UI 盖上来) | AVCaptureSessionWasInterrupted / InterruptionEnded / RuntimeError 0 处监听 | 🔴 来电挂了回来,取景框可能黑着不恢复;运行时错误(相机被系统回收)静默。加监听不碰画质参数 |
| 引擎起不来 | 回落微信相机 + 亮原因 | ✅ 做得好 |
| 热 | 只对人脸/分割算法降频;取景/录像不降 | 🟡 录 3 分钟 1080p + 实时滤镜的发热没人管;iPhone 自己会限频,不至于崩 |
| 方向 / 镜像 | 反复出事区:自拍在编辑器躺着(v0.811)、前摄滤镜层躺倒 90°(v1.560)、横屏档位字转动(v1.033) | 🟡 现在都修了,有守卫;每次动镜头/图层都要重跑这几条 |
| DUAL | 快门闪退过一次(v1.599:多摄把镜头格式换走了没换回);现在 rememberFormat / restoreDeviceFormats 有;不支持的机型整档不画 | 🟡 多摄是最复杂的一段(1063–1640 行),真机机型覆盖靠 Jeff 一台 |
| Android | 只拍照;切到 VIDEO / DUAL / NOTE 走 startVideo 会 PlatformException —— Dart 端只接了 DUAL 录像那一处(hoop_camera_screen.dart:660,弹「不支持」),普通录像那条没有 Android 分支 | 🔴 若 Android 在售,要么补录像,要么 Android 上不画那三档、明示回落 |
⑤ 工程质量
| 项 | 现状 |
|---|---|
| 测试 | 17 个文件 202 条,2026-09-03 刚跑全绿。覆盖:底排像素级版式(照 Jeff 三张截图量的)、切档、翻转不重建、变焦丝滑、实时滤镜、look id 两端契约、DUAL 取景、胶卷条、相册钮、横屏文字、视频留言、eKYC、后台停摄像头 |
| 锁参守卫 | camera_engine_locked_test.dart 把 Jeff 调的每一行钉成字面量(quality 上限 / 满血分辨率 / ZSL 三开关 / EV / 拍照 preset / 真广角单设备);红了是让你去问,不是改守卫。这是全仓最好的一份"人的判据变成机器守卫" |
| "坏刀"文化 | CHANGELOG 里相机的提交多数写了「三把坏刀各红各的」—— 守卫的牙是验过的,不是假绿灯 |
| 原生侧验证 | Swift 只有 swiftc -c,没有真机自动化;真机验收 = Jeff 一台 iPhone 16 Pro Max。多摄 / 超广角 / 48MP 这些能力机型差异大,老机型(无超广角、12MP)路径没人跑过 |
| 打点 | 0 处。相机开了几次、哪档用得多、DUAL 有没有人用、滤镜哪款热、拍完发出去的比例 —— 全都不知道。Tools 那边 P1 就有打点表,相机没有 |
| 文档 | docs/ 里没有相机图纸。全部知识在两个文件的抬头注释 + 345 条 CHANGELOG 里。新人要懂相机只能读 4500 行代码 |
| 文件体量 | Swift 单文件 2722 行(多摄 600 行、渲染链 400 行、人脸/证件 300 行混在一起);Dart 屏 1840 行 State 一个类。能跑,但下一个人加东西要读完整个文件才敢动 |
| 翻译 | cam_* 键 en / zh 各 25,对齐 |
⑥ 历史:哪儿反复出事
345 条里挑出的事故线(新→旧):
- v1.599 DUAL 按快门闪退 —— 多摄把镜头格式换走没换回
- v1.552 变焦那刀退回 —— 用了虚拟双摄,Jeff 一个字「退」;由此长出锁参守卫和铁律 29
- v1.560 前摄滤镜/特效/背景层躺倒 90°
- v1.192 取景框黑线横穿快门;v1.170 弱光把取景框钉死;v1.054 取景渲染路搬下主线程(认人像烤热手机)
- v0.811 自拍在编辑器里躺着 —— 烤方向漏了镜像四档
规律:出事的从来不是画质,是方向/镜像和多摄切换的状态恢复。这两块是"改一处、另一处静默坏"的典型,现有守卫覆盖了已知的坑,新坑靠 Jeff 真机。
⑦ 对标
| HOOP | iOS 系统相机 | ||
|---|---|---|---|
| 画质管线 | 48MP balanced,满血分辨率,ZSL | 系统相机组件(不吃满血) | 私有代理图+后台洗,quality |
| 确认页 | 零,快门即编辑器 | 有 | — |
| 实时滤镜 / 特效 / 背景 | 45 / 6 / 4 | 少量滤镜 | Photographic Styles |
| DUAL 前后同拍 | 有(BeReal 式) | 无 | 无 |
| 视频留言 | 有,60s | 有 | — |
| 弱光键 | 有 | 无 | 夜景自动 |
| 网格 / 计时器 / 画幅 | 无 | 无 / 无 / 无 | 有 |
| 4K / 60fps | 无(1080p30) | 有 | 有 |
| 发送默认画质 | 1600px / 720p,HD 原图(视频 HD 不生效) | 压缩,HD 原图 | — |
| Android | 只拍照 | 全 | — |
⑧ 建议(不动画质参数)
| 级 | 做什么 | 为什么 | 动不动引擎 |
|---|---|---|---|
| P0 | 打点:open / mode / shot / send 四个事件,照 Tools 的 chat_tool_events 一张表 | 没数据就没法说"相机好不好用";DUAL / 滤镜 / 弱光这些功能值不值得继续投,全靠它 | 不动 |
| P0 | 写一份 docs/CAMERA.md as-built:三层、四档、画质真相链、锁参清单、方向/镜像的坑、机型矩阵 | 现在唯一的图纸是代码抬头;下一个动相机的人没有地图 | 不动 |
| P1 | 引擎听 AVCaptureSessionWasInterrupted / InterruptionEnded / RuntimeError,中断结束自动 resume、出错走现有回落 | 来电 / 被抢相机之后取景黑着是最常见的"相机坏了"投诉 | 加监听,不改参数 |
| P1 | 视频 HD 生效:点了 HD 不压 720p | 和照片行为对齐;现在 HD 对视频是假开关 | 不动(发送层) |
| P1 | Android 明示:没有的档不画,或补 CameraX VideoCapture | 看 Android 有没有在售;现在切档会抛异常 | Android 侧 |
| P2 | 网格线、计时器、画幅 4:3/16:9(引擎已有 aspect169) | 系统相机基本件;纯 UI | 画幅那条碰输出裁切 —— 先问 Jeff |
| P2 | 相机屏 Semantics(快门 / 翻转 / 档位 / 闪光) | 无障碍 0 → 至少主控件可读 | 不动 |
| P3 | 4K / 60fps / HEVC、人像深度 | 画质参数区,要 Jeff 点头,而且发送压 720p 的前提下 4K 意义不大 —— 先做 P1 的视频 HD | 动 |
| P3 | 拆文件:Swift 多摄 / 渲染链 / 人脸证件各自成文件(照 call_engine 拆法);Dart 屏拆底排 / 魔术棒 / 录制 | 可维护性;拆的时候锁参守卫和 202 条测试是安全网 | 搬家不改行为 |
不建议做的:为了"功能比苹果多"去加全景 / 慢动作 / 延时 —— 聊天相机的判据是"拍了就发",不是"取代系统相机"。DUAL 和视频留言是对的方向(聊天场景独有),往那边长。
怎么核的
grep 引擎能力关键词 / 读 HoopCamera.swift 抬头、capturePhoto、startVideo、applyLowLight、thermal 段 / 读 hoop_camera_screen.dart 抬头与生命周期 / chat_screen.dart 4215–4280、5600–5740 / camera_look_options.dart / CHANGELOG 相机标题全列 / flutter test 17 个相机文件 202 条(2026-09-03)/ pro_image_editor 13.2.0 presetFiltersList 45 款。没跑真机。