From bb2506dabb91e686d3dc552377a88236b9a0f066 Mon Sep 17 00:00:00 2001 From: yibo Date: Tue, 2 Jun 2026 23:27:32 +0800 Subject: [PATCH] docs(CLAUDE.md): 加 lifelog-recorder 章节 + 多子项目顶层映射 --- CLAUDE.md | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+), 0 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index a4163a3..bb24955 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,10 +4,22 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## 项目概述 +本仓库(`aipcrm/`)现在托管 **3 个互相关联但独立的子项目**: + +| 子项目 | 路径 | 形态 | 状态 | +|---|---|---|---| +| **lemonPCRM** | `server/` + `frontend/` + `packages/` | Node.js + Express 后端 + 静态前端 | 主线 | +| **wechat_plain** | `wechat_plain/` | Android Xposed/A11y 模块 + Pixel 部署脚本 | 主线 | +| **lifelog-recorder** | `lifelog-recorder/` | Pixel 原生 Android 应用(Kotlin + Compose) | v0.1 (2026-06) | + **lemonPCRM** — lemonAI 出品的 Local-First AI 个人人脉管理系统(Personal CRM)。以人为中心、以对话为链接,通过知识图谱管理微信、LinkedIn、X 等多平台社交关系,将每个联系人与其社媒动态、会议纪要、文件、照片全面关联。 AI 对话与编排层基于 ACP 协议驱动本地 Claude CLI 进程,提供单 Agent 执行和 Master → Sub-Agent 多轮编排能力。Node.js + Express,无数据库依赖(使用 Node 22.5+ 内置 `node:sqlite`),数据完全本地化。 +**wechat_plain** — Pixel 上微信 bot 的 Xposed/A11y 落地(A11y UI 自动化是当前唯一能真把消息推进 message 表的发送链路;详见下文 §微信集成架构)。 + +**lifelog-recorder** — Pixel 8 Pro 上的 24/7 录音 + 本地中文 ASR + 时间轴 lifelog 应用(2026-06 新增,详见下文 §lifelog-recorder)。 + ## 常用命令 ```bash @@ -151,6 +163,100 @@ Launcher (ProcessLauncher spawn / NoneLauncher 无操作) 详见 `server/services/wechat/README.md`。 +## lifelog-recorder(Pixel 8 Pro 24/7 录音 + 本地中文 ASR,v0.1) + +> 完整接手地图、踩坑清单、命令速查见 `lifelog-recorder/HANDOFF.md`。本节只勒住整个项目的**架构骨架 + 关键决策来源**,不重复细节。 + +### 项目目标 + +把 Pixel 8 Pro 当成**永远开机的麦克风**:7×24 后台录音 → VAD 切段 → 中文 ASR 转文字 → 入库 → 按时间轴显示和搜索 → LLM 总结成纪要。最终目的是把所有「我说过 / 别人对我说过」的内容沉淀成可搜索、可回放的个人记忆库,下接 lemonPCRM 的人脉图谱(某段语音 → 某联系人 → 某项目)。 + +约束:**完全本地 / 零云端依赖 / 月成本 0 元 / 隐私走 0 网络**。 + +### 架构骨架 + +``` +Foreground Service (foregroundServiceType=microphone, WAKE_LOCK partial) + └ AudioRecord 16k mono PCM16 (VOICE_RECOGNITION source, no AGC/NS) + └ Silero VAD ONNX (sherpa-onnx 包装,500ms 静音切 / 30s 强切) + └ paraformer-zh int8 ONNX (sherpa-onnx JNI, 4 threads, 25× realtime) + └ Room SQLite (Segment / Transcript / Summary) + └ Compose LazyColumn 时间轴 UI (倒序,按 startTs) + ↓ (待办) hermes gateway 8642 → Kimi → 纪要 Worker +``` + +技术栈:Kotlin 2.1 + Compose BOM 2024.12.01 + Room 2.6.1 + WorkManager 2.10 + OkHttp 4.12,AGP 8.7.3,minSdk 30 / targetSdk 35(Android 14 强制 `foregroundServiceType` 起步),arm64-v8a 单 ABI。 + +### 接口 + +**内部组件接口**(pipeline,详见 `lifelog-recorder/HANDOFF.md` §四): + +| 上游 | → | 下游 | 数据形式 | +|---|---|---|---| +| `AudioCapture` | SharedFlow | VAD | `FloatArray` 30ms 帧 (512 samples) | +| `Vad.acceptWaveform()` | poll | `Vad.front()` / `pop()` | `SpeechSegment(start, samples: FloatArray)` | +| `ParaformerEngine.transcribeFloat()` | sync | — | `OfflineRecognizerResult(text, tokens, timestamps, lang, emotion, event)` | +| `SegmentWriter` | sync | filesystem | `filesDir/segments/YYYY-MM-DD/HH-MM-SS-MS.wav` | +| `Repository.segments/transcripts` | suspend | Room | DAOs in `data/Daos.kt` | + +**外部接口**: +- `ModelDownloader` → `https://hf-mirror.com/csukuangfj/sherpa-onnx-paraformer-zh-2023-09-14/`(断点续传,fallback huggingface.co) +- `XfyunIatClient` → `wss://iat.xf-yun.com/v1`(讯飞大模型,**仅作云复核 fallback**) +- 未来 Summary Worker → `http://127.0.0.1:8642/v1/chat/completions`(hermes gateway 转发到 Kimi) + +**对外暴露的 IPC**:`RecorderService` 仅做自启/暂停(`startForegroundService` / `stopService`),状态走 `RecorderState` (StateFlow) 推给 UI;没有 binder/广播接口。 + +### 历史沿革 / PoC 失败与成功记录 + +> 这一节是**为什么选了 paraformer 而不是 whisper / 云 ASR** 的完整溯源。后面 session 想换技术栈前必读。 + +**Round 1 — 全云 ASR 路线(弃)**:最初想用「VAD 段 → 上传讯飞 / 百度 / Groq Whisper」流式 ASR。讯飞「中文识别大模型」WebSocket 客户端已经写完(`asr/XfyunIatClient.kt`,鉴权 + 三段帧协议 + 增量结果解析),但发现按次计费下 24/7 用量会冲到月 5000+ 元。「讯飞流式听写区间包 80 元/月 unlimited」是**消费端「讯飞听见」App 的卡,不是开发者 API**——这是用户和我都踩过的坑。 + +**Round 2 — whisper.cpp on-device(弃)**:在 Pixel 8 Pro Termux 编了 whisper.cpp + NEON 优化,跑 95s 中文 TTS sample: + +| 模型 | 线程 | RTF | 速度 | 中文质量 | +|---|---|---|---|---| +| ggml-tiny.bin | 4 | 0.26 | **3.8× realtime** | ❌ 输出乱码「战亡未来一年」,中文不可用 | +| ggml-small-q5_1.bin (181 MB) | **8 (最快)** | 1.66 | **0.60× realtime** | ✓ 转写正确 | +| ggml-small.bin (fp16, 465 MB) | 4 | 1.76 | 0.57× | 同 q5_1(量化省的全被 ARM dequant 吃回) | + +**结论**:whisper-small **任何配置都 < 1× realtime**,连续录会越积越多。tiny 够快但中文崩。**on-device whisper 路线直接砍掉**。 + +**Round 3 — sherpa-onnx + 中文专门优化模型(采用)**:阿里 DAMO 的 paraformer-zh 跟 SenseVoice 都是 ONNX 部署、Android 友好。同样 95s sample: + +| 模型 | 测试环境 | RTF | 速度 | 备注 | +|---|---|---|---|---| +| paraformer-zh int8 (232 MB) t=4 | proot Ubuntu | 0.068 | **14.7× realtime** | 选定 | +| paraformer-zh int8 t=8 | proot | 0.099 | 10.1× | 8 线程反而慢,X3+A715 协调开销 | +| SenseVoice int8 (228 MB) t=4 | proot | 0.092 | 10.9× | 带情绪/事件 metadata,但慢 | +| **paraformer-zh int8 t=4** | **真机 Android app** | **0.048** | **20.94× realtime** | proot 摘掉后再快 43% | +| **paraformer-zh int8 t=4** | **真实活语音(用户对手机说)** | — | **20-32×** | 1-10s 段,~50-300ms 转写 | + +**结论**:on-device paraformer 完胜。月成本 0 元,延迟 <300ms,隐私零网络。讯飞客户端代码留作云复核 fallback。 + +### 关键坑(接手必读) + +1. **不要把 .onnx 当 asset mmap**:sherpa-onnx v1.13.2 native code 对 asset 压缩兼容差,silero VAD 直接 SIGSEGV。已加 `androidResources.noCompress.add("onnx")` 但保险起见在 `RecorderService.runPipeline` 里把 VAD 模型从 assets 拷到 `filesDir` 后再用 file path 加载。 +2. **silero_vad.onnx 别从 snakers4 的 GitHub raw 拉**:会被 LFS 重定向成 HTML。用 `https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/silero_vad.onnx`。 +3. **Tensor G3 paraformer 线程甜点 = 4,不是 8**。 +4. **AID_INET (3003) gotcha**:跨 root + adb 调试 Termux 用户态时必须 `su -G 3003 10288 -c "..."`,否则 DNS 全断。详见 `~/.claude/projects/-Users-yibo-Documents-aipcrm/memory/magisk-su-android-inet-group.md`。 +5. **`keys.properties` gitignored**:讯飞凭证从这里读到 `BuildConfig.XFYUN_*`。模板 `keys.properties.example`。 +6. **232 MB paraformer 模型不进仓库**:首次启动从 hf-mirror.com 下到 `app.filesDir/models/paraformer-zh/`。dev 加速可以预先 `adb push` 进去(HANDOFF.md §三)。 + +### 未来计划(按优先级) + +完整待办、估时、技术路线见 `lifelog-recorder/HANDOFF.md` §五。摘要: + +- 🔥 **Opus 编码**(WAV 24/7 跑 ~3 GB/天,必须) +- 🔥 **自启动 + 电池白名单**(BOOT_COMPLETED + REQUEST_IGNORE_BATTERY_OPTIMIZATIONS,让 v1 真能脱离 dev 环境跑) +- ⭐ **声纹识别 / speaker diarization**(用户语音里提了 3 次,sherpa-onnx `Speaker.kt` 现成可用) +- ⭐ **FTS5 中文搜索**(Room + ICU tokenizer) +- ⭐ **LLM 纪要 Worker**(cron + idle 触发 → hermes gateway → Kimi) + +### 与 lemonPCRM 的关系 + +目前**完全独立**——lifelog-recorder 的 Room DB 跟 lemonPCRM 的 GraphStore 没打通。未来计划:把 Transcript / Summary 表里的实体(人名 / 地名 / 项目)抽到 GraphStore 当 `MENTIONED_IN` 边,让你的「某次会议说了什么」可以从图谱里反查。这是 v2 范畴。 + ## 注意事项 - `server/src/standalone-entry.js` 的 `loadConfig()` 优先读 `backends.json` + `agents.json`,无需数据库。 -- libgit2 0.21.4