各位开发者大家好!欢迎来到Rokid开发者社区的实战教程专栏。

你是否曾想过让你的Rokid设备在无网环境下依然“耳聪舌辩”?是否希望用户的每一条指令都能得到毫秒级的响应,且隐私绝对安全?离线语音识别(ASR)技术正是你的不二之选。

本期教程,我们将深入 “功能解析所”,拆解Rokid离线语音的技术内核;分享 “实战经验库” 中的宝贵避坑指南;最后带你闯入 “创意孵化器”,实现一个完整的创意Demo。无论你是新手还是老鸟,都能有所收获!

工程源码和安装包体验包在文章末尾

Rokid开发教程 -离线语音指令识别

第一部分:【功能解析所】离线语音,到底是如何工作的?

在开始编码前,理解原理至关重要。Rokid的离线语音指令并非简单的“关键词匹配”,而是一个精巧的流程:

  • 语音唤醒(Wake-up): 设备持续监听环境音,通过内置的唤醒词引擎(如“若琪”)识别特定关键词,从而从休眠状态进入指令接收状态。
  • 语音端点检测(VAD): 唤醒后,VAD模块会精确判断用户什么时候开始说话,什么时候结束,从而截取出有效的语音片段。
  • 离线语音识别(ASR): 这是核心环节。截取的语音片段会被送入本地的语音识别引擎。该引擎基于预加载的语法网络(Grammar) 进行识别。语法网络就像一个本地的“指令库”,定义了所有可能被识别的词条组合,极大提高了识别的准确率和效率。
  • 语义理解(NLU)与执行: 识别出的文本会交给NLU模块解析出用户的意图(Intent)和参数(Slots),最终触发你预先编写好的回调函数来执行操作。

为什么选择离线?

  • 超低延迟: 无需网络传输,响应速度极快(毫秒级)。
  • 隐私安全: 语音数据完全在设备端处理,永不泄露。
  • 稳定可靠: 不依赖网络状态,在飞机、地下室、偏远地区等场景下依然可用。

第二部分:【实战经验库】轻松上手

大家可以使用官方的 XR Interaction Toolkit Plugin(OpenXR)或者UXR3.0 的SDK ,这里我使用的XR Interaction Toolkit Plugin作为教程。环境配置阶段这里我就跳过了,如果还不太了解的话可以看一下官方的这个文档进行配置下SDK 以下地址

https://custom.rokid.com/prod/rokid_web/c88be4bcde4c42c0b8b53409e1fa1701/pc/cn/9f40ac8d948545bb8e0b4d3c6fea411f.html?documentId=b55382f9e2df4672834042f360e1852a

更为详细的离线语音配置也可参考Rokid 官方提供的文档 https://custom.rokid.com/prod/rokid_web/c88be4bcde4c42c0b8b53409e1fa1701/pc/cn/9f40ac8d948545bb8e0b4d3c6fea411f.html?documentId=de7df0fb21184266aa22d66636e26a8d
https://custom.rokid.com/prod/rokid_web/c88be4bcde4c42c0b8b53409e1fa1701/pc/cn/9f40ac8d948545bb8e0b4d3c6fea411f.html?documentId=de7df0fb21184266aa22d66636e26a8d
    • 在 Unity 中点击 Assets > Import Package > Custom Package
    • 选择 UXRForOpenXR.unitypackage 并导入所有内容
  • 启用自定义 Gradle 模板

这里可以使用提前供配置好的包Plugins.unitypackage

  • 创建离线语音交互脚本
using Rokid.UXR.Module;          // Rokid UXR语音模块
using UnityEngine;
using UnityEngine.Android;          // Android权限管理
using UnityEngine.UI;               // UI组件


// 语音控制脚本 - 处理语音指令来控制物体的颜色变化和旋转
// 支持的功能:
// 1. 颜色控制:变成蓝色、变成绿色、随机颜色
// 2. 旋转控制:开始旋转、停止旋转(绕Y轴)
// 3. 重置功能:恢复初始颜色和角度
public class VoiceCommand : MonoBehaviour
{
 #region 私有变量

 // 语音模块是否已初始化的标志
 private bool isInitialized;

 // 当前是否正在旋转的状态标志
 private bool isRotating = false;


 // 保存物体的初始颜色,用于重置功能
 private Color originalColor;


 // 保存物体的初始旋转角度,用于重置功能
 private Vector3 originalRotation;
 #endregion

 #region 公共变量(在Inspector中设置)

 // 显示接收到的语音指令的UI文本组件
public Text infoText;


 // 需要改变颜色的物体的渲染器组件
 public Renderer m_Render;


 // 需要旋转的物体的Transform组件
 public Transform m_transform;


 // 旋转速度(度/秒)- 可在Inspector中调整
    [Header("旋转设置")]
    [Tooltip("物体绕Y轴旋转的速度,单位:度/秒")]
 public float rotationSpeed = 90f;
 #endregion
 #region Unity生命周期方法

 // Unity Awake方法 - 在对象创建时调用
 // 用于请求Android录音权限,语音识别需要此权限
 private void Awake()
    {
 // 检查是否有录音权限,没有则请求权限
 if (!Permission.HasUserAuthorizedPermission("android.permission.RECORD_AUDIO"))
        {
 Permission.RequestUserPermission("android.permission.RECORD_AUDIO");
        }
    }


 // 用于初始化语音控制系统和保存物体的初始状态
 void Start()
    {
 // 保存物体的初始状态,用于重置功能
 if (m_Render != null)
        {
 originalColor = m_Render.material.color;  // 保存初始颜色
        }
 originalRotation = m_transform.eulerAngles;   // 保存初始旋转角度

        // 初始化语音控制系统
 InitializeVoiceControl();
        // 添加语音指令
 AddInstruct();
    }



