# 安智伴 · AI 数字人陪护终端(Android) English | [中文](./README_zh.md) > 本项目与 [digital-human-monitor-v2](https://github.com/user/digital-human-monitor-v2)(家属监护 Web 端)配合使用,共同构成完整的"AI 数字人 + 家庭远程关怀"解决方案。 --- ## 目录 - [需求分析](#需求分析) - [设计思路](#设计思路) - [技术架构](#技术架构) - [模块说明](#模块说明) - [全链路数据流](#全链路数据流) - [通信协议](#通信协议) - [集成要求](#集成要求) - [SDK 接口文档](#sdk-接口文档) - [构建与运行](#构建与运行) --- ## 需求分析 ### 背景 中国老龄化进程加速,独居或空巢老人的心理陪伴和安全监护成为刚需。子女因工作或地理距离无法陪伴,需要一种低门槛、有温度的技术方案来弥合亲情距离。 ### 核心需求 | 需求维度 | 描述 | |---------|------| | **AI 陪伴对话** | 老人可随时与屏幕上的"数字人"自然语音对话,获得情感陪伴和生活助理服务 | | **家庭留言桥梁** | 子女通过 Web 端发送关怀留言 → 数字人主动转达;老人口述留言 → 子女在 Web 端收到 | | **使用行为上报** | 设备自动向云端上报使用事件(开屏、对话时长等),供家属了解老人日常 | | **离线数字人渲染** | 数字人形象的 2D 渲染完全在本地完成(NCNN 推理 + OpenGL),无需 GPU 服务器 | | **低门槛部署** | 老人无需任何操作,设备预装即可使用;家属扫码绑定即可监护 | ### 用户角色 | 角色 | 使用场景 | |------|---------| | **老人**(设备端) | 与数字人语音聊天、听取家人留言、口述回复 | | **家属**(Web 端) | 发送留言、查看老人使用动态、接收推送通知 | --- ## 设计思路 ### 1. 端云分离、各司其职 - **端侧(本项目)**:承担数字人渲染(完全离线)+ 实时 AI 对话(通过 Qwen Omni-Realtime 云端模型)+ 家庭消息同步 - **云侧(Monitor Web)**:承担家属身份管理、设备绑定、消息存储与分发、使用数据可视化 ### 2. AI 对话与数字人解耦 DUIX SDK 仅负责"给定 PCM 音频 → 渲染对应口型/表情动画",不关心音频来源。音频可来自: - Qwen Omni-Realtime 模型的实时语音回复 - 本地 TTS 合成 - 任意 WAV 文件 这种解耦使得 AI 模型可独立升级,不影响渲染管线。 ### 3. 工具调用实现双向留言 通过 Qwen 的 Function Calling 能力,在 AI 对话中注册两个工具函数: - `leave_message_for_family`:老人口述 → AI 提取内容 → 调用工具 → 消息存入云端 - `fetch_family_messages`:老人想听留言 → AI 调用工具 → 拉取消息 → 口播转达 AI 自主判断何时调用工具,无需老人学习任何操作指令。 ### 4. 面向老人的交互设计 - **语义 VAD**:采用 `semantic_vad` 而非传统声学 VAD,能过滤电视背景音、咳嗽等噪音,仅在老人真正说话时响应 - **主动播报**:对话开始时若有未读家人留言,AI 会主动口播转达,无需老人主动查询 - **温和人设**:系统 Prompt 设定为"面向中国老年群体的心理陪伴 AI",使用温和、简短、生活化的中文回复 --- ## 技术架构 ### 系统全景 ``` ┌──────────────────────────────────────────────────────────────────┐ │ Android 设备端 │ │ │ │ ┌─────────────┐ PCM音频 ┌──────────────────────────────┐ │ │ │ Qwen Omni │ ────────────→ │ DUIX SDK │ │ │ │ Realtime │ │ ┌────────────────────────┐ │ │ │ │ (WebSocket) │ AI回复语音 │ │ NCNN 推理引擎 │ │ │ │ │ │ │ │ (口型/表情/动作 推理) │ │ │ │ └──────┬──────┘ │ └───────────┬────────────┘ │ │ │ │ │ │ ImageFrame │ │ │ 语音 │ 文本 │ ┌───────────▼────────────┐ │ │ │ 输入 │ +语音 │ │ OpenGL ES 2.0 渲染 │ │ │ │ │ │ │ (DUIXRenderer) │ │ │ │ ┌──────▼──────┐ │ └───────────┬────────────┘ │ │ │ │ 麦克风录音 │ │ │ │ │ │ │ (16kHz PCM) │ │ ┌───────────▼────────────┐ │ │ │ └─────────────┘ │ │ GLTextureView (UI) │ │ │ │ └──────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ FamilyBridgeService (HTTP) │ │ │ │ • 设备注册 → POST /api/device/register │ │ │ │ • 拉取留言 → GET /api/device/messages │ │ │ │ • 标记已读 → POST /api/device/messages/read │ │ │ │ • 上报事件 → POST /api/device/usage │ │ │ │ • 对话存档 → POST /api/device/conversations │ │ │ │ • 工具记录 → POST /api/device/tool-call │ │ │ └──────────────────────────────┬───────────────────────────┘ │ └─────────────────────────────────┼────────────────────────────────┘ │ HTTPS ▼ ┌──────────────────────────────────────────────────────────────────┐ │ digital-human-monitor-v2 (Next.js 云端) │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │ │ │ 设备管理 │ │ 消息存储 │ │ 行为分析 │ │ Web Push 推送 │ │ │ └──────────┘ └──────────┘ └──────────┘ └──────────────┘ │ │ │ │ │ ▼ │ │ ┌──────────────┐ │ │ │ PostgreSQL │ │ │ └──────────────┘ │ └──────────────────────────────────────────────────────────────────┘ ``` ### 技术栈 | 层级 | 技术 | |------|------| | **数字人渲染** | NCNN (端侧推理) + OpenCV 4.6 + OpenGL ES 2.0 + ONNX Runtime | | **AI 对话** | 千问 Qwen 3.5 Omni Plus Realtime (WebSocket) | | **音频处理** | AudioRecord (16kHz) → PCM → Base64 → WebSocket;AudioTrack 播放 | | **网络通信** | OkHttp 4 (HTTP API) + OkHttp WebSocket (Qwen Realtime) | | **本地存储** | SharedPreferences (设备 UUID、配置) | | **构建系统** | Gradle 8.13.2 + AGP 8.9.1 + JDK 17 (Temurin) | | **语言** | Kotlin (应用层) + Java (SDK 层) + C++ (Native 推理层) | --- ## 模块说明 ### 项目结构 ``` dh_aigc_android/ ├── duix-sdk/ # 核心 2D 数字人渲染 SDK(库模块) │ ├── src/main/java/ # Java SDK 接口层 │ │ └── ai/guiji/duix/ │ │ ├── sdk/client/ # DUIX 主控、渲染、回调、工具类 │ │ └── duix/DuixNcnn.java # JNI 接口 │ └── src/main/cpp/ # C++ Native 推理引擎 │ ├── dhcore/ # 核心数字人推理 │ ├── dhmfcc/ # 音频 MFCC 特征提取 │ ├── dhunet/ # 口型网络模型 │ └── third/ # 预编译依赖 (NCNN, OpenCV, ONNX, libjpeg) │ ├── test/ # 演示应用(应用模块) │ └── src/main/java/ai/guiji/duix/test/ │ ├── ui/activity/ │ │ ├── MainActivity.kt # 主页:模型选择与下载管理 │ │ ├── CallActivity.kt # 核心:数字人渲染 + AI 对话 + 留言桥梁 │ │ ├── SettingsActivity.kt # 设备设置 │ │ └── VoiceCloneSetupActivity.kt # 声音克隆配置 │ ├── service/ │ │ ├── FamilyBridgeService.kt # 家庭监护 API 客户端 │ │ ├── OmniRealtimeClient.kt # Qwen Omni WebSocket 客户端 │ │ ├── QwenTtsRealtimeClient.kt # Qwen TTS 客户端 │ │ ├── VoiceCloneService.kt # 声音克隆服务 │ │ └── DashScopeConfig.java # API 配置常量 │ ├── audio/ │ │ ├── AudioResampler.java # PCM 重采样 │ │ └── StreamingAudioRecorder.java # 实时麦克风录音 │ └── camera/ │ └── CameraFrameCapture.java # 摄像头帧采集 │ └── qwen-docs/ # 千问 Omni-Realtime API 参考文档 ├── main.md # 协议总览 ├── client_events.md # 客户端事件定义 ├── server_events.md # 服务端事件定义 └── function_calling.md # 工具调用机制 ``` ### duix-sdk — 数字人渲染引擎 | 类 | 职责 | |----|------| | `DUIX` | 主控对象:管理初始化、渲染循环、音频驱动、生命周期 | | `RenderThread` | 独立渲染线程:逐帧推理 + 音频同步 | | `DUIXRenderer` | OpenGL ES 2.0 渲染器:将 ImageFrame 渲染到 TextureView | | `DUIXTextureView` | 自定义 TextureView:提供 GL 渲染表面 | | `VirtualModelUtil` | 模型资源管理:下载、校验、解压 | | `DuixNcnn` | JNI 桥接:调用 C++ 层 NCNN 推理 | **渲染流水线**: ``` pushPcm(音频) → MFCC特征提取 → NCNN口型网络推理 → 获取ImageFrame(图像+掩码) → OpenGL混合渲染 → TextureView显示 ``` ### test — 应用集成层 | 类 | 职责 | |----|------| | `CallActivity` | 整合 DUIX 渲染 + Qwen 对话 + 留言桥梁的核心页面 | | `OmniRealtimeClient` | Qwen Omni-Realtime WebSocket 客户端,处理实时语音对话 | | `FamilyBridgeService` | 家庭监护云 API 客户端,负责设备注册、消息同步、事件上报 | | `MainActivity` | 模型选择与下载管理入口 | --- ## 全链路数据流 ### 1. AI 实时对话 ``` 老人说话 → 麦克风录音 (16kHz PCM) → Base64 编码 → input_audio_buffer.append (WebSocket) → Qwen Omni 模型推理 → response.audio.delta (Base64 PCM 回传) → 解码为 PCM → DUIX.pushPcm() → NCNN 推理口型动画 → OpenGL 渲染 → 同时 AudioTrack 播放语音 ``` ### 2. 留言传递(老人 → 家属) ``` 老人对 AI 说 "帮我给儿子带个话,说我挺好的" → Qwen 识别意图 → 触发 leave_message_for_family 工具 → 提取 recipientRelation="儿子", message="我挺好的" → FamilyBridgeService → POST /api/device/conversations → Monitor Web 存入数据库 → Web Push 通知家属 → AI 回复老人 "好的,已经帮您告诉儿子了" ``` ### 3. 留言传递(家属 → 老人) ``` 家属在 Web 端发送留言 → 存入 FamilyMessage 表 → 老人设备启动 AI 对话 → FamilyBridgeService 拉取未读消息 → 注入 AI 系统 Prompt: "家里人刚留了新留言,请主动转告..." → AI 在第一轮回复中口播: "您儿子给您捎了个话——记得吃药" ``` ### 4. 使用行为上报 ``` 设备事件 (APP_OPEN / AI_SESSION_STARTED / TOOL_CALLED / ...) → FamilyBridgeService → POST /api/device/usage → Monitor Web 存入 UsageEvent 表 → 家属在"陪伴动态"页面查看趋势图 ``` --- ## 通信协议 ### Qwen Omni-Realtime WebSocket | 方向 | 事件 | 用途 | |------|------|------| | C→S | `session.update` | 设置模态(text+audio)、语音、VAD、系统 Prompt、工具列表 | | C→S | `input_audio_buffer.append` | 推送用户麦克风 PCM (Base64) | | S→C | `response.audio.delta` | 模型语音回复增量块 (Base64 PCM) | | S→C | `response.text.done` | 模型文本回复完成 | | S→C | `response.function_call_arguments.done` | 工具调用请求 | | C→S | `conversation.item.create` | 回传工具执行结果 | | C→S | `response.create` | 触发模型基于工具结果生成最终回复 | ### 注册的 AI 工具 | 工具名 | 参数 | 用途 | |--------|------|------| | `leave_message_for_family` | `recipientRelation` (称谓), `message` (内容), `importance` (优先级) | 老人留言给家人 | | `fetch_family_messages` | `count` (数量 1-5) | 拉取家人留言 | ### FamilyBridge HTTP API | 端点 | 方法 | 用途 | |------|------|------| | `/api/device/register` | POST | 设备注册,返回 `deviceUuid` + `bindUrl` | | `/api/device/messages` | GET | 拉取待送达消息 | | `/api/device/messages/read` | POST | 标记消息已读 | | `/api/device/usage` | POST | 上报使用事件 | | `/api/device/conversations` | POST | 上传对话轮次 | | `/api/device/tool-call` | POST | 记录工具调用日志 | --- ## 集成要求 | 项目 | 要求 | |------|------| | 系统版本 | Android 10+ (API 24+) | | CPU 架构 | arm64-v8a, armeabi-v7a | | 硬件 | 8 核 CPU (骁龙 8 Gen2), 8GB+ 内存, 1GB+ 存储 | | 内存 | 数字人运行需 ≥ 800MB 可用内存 | | 网络 | 数字人渲染:无需网络;AI 对话 + 监护同步:需联网 | | 开发 IDE | Android Studio Giraffe 2022.3.1+ | | JDK | OpenJDK 17 (Temurin) | | Gradle | 8.13.2 (使用项目自带 wrapper) | --- ## SDK 接口文档 ### 术语 | 术语 | 含义 | |------|------| | PCM | 16kHz 采样率、16bit 位深、Mono 单通道的原始音频流 | | WAV | 支持 PCM 编码的音频文件格式 | | RenderSink | 渲染数据接收接口,SDK 提供默认实现 | | DUIX | 数字人主控对象 | | ImageFrame | 包含 rawBuffer (图像) + maskBuffer (掩码) + 宽高的渲染帧 | ### 模型检查与下载 ```kotlin // 检查基础配置 VirtualModelUtil.checkBaseConfig(context): Boolean // 下载基础配置 VirtualModelUtil.baseConfigDownload(context, url, callback) // 检查模型 VirtualModelUtil.checkModel(context, modelUrl): Boolean // 下载模型 VirtualModelUtil.modelDownload(context, modelUrl, callback) ``` ### 初始化与渲染 ```kotlin // 构建 DUIX 实例 val duix = DUIX(context, modelUrl, renderSink) { event, msg, info -> when (event) { Constant.CALLBACK_EVENT_INIT_READY -> { /* 初始化完成 */ } Constant.CALLBACK_EVENT_INIT_ERROR -> { /* 初始化失败 */ } Constant.CALLBACK_EVENT_PLAY_START -> { /* 播放开始 */ } Constant.CALLBACK_EVENT_PLAY_END -> { /* 播放结束 */ } } } duix.init() ``` ### 音频驱动 ```kotlin // PCM 流式推送(用于实时 AI 语音) duix.pushPcm(pcmBytes) // WAV 文件播放 duix.playWav(wavFilePath) ``` ### 资源释放 ```kotlin // 在 Activity onDestroy 中调用 duix.release() ``` --- ## 构建与运行 ### 环境准备 1. 安装 Android Studio Giraffe 2022.3.1+ 2. 配置 JDK 17:`File → Settings → Build → Gradle → Gradle JDK → 选择 JDK 17` 3. 连接 Android 设备(需满足硬件要求) ### 编译安装 ```bash # 使用 Gradle Wrapper 编译安装 test 应用 ./gradlew :test:installDebug ``` ### 配置说明 API 密钥和服务地址在 `DashScopeConfig.java` 中配置: ```java MONITOR_BASE_URL // 监护 Web 服务地址 REALTIME_BASE_URL // Qwen Omni WebSocket 地址 DEFAULT_API_KEY // DashScope API Key AUDIO_SAMPLE_RATE // 音频采样率 (24000) ``` --- ## 关联项目 | 项目 | 角色 | 仓库 | |------|------|------| | **dh_aigc_android**(本项目) | 老人端:AI 数字人陪护 + 设备行为上报 | 当前仓库 | | **digital-human-monitor-v2** | 家属端:远程监护 Web 面板 + 消息管理 + 推送通知 | [digital-human-monitor-v2](../digital-human-monitor-v2/) |