-
- SummaryWorker: 后端从 SharedPreferences 读 ChatTarget.id(local-2b/4b/hermes), 经 ChatConfig 解析端点/model(与对话共用配置),不再写死 2B。 - SummaryProgress:新增 worker→UI 进度 singleton(同进程 StateFlow), worker 每步发 line(开始/会话生成中/✅完成 Ns/❌失败/跳过统计)。 - SummariesTab:加「纪要模型」下拉(2B/4B/Hermes,存 prefs)+ 进度 console (滚动框,最新在上)+「现在跑一次」运行中转圈禁用。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
-
- HermesClient: 加 chat_template_kwargs.enable_thinking=false —— 纪要走本地 Qwen3.5,不需要 <think>,关掉省 token/发热(Kimi 等不认会忽略)。 - SpeakerClusterer: MATCH_THRESHOLD 0.5 → 0.55 —— 0.5 偏松过度合并 (4B 测试「说话人4」吃了 23 段),收紧分得更细。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
-
- ChatClient: 本地 Qwen 目标加 chat_template_kwargs.enable_thinking=false (Hermes/Kimi 不认会忽略,故只对 LOCAL 加);修 parseDelta —— delta.content 为 JSON null(思考阶段/role-only 首块)时跳过,不再因 org.json.optString 返回字面 "null" 污染回复开头。 - SummaryWorker: 纪要后端解耦到本地 llama-swap(LLM_BASE_URL=8080 / LLM_MODEL="2b"), 独立于 keys.properties——那个留给聊天的 Hermes 选项(8642 网关 → Kimi)。 - AppDatabase: 删掉 fallbackToDestructiveMigration 改 fail-loud(已有 MIGRATION_2_3; 以后改 schema 不写迁移直接抛异常,绝不再静默清掉真实录音)。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
-
- SummaryScheduler.runNow 改 enqueueUniqueWork(KEEP):在跑/排队时重复触发直接忽略, 避免并发跑出重复纪要 - SummaryWorker:单篇喂 LLM 的转写条数上限 150,超长会话均匀抽样(覆盖整段、时间戳 保真),防止 prompt 撑爆上下文 / 端侧 prefill 过慢 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
-
- 首页 tab 改名「录音」,新增「对话」tab(ChatGPT 式:抽屉历史 / 气泡 / 流式 / 输入框) - chat/ChatConfig:聊天对象 = OpenAI 兼容端点 + model;本地 2B/4B 共用一个 llama-server 端口按 model 热切换,Hermes 走 gateway 8642;本地 baseUrl/model 名 app 内 ⚙ 可改 - chat/ChatClient:SSE 流式逐 token,端点不支持流式时自动降级整段解析 - 持久化到 Room:chat_conversations / chat_messages 两表,切换对象记到会话 targetId - data:AppDatabase 加 MIGRATION_2_3(纯增量加表),修复 fallbackToDestructiveMigration 在 24/7 RecorderService 重装时静默清库的风险 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
-
- 声纹方案 B:新增 SpeakerClusterer 在线增量聚类,按余弦相似度自动发现 「说话人N」,capped 滑动均值精修质心并写穿 speaker_profiles; reclusterAll() 一键对历史段重聚类。不改 schema。 - UI 重构为 4 个底部 Tab:首页 / 时间轴 / 声纹 / 纪要。 - 时间轴:FTS 中文搜索 + 按说话人/时间范围/未匹配低置信筛选 + 排序切换, 全 CRUD(删段 / 改派说话人 / 订正转写 / 记为新说话人),批量选择删除 / 导出。 - 声纹 Tab:说话人列表(归属段数)、重命名 / 合并 / 删除、点击筛选时间轴。 - 真暂停:RecorderService 加 PAUSE/RESUME,停采集但 paraformer/VAD/聚类器常驻, 秒级恢复;RecorderState 加 isPaused。 - 纪要会话化:SummaryWorker 改为按时间间隔(UI 可调,默认 10min)自动切会话, 每场连续录音单独成篇,只总结已结束会话,时间范围重叠判重幂等。 - 纪要列表折叠显示「从 xx 到 xx · N 段 · 说话人名单 · 时长」,点开看 markdown。 - 纪要要点带 [HH
ss] 来源时间戳,点击跳回时间轴对应段并高亮(含跨午夜处理)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
-
设备侧 hermes api_server platform 配置(HANDOFF §五新增详细步骤): - ~/.hermes/.env 加 API_SERVER_ENABLED + HOST + PORT + KEY + MODEL_NAME - pip install anthropic(kimi-for-coding 走 Anthropic-compat 协议层) - setsid + disown 启动避免 adb shell 退出时 SIGTERM 杀掉 gateway App 侧: - BuildConfig 增加 HERMES_API_URL / HERMES_API_KEY / HERMES_MODEL - keys.properties.example 同步样本 - HermesClient.kt: minimal OkHttp 客户端,POST /v1/chat/completions + Bearer auth;JSONObject 拼请求 / 解 choices[0].message.content - SummaryWorker.kt (CoroutineWorker): - 滑动 1h 时间窗;speech < 60s 直接 skip - 拉 Transcript + speaker name 拼用户提示 - system prompt 要求 markdown 出「主题概括 / 关键要点 / 人物 / 地点 / 待办」 - 写 Summary 表(windowStartTs, windowEndTs, markdown, model) - SummaryScheduler.kt: enqueueUniquePeriodicWork 每小时(KEEP)+ OneTimeWorkRequest(按钮触发) - LifelogApp.onCreate 启动时 schedulePeriodic - MainActivity: 新「纪要」section + 「现在跑一次」按钮 + SummaryCard 列表 - AndroidManifest android:networkSecurityConfig 开 127.0.0.1 + localhost cleartext 豁免(OkHttp 默认禁 HTTP,loopback 也禁) 实测:60min 窗 / 172 段 / 709s 语音 / Kimi 14.3k prompt token / 649 completion → 一份 markdown 纪要正确分辨出「电影解说 + 修仙网文」两段 内容,按要求列出主题/要点/人物/地点/待办 5 个 section。 HANDOFF.md §五 LLM 纪要 worker 移到「已完成」;下一档是存储 TTL / 设置页 / 多 anchor 平均 / lemonPCRM 回链 / hermes 自启。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
-
闭环 v0.3 的两个自然延伸: - SegmentPlayer.kt: MediaPlayer 包装,Opus 段原音播放 Android API 21+ MediaPlayer 原生解码 Ogg-Opus,验证 logcat 见 「MetaDataBase: OpusHead.. mime: audio/opus brte: 16000 #chn: 1」 音频属性设 USAGE_MEDIA + CONTENT_TYPE_SPEECH,单实例复用 - SpeakerMatcher.kt: backfillAll() 遍历所有有 embedding 的段,重算 最近邻 profile + cosine 距离;threshold 0.5 复用 RecorderService 里的逻辑;只更新变化的行(避免 Room 全表写) enroll 落库后 MainActivity 自动 launch 调用 - MainActivity: 时间轴 tap row 不再直接弹 enroll dialog,改为 ModalBottomSheet 出「▶ 播放原音 / 记为说话人」二选一 TimelineRow 加 isPlaying 状态指示,正在播放的段前缀 "▶ " DisposableEffect 在 onDispose 调 player.stop() 防泄漏 HANDOFF.md §五 更新(v0.4 移到「已完成」),加 SegmentPlayer.kt + SpeakerMatcher.kt 到文件清单。 实测(Pixel 8 Pro,电影 audio 输入): - 段 #11-14 显示 "未匹配 (0.09-0.13)" — 电影角色声纹与 Me anchor cosine 远低于 0.5 → 正确拒绝匹配 - 段 #13 19s opus 文件 MediaPlayer 立刻播放,文件 ~38 KB Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
-
声纹(用户语音里提了 3 次的 feature): - SpeakerEmbedder.kt: sherpa-onnx SpeakerEmbeddingExtractor 包装 3dspeaker CAMPPlus 16k zh-cn 模型(28 MB int8 ONNX),192 维 embedding - ModelDownloader.ensureSpeakerModel(): 首次启动从 hf-mirror.com 自动下 - Segment 实体加 embedding/speakerId/speakerSim 三列 - SpeakerProfile 实体(id/name/embedding/sampleCount/createdAt)+ SpeakerDao - RecorderService.handleSegment 每段算 embedding + 与已注册 profiles 算 cosine,threshold ≥0.5 才 assign - RecorderService 通过 speakers.observeAll() 实时 reload profile 缓存 - MainActivity 点时间轴段 → AlertDialog 输入名字 → 创建 SpeakerProfile - TimelineRow 显示 "name (sim=0.xx)" 或 "—" / "未匹配 (0.xx)" FTS4 全文搜索: - TranscriptFts 实体用 @Fts4(contentEntity=Transcript, tokenizer="unicode61") Room 自动建虚表 + 同步触发器,unicode61 把中文字当 token - searchTimeline DAO 查询 JOIN transcript_fts MATCH :query - MainActivity 顶部 OutlinedTextField 实时切换 timelineFlow - sanitizeFtsQuery 给每 token 加 * 做前缀匹配,剥掉 FTS metachars Schema: - AppDatabase v1 → v2 + fallbackToDestructiveMigration(v0.3 dev 数据可丢) - 新增 SpeakerProfile + TranscriptFts 虚表 + Segment 三列 HANDOFF.md §五 更新:声纹 + 搜索移到「已完成」,下一档变成 LLM 纪要 worker / 存储 TTL / 段播放 / 多 anchor 平均 / lemonPCRM 回链。 实测(Pixel 8 Pro Tensor G3,Android 16): - speaker model load: 441 ms - embedding 计算开销 ~10-30 ms/段,跟 paraformer 同期完成 - enroll "Me" anchor → 后续段在 logcat 见 "speaker=Me sim=0.xx" Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
-
让 v1 真能脱离开发环境 24/7 跑的最后三公里: - SegmentWriter 改 Opus(MediaCodec audio/opus encoder + MediaMuxer OGG) ~17× 压缩,~2 KB/s 实测(vs WAV 32 KB/s) 存储预算:8h 语音/天 → ~57 MB/天,~1.7 GB/月(vs WAV 51 GB/月) ffprobe 验证 codec_name=opus, channels=1, OggS magic OK - BootReceiver 监听 BOOT_COMPLETED / LOCKED_BOOT_COMPLETED / QUICKBOOT_POWERON,try-catch 兜底 Android 14+ FG service 限制 - MainActivity 加电池豁免行:dumpsys deviceidle whitelist 实时检测, 未豁免时给「申请豁免」按钮,触发系统 RequestIgnoreBatteryOptimizations 对话框;ON_RESUME 生命周期观察让从设置页回来 UI 自动刷新 - AndroidManifest: + REQUEST_IGNORE_BATTERY_OPTIMIZATIONS 权限 + BootReceiver 注册(含 3 个 boot 相关 action) HANDOFF.md §五 更新待办(v0.2 三项移到「已完成」),加存储预算 + Android 14 BOOT_COMPLETED caveat 段落(Pixel 8 Pro 实测能自动续上, 前提 app 至少开过一次 + RECORD_AUDIO 已授)。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
-
Pixel 8 Pro 上的本地 lifelog 应用,v1 核心闭环: - 前台服务 (foregroundServiceType=microphone) + AudioRecord 16k mono PCM - Silero VAD on-device 切段(500ms 静音切、300ms 最短、30s 强切) - sherpa-onnx + paraformer-zh int8 本地 ASR Tensor G3 实测 ~25× realtime,<200ms 处理 1-10s 段 whisper-small 0.6× 跑不动,paraformer 是甜点选型 - Room (Segment + Transcript + Summary) + Compose 时间轴 LazyColumn UI - 232 MB 模型首次启动从 hf-mirror.com 下载到 app filesDir - 讯飞 中文识别大模型 WebSocket 客户端备用(云复核 fallback) 依赖: - sherpa-onnx v1.13.2 Android jniLibs (arm64-v8a, ~34 MB) - Silero VAD ONNX (~629 KB),sample.wav (3 MB) 内嵌资源 - AGP 8.7.3 / Kotlin 2.1 / Compose BOM 2024.12.01 / Room 2.6.1 后续待办(按用户语音里提到的优先级):声纹识别 / Opus 编码 / FTS5 中文搜索 / hermes-Kimi 纪要 worker。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>