更新 readme

This commit is contained in:
2026-04-18 11:42:08 +08:00
parent 1ad70525c1
commit 3f84c111d9
4 changed files with 730 additions and 833 deletions
+347 -348
View File
@@ -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/) |