1. ## 🎯 当前使用的ASR模型 ### 模型名称:SenseVoice (RKNN版本) ### 模型架构: - 编码器 : sense-voice-encoder.rknn - RKNN格式的神经网络模型 - 嵌入层 : embedding.npy - 词嵌入矩阵 - 分词器 : chn_jpn_yue_eng_ko_spectok.bpe.model - BPE分词模型 ### 模型特点: 1. 多语言支持 - 支持中文、日文、粤语、英文、韩文 2. RKNN加速 - 针对RK3588等Rockchip芯片优化 3. ITN支持 - 启用了逆文本归一化(Inverse Text Normalization),提高数字/日期识别准确性 2. ## TTS模型信息 ### 模型名称 Sherpa-ONNX VITS - 中文版本(sherpa-onnx-vits-zh-ll) ### 模型文件 位于 app/src/main/assets/tts_model/sherpa-onnx-vits-zh-ll/ 目录: - model.onnx - ONNX格式的声学模型 - tokens.txt - 音素/字符映射表 - lexicon.txt - 发音词典 - phone.fst - 音素转换规则 - date.fst - 日期归一化规则 - number.fst - 数字归一化规则 - new_heteronym.fst - 多音字处理规则 3. ## VAD模型信息 ### 模型名称 Silero VAD (Voice Activity Detection) ### 模型文件 - 文件路径: assets/vad_model/silero_vad.onnx - 格式:ONNX格式 4. 模型部署对比 模型 类型 格式 RKNN加速 推理设备 配置 ASR SenseVoice .rknn ✅ 是 NPU RKNN Runtime VAD Silero VAD .onnx ❌ 否 CPU provider="cpu" TTS Sherpa-ONNX VITS .onnx ❌ 否 CPU ONNX Runtime ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ AudioProcessor │────▶│ VadManager │────▶│ ASR Queue │ │ (录音+增益) │ │ (语音活动检测) │ │ (Channel队列) │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ ┌─────────────────────────┘ ▼ ┌─────────────────┐ │ runAsrWorker │ │ (协程工作器) │ └─────────────────┘ │ ▼ ┌─────────────────┐ │ SenseVoice │ │ (RKNN推理) │ └─────────────────┘ 5. live2d, Haru的动作 由于没有官方文档,基于Live2D模型的常见设计模式,我建议以下映射: ### 🎭 开心类情绪 - haru_g_m22 眯眼微笑 - haru_g_m21 跳动微笑 - haru_g_m18 手收背后微笑 - haru_g_m09 微微鞠躬 - haru_g_m08 深深鞠躬 ### 😢 伤心类情绪 - haru_g_m25 - 扁嘴 - haru_g_m24 - 低头斜看地板,收手到背后 - haru_g_m05 扁嘴,张开双手 - haru_g_m16 双手捧腮,思考 ### 😠 愤怒类情绪 - haru_g_m11 双手交叉,摇头,扁嘴 - haru_g_m04 双手交叉,点头 - haru_g_m03 双手交叉,点头 ### 😌 平和类情绪 - haru_g_m15 双手交叉在胸前 - haru_g_m07 举起左手 - haru_g_m06 举起右手 - haru_g_m02 双手放到背后 - haru_g_m01 点头 ### 😲 惊讶类情绪 - haru_g_m26 - 后退一步(适合:惊讶、吃惊) - haru_g_m12 摆手,摇头 ### 😕 困惑类情绪 - haru_g_m14 身体前倾,皱眉 - haru_g_m13 身体前倾,双手分开 ### 害羞 - haru_g_m19 脸红微笑 ### 担心 - haru_g_m20 手指点腮,思考,皱眉 ### ❤️ 关心类情绪 - haru_g_m17 靠近侧脸 6. 其实可以抄一下讯飞的超脑平台的功能: https://aiui-doc.xf-yun.com/project-2/doc-397/ 7. 人脸检测使用的是RKNN zoo里的 retinaface模型,转成了rknn格式,并且使用了wider_face的数据集(验证集)进行了校准,下载地址: https://www.modelscope.cn/datasets/shaoxuan/WIDER_FACE/files 8. 人脸识别模型是insightface的r18模型,转成了rknn格式,并且使用了 lfw 的数据集进行了校准,下载地址: https://tianchi.aliyun.com/dataset/93864 9. 本地LLM,用的是 rkllm 模型,由于内存限制,只能用较小的模型,如 Qwen3-0.6B-rk3588-w8a8.rkllm。 10. 数字人交互设计说明书(优化版) 核心原则 * 尊重用户:给用户足够的反应时间,不抢话,不催促。 * 主动但不打扰:用户沉默时适度引导,但不强行交互;数字人拥有独立的内心活动,即便无人交互也保持“生命感”。 * 个性化:记住每个用户的偏好、名字、对话历史,并据此调整问候和回应。 * 动作同步:Live2D人物的表情与动作与当前状态、情绪、内心活动相匹配。 * 持续内心活动:数字人即使在没有用户时也会进行“回忆”或“思考”,并通过文字展现,用户可随时打断并询问想法。 状态定义 [空闲状态]:无人,数字人无内心活动(省电模式)。 [回忆状态]:无人,数字人正在根据记忆产生内心想法,通过表情表现。 [问候状态]:检测到用户,主动打招呼。 [等待回复状态]:问候后或对话间隙,等待用户回复。 [对话状态]:正在与用户交流,根据情绪调整动作。 [主动引导状态]:用户沉默但仍在画面中,数字人主动开启新话题。 [告别状态]:用户离开画面,数字人告别。 [空闲状态] 动作 : haru_g_idle (待机动作) ↓ 检测到人脸 → 等待1秒(让人脸稳定) ↓ [问候状态] 动作 : - 认识用户: haru_g_m22 (高兴动作) - 不认识: haru_g_m01(中性动作) AI问候(根据是否认识,节日,时间等因素个性化) 启动20秒计时器 ↓ [等待回复状态] 动作 : haru_g_m17 ↓ ├─ 如果用户按下了麦克风按钮 → 进入[对话状态] │ 动作 :根据对话情绪动态调整 │ - 开心: haru_g_m22 / haru_g_m21 / haru_g_m18 / haru_g_m09 / haru_g_m08 │ - 悲伤: haru_g_m25 / haru_g_m24 / haru_g_m05 / haru_g_m16 │ - 惊讶: haru_g_m26 / haru_g_m12 │ - 愤怒: haru_g_m04 / haru_g_m11 / haru_g_m04 │ - 平静: haru_g_m15 / haru_g_m07 / haru_g_m06 / haru_g_m02 / haru_g_m01 │ AI根据内容回应,持续直到用户说“再见” │ ↓ │ (用户离开)→ 进入[告别状态] │ └─ 如果20秒内无回复 ↓ 检查用户是否还在画面 ↓ ├─ 如果还在 → [主动引导状态] │ 动作 : haru_g_m15 / haru_g_m07 (中性动作) │ AI开启轻松话题(如“我出一道数学题考考你吧?1+6等于多少?”) │ 等待10秒 │ ↓ │ ├─ 回复 → 进入[对话状态] │ └─ 没回复 → 换话题,如,我们上完厕所应该干什么呀?最多重复3次 │ 动作 : haru_g_m22 / haru_g_m18 │ (重复尝试)→ 再次等待10秒 │ (3次后仍无回复)→ 回到[等待回复状态] │ └─ 如果已离开 → [告别状态] 动作 : haru_g_idle (告别后待机) ↓ 3秒后 → 回到[空闲状态] [空闲状态] (长时间无人) ↓ 如果持续30秒无人 → 进入[回忆状态] 动作 : haru_g_m15 回顾之前的聊天记录,生成想法,不发声,把想法显示在屏幕上 ↓ 如果检测到人脸 → 立即中断回忆,进入[问候状态] [回忆状态] 被用户询问“你在想什么?” ↓ AI说出最近的想法(如“我刚才在想,上次你说你喜欢蓝色...”) ↓ 进入[问候状态]或直接进入[对话状态](根据用户后续反应) [告别状态] (用户离开后) 动作 : 简短告别,用语音,→ 等待3秒 → 回到[空闲状态] 11. ## 用户类型区分 1. guest 用户 : - 默认用户ID,当没有检测到人脸时使用 - 在 Live2DChatActivity.kt 中初始化为 private var activeUserId: String = "guest" - 表示未通过人脸识别的临时用户 2. face_ 用户 : - 通过人脸识别生成的用户ID,格式为 face_<数字> - 在 FaceDetectionPipeline.kt 中生成: lastFaceIdentityId = match.matchedId?.let { "face_$it" } - 表示通过人脸识别的正式用户 ## 转换逻辑 当系统检测到人脸时,会触发以下流程: 1. 人脸检测 : FaceDetectionPipeline 检测到人脸 2. 身份识别 : FaceRecognizer 尝试识别用户身份 3. ID生成 :如果是新用户,生成新的 face_<数字> ID 4. 回调更新 :通过 onPresenceChanged 回调将 faceIdentityId 传递给 Live2DChatActivity 5. ID切换 : Live2DChatActivity 中的 interactionController.onFacePresenceChanged 会调用 handler.onRememberUser(faceIdentityId, recognized) 6. 更新活跃用户 : onRememberUser 方法会将 activeUserId 更新为 faceIdentityId 因此,当检测到人脸时, guest 用户会自动切换为 face_ 用户。 face_profiles 和 user_memory 表之间的关联是通过 ID转换 实现的,没有专门的关联表: ## 关联机制 1. ID转换规则 : - face_profiles 表中的 id 字段(数字)→ 转换为 face_ 格式 - 例如: id=1 → face_1 - 这个转换在 FaceDetectionPipeline.kt 中实现: lastFaceIdentityId = match.matchedId?.let { "face_$it" } 2. 关联流程 : - 系统检测到人脸后,从 face_profiles 表中查找匹配的记录,获取 id - 将 id 转换为 face_ 格式的用户ID - 这个用户ID被用作 user_memory 表中的 userId 字段 - 通过这个 userId ,两个表就建立了关联 12. 使用 adb shell 直接操作sqlite数据库 1. 进入设备 shell adb shell 2. 找到应用数据库 # 进入应用数据目录 run-as com.digitalperson # 进入数据库目录 cd databases # 查看数据库文件 ls -la 3. 使用 sqlite3 命令查看数据库 bash # 打开数据库 sqlite3 your_database.db # digital_human.db face_feature.db # 在 sqlite3 提示符下执行命令: .tables # 查看所有表 .schema table_name # 查看表结构 SELECT * FROM table_name; # 查询数据 .headers on # 显示列名 .mode column # 列模式显示 .quit # 退出