更新 readme
This commit is contained in:
@@ -1,405 +1,404 @@
|
||||
# Duix Mobile for Android SDK Documentation
|
||||
# 安智伴 · AI 数字人陪护终端(Android)
|
||||
|
||||
English | [中文](./README_zh.md)
|
||||
|
||||
## 1. Product Overview
|
||||
|
||||
`Duix Mobile for Android` is a lightweight, fully offline 2D digital human solution for Android, supporting real-time rendering of digital avatars driven by voice audio.
|
||||
|
||||
### 1.1 Application Scenarios
|
||||
|
||||
- **Low deployment cost**: Suitable for unattended scenarios such as large-screen terminals, government halls, and banks.
|
||||
- **Minimal network dependency**: Runs entirely locally, no internet required, stable operation in subways and remote areas.
|
||||
- **Diverse functionality**: Can serve as a guide, Q&A customer service, intelligent companion, and more.
|
||||
|
||||
### 1.2 Core Features
|
||||
|
||||
- Customizable digital avatar and local rendering
|
||||
- Real-time voice-driven playback (supports WAV playback and PCM streaming)
|
||||
- Motion playback control (specific or random actions)
|
||||
- Automatic resource download management
|
||||
> 本项目与 [digital-human-monitor-v2](https://github.com/user/digital-human-monitor-v2)(家属监护 Web 端)配合使用,共同构成完整的"AI 数字人 + 家庭远程关怀"解决方案。
|
||||
|
||||
---
|
||||
|
||||
## 2. Terminology
|
||||
## 目录
|
||||
|
||||
| Term | Meaning |
|
||||
|--------------------|----------------------------------------------------------------------------|
|
||||
| PCM | Pulse-Code Modulation, raw audio stream with 16kHz sample rate, 16-bit depth, Mono channel |
|
||||
| WAV | An audio file format that supports PCM encoding, suitable for short voice playback |
|
||||
| RenderSink | Rendering data reception interface, implemented by the SDK, can be used for custom rendering or default display |
|
||||
| DUIX | Main control object of the digital human, integrates model loading, rendering, broadcasting, and motion control |
|
||||
| GLES | OpenGL ES, a graphics interface for rendering images on Android |
|
||||
| SpecialAction | A JSON file attached to the model that marks action intervals (e.g., greetings, waving) |
|
||||
- [需求分析](#需求分析)
|
||||
- [设计思路](#设计思路)
|
||||
- [技术架构](#技术架构)
|
||||
- [模块说明](#模块说明)
|
||||
- [全链路数据流](#全链路数据流)
|
||||
- [通信协议](#通信协议)
|
||||
- [集成要求](#集成要求)
|
||||
- [SDK 接口文档](#sdk-接口文档)
|
||||
- [构建与运行](#构建与运行)
|
||||
|
||||
---
|
||||
|
||||
## 3. SDK Access
|
||||
## 需求分析
|
||||
|
||||
### 3.1 Module Reference (Recommended)
|
||||
### 背景
|
||||
|
||||
1. Obtain the complete source package, unzip it, and copy the `duix-sdk` directory to the project root directory.
|
||||
2. In the project `settings.gradle`, add:
|
||||
中国老龄化进程加速,独居或空巢老人的心理陪伴和安全监护成为刚需。子女因工作或地理距离无法陪伴,需要一种低门槛、有温度的技术方案来弥合亲情距离。
|
||||
|
||||
```gradle
|
||||
include ':duix-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 │ │
|
||||
│ └──────────────┘ │
|
||||
└──────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
3. In the module's `build.gradle`, add the dependency:
|
||||
### 技术栈
|
||||
|
||||
```gradle
|
||||
dependencies {
|
||||
api project(":duix-sdk")
|
||||
}
|
||||
| 层级 | 技术 |
|
||||
|------|------|
|
||||
| **数字人渲染** | 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 # 工具调用机制
|
||||
```
|
||||
|
||||
### 3.2 AAR Reference (Optional)
|
||||
### duix-sdk — 数字人渲染引擎
|
||||
|
||||
1. Place the compiled `duix-sdk-release.aar` module into the `libs/` directory.
|
||||
2. Add the dependency:
|
||||
| 类 | 职责 |
|
||||
|----|------|
|
||||
| `DUIX` | 主控对象:管理初始化、渲染循环、音频驱动、生命周期 |
|
||||
| `RenderThread` | 独立渲染线程:逐帧推理 + 音频同步 |
|
||||
| `DUIXRenderer` | OpenGL ES 2.0 渲染器:将 ImageFrame 渲染到 TextureView |
|
||||
| `DUIXTextureView` | 自定义 TextureView:提供 GL 渲染表面 |
|
||||
| `VirtualModelUtil` | 模型资源管理:下载、校验、解压 |
|
||||
| `DuixNcnn` | JNI 桥接:调用 C++ 层 NCNN 推理 |
|
||||
|
||||
```gradle
|
||||
dependencies {
|
||||
api fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
|
||||
}
|
||||
**渲染流水线**:
|
||||
```
|
||||
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 表
|
||||
→ 家属在"陪伴动态"页面查看趋势图
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Integration Requirements
|
||||
## 通信协议
|
||||
|
||||
| Item | Description |
|
||||
|----------------|-----------------------------------------------------------------|
|
||||
| System | Supports Android 10+ systems. |
|
||||
| CPU Architecture | armeabi-v7a, arm64-v8a |
|
||||
| Hardware Requirements | Device CPU with 8 or more cores (Snapdragon 8 Gen 2), 8GB or more memory, available storage space of 1GB or more |
|
||||
| Network | None (Fully local operation) |
|
||||
| Development IDE | Android Studio Giraffe 2022.3.1 Patch 2 |
|
||||
| Memory Requirements | Minimum 800MB memory available for the digital human |
|
||||
### 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 | 记录工具调用日志 |
|
||||
|
||||
---
|
||||
|
||||
## 5. Usage Flow Overview
|
||||
## 集成要求
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Check Configuration and Models] --> B[Build DUIX Instance]
|
||||
B --> C[Call init to Initialize]
|
||||
C --> D[Display Avatar / Render]
|
||||
D --> E[PCM or WAV Audio Driving]
|
||||
E --> F[Playback Control & Motion Triggering]
|
||||
F --> G[Resource Release]
|
||||
```
|
||||
| 项目 | 要求 |
|
||||
|------|------|
|
||||
| 系统版本 | 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) |
|
||||
|
||||
---
|
||||
|
||||
## 6. Key Interfaces and Example Calls
|
||||
## SDK 接口文档
|
||||
|
||||
### 6.1 Model Check and Download
|
||||
### 术语
|
||||
|
||||
Before using the rendering service, ensure that the basic configuration and model files are synchronized to local storage. The SDK provides a simple demonstration of the model download and decompression process using `VirtualModelUtil`. If model download is slow or fails, developers can choose to cache the model package to their own storage service.
|
||||
| 术语 | 含义 |
|
||||
|------|------|
|
||||
| PCM | 16kHz 采样率、16bit 位深、Mono 单通道的原始音频流 |
|
||||
| WAV | 支持 PCM 编码的音频文件格式 |
|
||||
| RenderSink | 渲染数据接收接口,SDK 提供默认实现 |
|
||||
| DUIX | 数字人主控对象 |
|
||||
| ImageFrame | 包含 rawBuffer (图像) + maskBuffer (掩码) + 宽高的渲染帧 |
|
||||
|
||||
> Function Definition: `ai.guiji.duix.sdk.client.VirtualModelUtil`
|
||||
|
||||
```
|
||||
// Check if base configuration is downloaded
|
||||
boolean checkBaseConfig(Context context)
|
||||
|
||||
// Check if the model is downloaded
|
||||
boolean checkModel(Context context, String name)
|
||||
|
||||
// Base configuration download
|
||||
void baseConfigDownload(Context context, String url, ModelDownloadCallback callback)
|
||||
|
||||
// Model download
|
||||
void modelDownload(Context context, String modelUrl, ModelDownloadCallback callback)
|
||||
```
|
||||
|
||||
`ModelDownloadCallback` includes progress, completion, failure callbacks, etc., as defined in the SDK.
|
||||
|
||||
```
|
||||
interface ModelDownloadCallback {
|
||||
// Download progress
|
||||
void onDownloadProgress(String url, long current, long total);
|
||||
// Unzip progress
|
||||
void onUnzipProgress(String url, long current, long total);
|
||||
// Download and unzip complete
|
||||
void onDownloadComplete(String url, File dir);
|
||||
// Download and unzip failed
|
||||
void onDownloadFail(String url, int code, String msg);
|
||||
}
|
||||
```
|
||||
|
||||
**Call Example**:
|
||||
### 模型检查与下载
|
||||
|
||||
```kotlin
|
||||
if (!VirtualModelUtil.checkBaseConfig(mContext)){
|
||||
VirtualModelUtil.baseConfigDownload(mContext, baseConfigUrl, callback)
|
||||
}
|
||||
// 检查基础配置
|
||||
VirtualModelUtil.checkBaseConfig(context): Boolean
|
||||
// 下载基础配置
|
||||
VirtualModelUtil.baseConfigDownload(context, url, callback)
|
||||
|
||||
// 检查模型
|
||||
VirtualModelUtil.checkModel(context, modelUrl): Boolean
|
||||
// 下载模型
|
||||
VirtualModelUtil.modelDownload(context, modelUrl, callback)
|
||||
```
|
||||
|
||||
### 初始化与渲染
|
||||
|
||||
```kotlin
|
||||
if (!VirtualModelUtil.checkModel(mContext, modelUrl)){
|
||||
VirtualModelUtil.modelDownload(mContext, modelUrl, callback)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 6.2 Initialization and Rendering Start
|
||||
|
||||
In the `onCreate()` stage of the rendering page, build the DUIX object and call the init interface.
|
||||
|
||||
> Function Definition: `ai.guiji.duix.sdk.client.DUIX`
|
||||
|
||||
```
|
||||
// Build DUIX object
|
||||
public DUIX(Context context, String modelName, RenderSink sink, Callback callback)
|
||||
|
||||
// Initialize DUIX service
|
||||
void init()
|
||||
```
|
||||
|
||||
**DUIX Object Construction Explanation**:
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|---------------|-----------|----------------------------------------------------------------|
|
||||
| context | Context | System context |
|
||||
| modelName | String | Can pass the model download URL (if downloaded) or cached filename |
|
||||
| render | RenderSink| Rendering data interface, SDK provides a default rendering component inheriting from this interface, or you can implement it yourself |
|
||||
| callback | Callback | Various callback events handled by the SDK |
|
||||
|
||||
Where **Callback** is defined as: `ai.guiji.duix.sdk.client.Callback`
|
||||
|
||||
```
|
||||
interface Callback {
|
||||
void onEvent(String event, String msg, Object info);
|
||||
}
|
||||
```
|
||||
|
||||
**Call Example**:
|
||||
|
||||
```kotlin
|
||||
duix = DUIX(mContext, modelUrl, mDUIXRender) { event, msg, info ->
|
||||
// 构建 DUIX 实例
|
||||
val duix = DUIX(context, modelUrl, renderSink) { event, msg, info ->
|
||||
when (event) {
|
||||
ai.guiji.duix.sdk.client.Constant.CALLBACK_EVENT_INIT_READY -> {
|
||||
initOK()
|
||||
}
|
||||
|
||||
ai.guiji.duix.sdk.client.Constant.CALLBACK_EVENT_INIT_ERROR -> {
|
||||
initError()
|
||||
}
|
||||
// ...
|
||||
Constant.CALLBACK_EVENT_INIT_READY -> { /* 初始化完成 */ }
|
||||
Constant.CALLBACK_EVENT_INIT_ERROR -> { /* 初始化失败 */ }
|
||||
Constant.CALLBACK_EVENT_PLAY_START -> { /* 播放开始 */ }
|
||||
Constant.CALLBACK_EVENT_PLAY_END -> { /* 播放结束 */ }
|
||||
}
|
||||
}
|
||||
// Asynchronous callback result
|
||||
duix?.init()
|
||||
duix.init()
|
||||
```
|
||||
|
||||
In the `init` callback, confirm the initialization result.
|
||||
### 音频驱动
|
||||
|
||||
```kotlin
|
||||
// PCM 流式推送(用于实时 AI 语音)
|
||||
duix.pushPcm(pcmBytes)
|
||||
|
||||
// WAV 文件播放
|
||||
duix.playWav(wavFilePath)
|
||||
```
|
||||
|
||||
### 资源释放
|
||||
|
||||
```kotlin
|
||||
// 在 Activity onDestroy 中调用
|
||||
duix.release()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 6.3 Digital Human Avatar Display
|
||||
## 构建与运行
|
||||
|
||||
Use the SDK-provided `DUIXRenderer` and `DUIXTextureView` to quickly implement rendering with transparency support. Alternatively, you can implement the `RenderSink` interface to customize the rendering logic.
|
||||
### 环境准备
|
||||
|
||||
The **RenderSink** definition is as follows: `ai.guiji.duix.sdk.client.render.RenderSink`
|
||||
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
|
||||
/**
|
||||
* Rendering pipeline, returns rendering data through this interface
|
||||
*/
|
||||
public interface RenderSink {
|
||||
|
||||
// The frame's buffer data is arranged in BGR order
|
||||
void onVideoFrame(ImageFrame imageFrame);
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
**Call Example**:
|
||||
|
||||
Use `DUIXRenderer` and `DUIXTextureView` to quickly implement rendering. These controls support transparency and can freely set the background and foreground.
|
||||
|
||||
```kotlin
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
// ...
|
||||
mDUIXRender =
|
||||
DUIXRenderer(
|
||||
mContext,
|
||||
binding.glTextureView
|
||||
)
|
||||
|
||||
binding.glTextureView.setEGLContextClientVersion(GL_CONTEXT_VERSION)
|
||||
binding.glTextureView.setEGLConfigChooser(8, 8, 8, 8, 16, 0) // Transparency
|
||||
binding.glTextureView.isOpaque = false // Transparency
|
||||
binding.glTextureView.setRenderer(mDUIXRender)
|
||||
binding.glTextureView.renderMode =
|
||||
GLSurfaceView.RENDERMODE_WHEN_DIRTY // Must be called after setting the renderer
|
||||
|
||||
duix = DUIX(mContext, modelUrl, mDUIXRender) { event, msg, _ ->
|
||||
}
|
||||
// ...
|
||||
}
|
||||
MONITOR_BASE_URL // 监护 Web 服务地址
|
||||
REALTIME_BASE_URL // Qwen Omni WebSocket 地址
|
||||
DEFAULT_API_KEY // DashScope API Key
|
||||
AUDIO_SAMPLE_RATE // 音频采样率 (24000)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 6.4 Broadcasting Control
|
||||
## 关联项目
|
||||
|
||||
#### Use Streaming PCM to Drive Digital Human Broadcasting
|
||||
|
||||
**PCM Format: 16kHz sample rate, single channel, 16-bit depth**
|
||||
|
||||
> Function Definition: `ai.guiji.duix.sdk.client.DUIX`
|
||||
|
||||
```
|
||||
// Notify service to start pushing audio
|
||||
void startPush()
|
||||
|
||||
// Push PCM data
|
||||
void pushPcm(byte[] buffer)
|
||||
|
||||
// Finish a segment of audio push (Call this after the audio push is complete, not after playback finishes)
|
||||
void stopPush()
|
||||
```
|
||||
|
||||
`startPush`, `pushPcm`, and `stopPush` need to be called in pairs. `pushPcm` should not be too long. After pushing the entire audio, call `stopPush` to end the session. Use `startPush` again for the next audio.
|
||||
|
||||
**The audio data between each startPush and stopPush segment should be at least 1 second (32000 bytes), otherwise the mouth shape driver cannot be triggered, and blank frames can be used to fill in.**
|
||||
|
||||
**Call Example**:
|
||||
|
||||
```kotlin
|
||||
val thread = Thread {
|
||||
duix?.startPush()
|
||||
val inputStream = assets.open("pcm/2.pcm")
|
||||
val buffer = ByteArray(320)
|
||||
var length = 0
|
||||
while (inputStream.read(buffer).also { length = it } > 0){
|
||||
val data = buffer.copyOfRange(0, length)
|
||||
duix?.pushPcm(data)
|
||||
}
|
||||
duix?.stopPush()
|
||||
inputStream.close()
|
||||
}
|
||||
thread.start()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 6.5 Motion Control
|
||||
|
||||
#### Play Specific Motion Interval
|
||||
|
||||
The model supports new motion intervals marked in `SpecialAction.json`
|
||||
|
||||
> Function Definition: `ai.guiji.duix.sdk.client.DUIX`
|
||||
|
||||
```
|
||||
/**
|
||||
* Play specific motion interval
|
||||
* @param name The motion interval name, which can be obtained from @{ModelInfo.getSilenceRegion()} after init callback
|
||||
* @param now Whether to play immediately: true: play now; false: wait for current silent or motion interval to finish
|
||||
*/
|
||||
void startMotion(String name, boolean now)
|
||||
```
|
||||
|
||||
**Call Example**:
|
||||
|
||||
```kotlin
|
||||
duix?.startMotion("Greeting", true)
|
||||
```
|
||||
|
||||
#### Randomly Play Motion Interval
|
||||
|
||||
> Function Definition: `ai.guiji.duix.sdk.client.DUIX`
|
||||
|
||||
```
|
||||
/**
|
||||
* Randomly play a motion interval
|
||||
* @param now Whether to play immediately: true: play now; false: wait for current silent or motion interval to finish
|
||||
*/
|
||||
void startRandomMotion(boolean now);
|
||||
```
|
||||
|
||||
**Call Example**:
|
||||
|
||||
```kotlin
|
||||
duix?.startRandomMotion(true)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Proguard Configuration
|
||||
|
||||
If using obfuscation, add the following in `proguard-rules.pro`:
|
||||
|
||||
```proguard
|
||||
-keep class ai.guiji.duix.DuixNcnn{*; }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. Precautions
|
||||
|
||||
1. Ensure that the base configuration file and model are downloaded to the specified location before driving rendering initialization.
|
||||
2. PCM audio should not be too long, as PCM buffers are cached in memory; long audio streams may cause memory overflow.
|
||||
3. To replace the preview model, modify the `modelUrl` value in `MainActivity.kt` and use the SDK's built-in file download and decompression management to obtain the complete model files.
|
||||
4. Audio driving format: 16kHz sample rate, single channel, 16-bit depth.
|
||||
5. Insufficient device performance may result in the audio feature extraction speed not matching the playback speed. You can use `duix?.setReporter()` to monitor frame rendering information.
|
||||
|
||||
---
|
||||
|
||||
## 9. FAQ and Troubleshooting Guide
|
||||
|
||||
| Issue | Possible Cause | Solution |
|
||||
|---------------------------------|------------------------------|------------------------------|
|
||||
| init callback failed | Model path error or model not downloaded | Use `checkModel` to check model status |
|
||||
| Rendering black screen | EGL configuration or texture view error | Use SDK-provided example settings |
|
||||
| No PCM playback effect | Incorrect format or `startPush` not called | Ensure audio format is correct and call push method |
|
||||
| Model download slow | Unstable network or restricted CDN | Support self-hosted model file storage service |
|
||||
|
||||
---
|
||||
|
||||
## 10. Version History
|
||||
|
||||
**<a>4.0.1</a>**
|
||||
|
||||
1. Supports PCM audio stream driving the digital human, improving audio playback response speed.
|
||||
2. Optimized motion interval playback, allowing specific motion intervals based on model configuration.
|
||||
3. Custom audio player, removed Exoplayer playback dependency.
|
||||
4. Provided simplified model download synchronization management tools.
|
||||
5. The audio data between each startPush and stopPush segment should be at least 1 second (32000 bytes), otherwise the mouth shape driver cannot be triggered, and blank frames can be used to fill in.
|
||||
|
||||
**<a>3.0.5</a>**
|
||||
|
||||
```text
|
||||
1. Updated arm32 CPU libonnxruntime.so version to fix compatibility issues.
|
||||
2. Modified motion interval playback function, supports random and sequential playback, requires manual call to stop playback to return to silent interval.
|
||||
```
|
||||
|
||||
**<a>3.0.4</a>**
|
||||
|
||||
```text
|
||||
1. Fixed model display issue due to low float precision on some devices.
|
||||
```
|
||||
|
||||
**<a>3.0.3</a>**
|
||||
|
||||
```text
|
||||
1. Optimized local rendering.
|
||||
```
|
||||
|
||||
## 11. 🔗 Open-source Dependencies
|
||||
|
||||
| Module | Description |
|
||||
|------------------------------------------|--------------------------------|
|
||||
| [onnx](https://github.com/onnx/onnx) | General AI model standard format |
|
||||
| [ncnn](https://github.com/Tencent/ncnn) | High-performance neural network computing framework (Tencent) |
|
||||
|
||||
---
|
||||
|
||||
For more help, please contact the technical support team.
|
||||
| 项目 | 角色 | 仓库 |
|
||||
|------|------|------|
|
||||
| **dh_aigc_android**(本项目) | 老人端:AI 数字人陪护 + 设备行为上报 | 当前仓库 |
|
||||
| **digital-human-monitor-v2** | 家属端:远程监护 Web 面板 + 消息管理 + 推送通知 | [digital-human-monitor-v2](../digital-human-monitor-v2/) |
|
||||
|
||||
Reference in New Issue
Block a user