 void Update()
    {
        // 如果旋转标志为true,则持续绕Y轴旋转
 if (isRotating)
        {
            // 使用Time.deltaTime确保旋转速度不受帧率影响
            // 参数:(x轴旋转, y轴旋转, z轴旋转)
 m_transform.Rotate(0, rotationSpeed * Time.deltaTime, 0);
        }
    }

  
    // Unity OnDestroy方法 - 在对象销毁时调用
    // 用于清理语音指令和释放资源
 private void OnDestroy()
    {
        // 清除所有已注册的语音指令
 OfflineVoiceModule.Instance.ClearAllInstruct();
        // 提交更改
 OfflineVoiceModule.Instance.Commit();
    }
    #endregion

    #region 语音指令管理

    // 添加语音指令到语音识别系统
    // 注册所有支持的中文和英文语音指令
 void AddInstruct()
    {
        // 确保语音模块已初始化
 if (isInitialized)
        {
            // 注册中文语音指令
            // 参数说明:(语言, 显示文本, 拼音, 目标GameObject名称, 回调方法名)

            // 颜色控制指令
 OfflineVoiceModule.Instance.AddInstruct(LANGUAGE.CHINESE, "变成蓝色", "bian cheng lan se", this.gameObject.name, "OnReceive");
 OfflineVoiceModule.Instance.AddInstruct(LANGUAGE.CHINESE, "变成绿色", "bian cheng lv se", this.gameObject.name, "OnReceive");
 OfflineVoiceModule.Instance.AddInstruct(LANGUAGE.CHINESE, "随机颜色", "sui ji yan se", this.gameObject.name, "OnReceive");

            // 旋转控制指令
 OfflineVoiceModule.Instance.AddInstruct(LANGUAGE.CHINESE, "开始旋转", "kai shi xuan zhuan", this.gameObject.name, "OnReceive");
 OfflineVoiceModule.Instance.AddInstruct(LANGUAGE.CHINESE, "停止旋转", "ting zhi xuan zhuan", this.gameObject.name, "OnReceive");

            // 重置指令
 OfflineVoiceModule.Instance.AddInstruct(LANGUAGE.CHINESE, "重置", "chong zhi", this.gameObject.name, "OnReceive");

            // 注册英文语音指令(部分功能)
 OfflineVoiceModule.Instance.AddInstruct(LANGUAGE.ENGLISH, "Show blue", "show blue", this.gameObject.name, "OnReceive");
 OfflineVoiceModule.Instance.AddInstruct(LANGUAGE.ENGLISH, "Show green", "show green", this.gameObject.name, "OnReceive");

            // 提交所有指令到语音识别系统
 OfflineVoiceModule.Instance.Commit();
        }
    }
   
    // 语音指令接收回调方法
    // 当语音识别系统识别到注册的指令时会调用此方法
 void OnReceive(string msg)
    {
        // 在UI上显示接收到的语音指令
 infoText.text = msg;
        // 在控制台输出日志
 Debug.Log("-RKX- UXR-Sample:: On Voice Response received : " + msg);

        // 根据不同的语音指令执行相应的功能

        // 颜色控制指令处理
 if (string.Equals("变成蓝色", msg) || string.Equals("Show blue", msg))
        {
            // 将物体颜色设置为蓝色
 m_Render.material.color = Color.blue;
        }
 else if (string.Equals("变成绿色", msg) || string.Equals("Show green", msg))
        {
            // 将物体颜色设置为绿色
 m_Render.material.color = Color.green;
        }
 else if (string.Equals("随机颜色", msg))
        {
            // 生成随机颜色,确保透明度为1(完全不透明)
            // 使用Random.Range(0f, 1f)生成0-1之间的随机RGB值
 m_Render.material.color = new Color(Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f), 1f);
        }

        // 旋转控制指令处理
 else if (string.Equals("开始旋转", msg))
        {
            // 启动旋转标志,物体将在Update方法中持续旋转
 isRotating = true;
 Debug.Log("开始Y轴旋转");
        }
 else if (string.Equals("停止旋转", msg))
        {
            // 停止旋转标志,物体将停止旋转但保持当前角度
 isRotating = false;
 Debug.Log("停止旋转");
        }

        // 重置功能指令处理
 else if (string.Equals("重置", msg))
        {
            // 停止旋转
 isRotating = false;

            // 重置物体角度到初始状态
 m_transform.eulerAngles = originalRotation;

            // 重置物体颜色到初始状态
 if (m_Render != null)
            {
 m_Render.material.color = originalColor;
            }

 Debug.Log("重置完成:颜色和角度已恢复到初始状态");
        }
 else
        {
            // 处理未识别的指令
 Debug.Log("voice OnResponse: " + msg);
        }
    }
    #endregion
    #region 语音模块初始化

    // 初始化语音控制模块
    // 注册Rokid语音命令助手模块并设置语言为中文
 private void InitializeVoiceControl()
    {
        // 防止重复初始化
 if (!isInitialized)
        {
            // 注册Rokid语音命令助手模块
            // 参数:模块名称,是否为必需模块
 ModuleManager.Instance.RegistModule("com.rokid.voicecommand.VoiceCommandHelper", false);

            // 设置语音识别语言为中文
 OfflineVoiceModule.Instance.ChangeVoiceCommandLanguage(LANGUAGE.CHINESE);

            // 标记为已初始化
 isInitialized = true;
        }
    }
    #endregion
}

场景创建空物体挂载脚本,添加用于显示的文本,控制颜色旋转的模型,

这里我把unity 工程也上传一份

RokidXRI3.zip (源码)
发布APK 包

RokidAudio.apk

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