前言

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

终于到了这个系列最核心的技术点——Core Speech Kit。前面九篇我们做了大量的铺垫工作:搭环境、学原理、分析源码、创建工程、实现接口。所有这些准备,最终都是为了能正确地调用Core Speech Kit来实现语音识别。

Core Speech Kit是OpenHarmony提供的AI语音能力套件,包含语音识别(ASR)和语音合成(TTS)两大功能。flutter_speech用到的是其中的语音识别部分。

坦白说,Core Speech Kit的文档目前还不够完善。我在适配过程中,很多细节都是靠自己试出来的——比如createEngine的参数格式、setListener的回调时序、各种错误码的含义等。今天我把这些摸索出来的经验都整理出来,希望能帮大家少走弯路。

💡 版本说明:本文基于OpenHarmony API 20的Core Speech Kit。不同API版本的接口可能有差异。

一、HarmonyOS Core Speech Kit 功能介绍

1.1 Kit整体架构

Core Speech Kit是HarmonyOS AI能力的一部分,在系统架构中的位置:

请添加图片描述

图:Core Speech Kit在HarmonyOS系统架构中的位置

┌─────────────────────────────────────────┐
│            应用层 (Application)           │
│  Flutter App → FlutterSpeechPlugin      │
├─────────────────────────────────────────┤
│            框架层 (Framework)             │
│  @kit.CoreSpeechKit                     │
│  ├── speechRecognizer (语音识别)         │
│  └── textToSpeech (语音合成)            │
├─────────────────────────────────────────┤
│            系统服务层 (System Service)    │
│  AI Engine Service                      │
│  Audio Service                          │
├─────────────────────────────────────────┤
│            硬件层 (Hardware)             │
│  麦克风 / 扬声器 / NPU                  │
└─────────────────────────────────────────┘

1.2 两大核心能力

能力 模块 功能 flutter_speech是否使用
语音识别 (ASR) speechRecognizer 语音转文字 ✅ 是
语音合成 (TTS) textToSpeech 文字转语音 ❌ 否

flutter_speech只用到了speechRecognizer模块。如果你以后想做TTS功能,可以参考textToSpeech模块的API。

1.3 导入方式

import { speechRecognizer } from '@kit.CoreSpeechKit';

这一行import就把语音识别相关的所有类型都导入了。speechRecognizer是一个命名空间,包含了引擎创建、参数配置、结果类型等所有内容。

📌 注意导入路径:是@kit.CoreSpeechKit而不是@ohos.ai.speechRecognizer。后者是旧版API的导入方式,在新版SDK中可能已经废弃。

二、speechRecognizer 模块 API 总览

2.1 核心API列表

speechRecognizer模块提供了以下核心API:

API 功能 返回类型 flutter_speech中的使用
createEngine(params) 创建识别引擎 Promise<SpeechRecognitionEngine> activate方法中调用
SpeechRecognitionEngine.setListener(listener) 设置回调监听器 void setupListener方法中调用
SpeechRecognitionEngine.startListening(params) 开始识别 void startListening方法中调用
SpeechRecognitionEngine.finish(sessionId) 正常停止 void stop方法中调用
SpeechRecognitionEngine.cancel(sessionId) 取消识别 void cancel方法中调用
SpeechRecognitionEngine.shutdown() 关闭引擎 void destroyEngine方法中调用

2.2 类型定义

// 引擎创建参数
interface CreateEngineParams {
  language: string;   // 语言代码,如"zh-CN"
  online: number;     // 1=在线识别,0=离线识别
}

// 音频信息
interface AudioInfo {
  audioType: string;    // 音频格式,如"pcm"
  sampleRate: number;   // 采样率,如16000
  soundChannel: number; // 声道数,如1
  sampleBit: number;    // 位深,如16
}

// 启动参数
interface StartParams {
  sessionId: string;              // 会话ID
  audioInfo: AudioInfo;           // 音频参数
  extraParams: Record<string, Object>; // 扩展参数
}

// 识别结果
interface SpeechRecognitionResult {
  result: string;   // 识别文本
  isLast: boolean;  // 是否是最终结果
}

2.3 API调用流程

createEngine(params)          // 1. 创建引擎
    │
setListener(listener)         // 2. 设置监听器
    │
startListening(startParams)   // 3. 开始识别
    │
    ├── onStart()             // 4. 识别开始回调
    ├── onResult(result)      // 5. 识别结果回调(多次)
    ├── onComplete()          // 6. 识别完成回调
    │
finish(sessionId)             // 7. 停止识别(或cancel取消)
    │
shutdown()                    // 8. 关闭引擎

三、SpeechRecognitionEngine 引擎创建与配置

3.1 createEngine 详解

这是整个语音识别流程的起点:

// flutter_speech中的引擎创建代码
this.asrEngine = await speechRecognizer.createEngine({
  language: language,  // "zh-CN"
  online: 1            // 在线识别
});

createEngine是一个异步方法,返回Promise<SpeechRecognitionEngine>。这和Android的SpeechRecognizer.createSpeechRecognizer()(同步)不同,需要用await等待。

3.2 参数详解

参数 类型 可选值 说明
language string “zh-CN” 识别语言,目前仅支持中文
online number 0 或 1 0=离线,1=在线。目前建议用1

⚠️ language参数格式:Core Speech Kit要求使用BCP 47格式(用连字符),如zh-CN。而Dart层传过来的是下划线格式zh_CN。所以需要做格式转换。

flutter_speech中的转换逻辑:

private convertLocale(locale: string): string {
  return locale.replace('_', '-');
  // "zh_CN" → "zh-CN"
  // "en_US" → "en-US"
}

3.3 引擎创建失败的处理

createEngine可能因为多种原因失败:

try {
  this.asrEngine = await speechRecognizer.createEngine({
    language: language,
    online: 1
  });
  console.info(TAG, 'engine created successfully');
} catch (e) {
  console.error(TAG, `createEngine failed: ${JSON.stringify(e)}`);
  // 可能的失败原因:
  // 1. 设备不支持语音识别
  // 2. 语言不支持
  // 3. 网络不可用(在线模式)
  // 4. 系统资源不足
  result.error('SPEECH_ACTIVATION_ERROR',
    `Failed to create engine: ${JSON.stringify(e)}`, null);
}
失败原因 错误表现 解决方案
设备不支持 createEngine抛异常 先用canIUse检测
语言不支持 createEngine抛异常 先用isSupportedLocale检查
网络不可用 createEngine超时或失败 提示用户检查网络
资源不足 createEngine抛异常 先释放旧引擎再创建

3.4 能力检测

在创建引擎之前,应该先检测设备是否支持语音识别:

// 检测设备能力
if (!canIUse('SystemCapability.AI.SpeechRecognizer')) {
  result.error('ERROR_NO_SPEECH_RECOGNITION_AVAILABLE',
    'Device does not support speech recognition', null);
  return;
}

canIUse是OpenHarmony的系统能力检测API,类似Android的PackageManager.hasSystemFeature()

能力标识 含义 说明
SystemCapability.AI.SpeechRecognizer 语音识别 不是所有设备都支持
SystemCapability.AI.TextToSpeech 语音合成 flutter_speech不需要

四、支持的语言与识别模式

4.1 语言支持现状

这是目前Core Speech Kit最大的限制——只支持中文

语言 BCP 47代码 支持状态 说明
中文(普通话) zh-CN ✅ 支持 主要支持的语言
英文 en-US ❌ 不支持 未来可能支持
法文 fr-FR ❌ 不支持 暂无计划
俄文 ru-RU ❌ 不支持 暂无计划
意大利文 it-IT ❌ 不支持 暂无计划
西班牙文 es-ES ❌ 不支持 暂无计划

flutter_speech的语言校验逻辑:

private isSupportedLocale(locale: string): boolean {
  return locale.startsWith('zh');
}

如果用户选择了不支持的语言:

if (!this.isSupportedLocale(language)) {
  result.error('ERROR_LANGUAGE_NOT_SUPPORTED',
    `Language "${locale}" is not supported on HarmonyOS. Only Chinese (zh_CN) is currently supported.`,
    null);
  return;
}

😅 现实吐槽:原插件支持6种语言,到了OpenHarmony只能用中文。这确实是个遗憾,但也没办法,Core Speech Kit目前就是这个能力。好在中文识别的准确率还不错。

4.2 识别模式

Core Speech Kit支持两种识别模式:

模式 online值 特点 适用场景
在线识别 1 准确率高,需要网络 大多数场景
离线识别 0 无需网络,准确率较低 无网络环境

flutter_speech目前使用在线识别(online: 1):

this.asrEngine = await speechRecognizer.createEngine({
  language: language,
  online: 1  // 在线模式
});

📌 为什么选在线模式:在线模式的识别准确率明显高于离线模式,而且大多数使用场景都有网络。如果你的应用需要在无网络环境下工作,可以改成online: 0,但要做好准确率下降的心理准备。

4.3 中英混合识别

虽然Core Speech Kit官方只支持中文,但在实际测试中我发现它对中英混合文本有一定的识别能力:

输入语音:"打开WiFi设置"
识别结果:"打开WiFi设置"  ← 英文单词能正确识别

输入语音:"Hello你好"
识别结果:"Hello你好"     ← 中英混合也能识别

输入语音:"Please open the door"
识别结果:(识别失败或乱码) ← 纯英文不行

所以实际上Core Speech Kit的能力是:以中文为主,能识别常见的英文单词和缩写,但不支持纯英文输入

五、在线识别 vs 离线识别的区别与选择

5.1 详细对比

对比维度 在线识别 (online=1) 离线识别 (online=0)
网络要求 需要网络连接 不需要
识别准确率 高(95%+) 中等(80%+)
响应速度 取决于网络延迟 较快(本地处理)
词汇量 大(云端模型) 有限(本地模型)
隐私性 音频上传到云端 数据不出设备
电量消耗 较高(网络+计算) 较低(仅本地计算)
可用性 受网络影响 始终可用

5.2 选择建议

你的应用需要语音识别
    │
    ├── 用户通常有网络?
    │   ├── 是 → 使用在线模式 (online=1)
    │   └── 否 → 使用离线模式 (online=0)
    │
    ├── 对准确率要求高?
    │   ├── 是 → 使用在线模式
    │   └── 否 → 离线模式也可以
    │
    └── 对隐私要求高?
        ├── 是 → 使用离线模式
        └── 否 → 在线模式

5.3 混合策略

一种更优雅的方案是先尝试在线,失败后降级到离线

// 混合策略示例(flutter_speech当前未实现,仅供参考)
private async createEngineWithFallback(language: string): Promise<void> {
  try {
    // 先尝试在线模式
    this.asrEngine = await speechRecognizer.createEngine({
      language: language,
      online: 1
    });
    console.info(TAG, 'Online engine created');
  } catch (onlineError) {
    console.warn(TAG, `Online engine failed, trying offline: ${onlineError}`);
    try {
      // 降级到离线模式
      this.asrEngine = await speechRecognizer.createEngine({
        language: language,
        online: 0
      });
      console.info(TAG, 'Offline engine created (fallback)');
    } catch (offlineError) {
      console.error(TAG, `Both modes failed: ${offlineError}`);
      throw offlineError;
    }
  }
}

💡 未来改进方向:flutter_speech目前硬编码了online: 1,如果要支持离线模式,可以通过Dart层的参数传递来控制。这是一个很好的PR贡献方向。

六、Core Speech Kit 与其他平台引擎的对比

6.1 三平台引擎对比

对比维度 Android SpeechRecognizer iOS SFSpeechRecognizer OHOS Core Speech Kit
引擎创建 同步 同步 异步
语言支持 多语言 多语言 仅中文
离线支持 部分设备 iOS 13+ 支持但准确率低
音频管理 系统自动 手动(AVAudioEngine) 系统自动
回调模式 RecognitionListener Block闭包 setListener
部分结果 onPartialResults isFinal=false isLast=false
置信度
会话管理 隐式 Task对象 sessionId
VAD控制 系统默认 系统默认 可配置

6.2 Core Speech Kit的独特优势

虽然在语言支持上有限制,但Core Speech Kit也有一些独特的优势

  1. VAD精细控制:可以配置vadBeginvadEnd参数,精确控制语音活动检测的灵敏度
  2. 音频参数可配:可以指定PCM格式、采样率、声道数等,灵活性更高
  3. 会话管理:通过sessionId管理识别会话,便于追踪和调试
  4. 异步创建:引擎创建是异步的,不会阻塞主线程

6.3 flutter_speech中的参数配置

// 音频参数
const audioParam: speechRecognizer.AudioInfo = {
  audioType: 'pcm',      // PCM格式
  sampleRate: 16000,      // 16kHz采样率
  soundChannel: 1,        // 单声道
  sampleBit: 16           // 16位深
};

// 扩展参数
const extraParam: Record<string, Object> = {
  "recognitionMode": 0,   // 识别模式:0=短语音,1=长语音
  "vadBegin": 2000,       // VAD开始超时:2秒内没检测到语音就停止
  "vadEnd": 3000,         // VAD结束超时:3秒静音后认为说话结束
  "maxAudioDuration": 60000 // 最大录音时长:60秒
};
参数 含义 调优建议
audioType “pcm” 音频格式 固定用PCM
sampleRate 16000 采样率 16kHz是语音识别的标准采样率
soundChannel 1 声道数 语音识别用单声道就够了
sampleBit 16 位深 16bit是标准位深
recognitionMode 0 识别模式 0=短语音(适合指令),1=长语音(适合听写)
vadBegin 2000 VAD开始超时(ms) 太短容易误触发,太长用户等待久
vadEnd 3000 VAD结束超时(ms) 太短会截断长句,太长等待时间久
maxAudioDuration 60000 最大时长(ms) 根据业务需求调整

🎯 调优经验vadBegin设2秒、vadEnd设3秒是我测试下来比较平衡的值。如果你的应用是语音指令类的(短句),可以把vadEnd调小到2秒;如果是听写类的(长句),建议调大到5秒。

七、Core Speech Kit 使用注意事项

7.1 引擎生命周期管理

// ✅ 正确的生命周期管理
// 1. 创建引擎
this.asrEngine = await speechRecognizer.createEngine({...});

// 2. 设置监听器
this.asrEngine.setListener({...});

// 3. 开始识别
this.asrEngine.startListening(params);

// 4. 停止或取消
this.asrEngine.finish(sessionId);  // 正常停止
// 或
this.asrEngine.cancel(sessionId);  // 取消

// 5. 不再使用时销毁
this.asrEngine.shutdown();
this.asrEngine = null;
// ❌ 常见错误
// 错误1:不设置监听器就开始识别
this.asrEngine.startListening(params);  // 没有setListener,收不到结果

// 错误2:不销毁引擎
// 引擎会一直占用系统资源

// 错误3:销毁后继续使用
this.asrEngine.shutdown();
this.asrEngine.startListening(params);  // 崩溃!

7.2 并发限制

Core Speech Kit有并发限制——同一时间只能有一个活跃的识别会话:

// ❌ 不能同时进行两个识别
engine1.startListening(params1);
engine2.startListening(params2);  // 可能失败

// ✅ 先停止旧的,再开始新的
if (this.isListening) {
  this.asrEngine.cancel(this.sessionId);
  this.isListening = false;
}
this.asrEngine.startListening(params);

flutter_speech的实现中已经处理了这个问题:

private startListening(result: MethodResult): void {
  // ...
  if (this.isListening) {
    this.asrEngine.cancel(this.sessionId);  // 先取消旧的
    this.isListening = false;
  }
  // 再开始新的
  this.asrEngine.startListening(recognizerParams);
  // ...
}

7.3 错误码参考

错误码 含义 常见原因 处理建议
0 成功 - -
-1 通用错误 参数错误或内部异常 检查参数
-2 网络错误 无网络或网络超时 提示用户检查网络
-3 音频错误 麦克风被占用 释放麦克风资源
-4 引擎错误 引擎未初始化 重新创建引擎
-5 权限错误 未授权麦克风 重新申请权限

7.4 网络依赖

在线识别模式下,Core Speech Kit需要稳定的网络连接:

// 建议在activate时检查网络状态
import { connection } from '@kit.NetworkKit';

private async checkNetwork(): Promise<boolean> {
  try {
    const netHandle = await connection.getDefaultNet();
    const netCapabilities = await connection.getNetCapabilities(netHandle);
    return netCapabilities.networkCap.includes(
      connection.NetCap.NET_CAPABILITY_INTERNET
    );
  } catch (e) {
    return false;
  }
}

八、flutter_speech 中 Core Speech Kit 的完整使用

8.1 完整调用链

把flutter_speech中所有涉及Core Speech Kit的代码串起来:

// 第1步:activate方法中创建引擎
private async activate(locale: string, result: MethodResult): Promise<void> {
  // 1.1 权限检查(需要abilityContext)
  // 1.2 能力检测(canIUse)
  // 1.3 语言校验(isSupportedLocale)

  // 1.4 创建引擎
  const language = this.convertLocale(locale);  // zh_CN → zh-CN
  this.asrEngine = await speechRecognizer.createEngine({
    language: language,
    online: 1
  });

  // 1.5 设置监听器
  this.setupListener();

  // 1.6 通知Dart层引擎就绪
  this.channel?.invokeMethod('speech.onSpeechAvailability', true);
  result.success(true);
}

// 第2步:startListening方法中开始识别
private startListening(result: MethodResult): void {
  // 2.1 配置音频参数
  const audioParam: speechRecognizer.AudioInfo = {
    audioType: 'pcm', sampleRate: 16000, soundChannel: 1, sampleBit: 16
  };

  // 2.2 配置扩展参数
  const extraParam: Record<string, Object> = {
    "recognitionMode": 0, "vadBegin": 2000, "vadEnd": 3000, "maxAudioDuration": 60000
  };

  // 2.3 构建启动参数
  const recognizerParams: speechRecognizer.StartParams = {
    sessionId: this.sessionId,
    audioInfo: audioParam,
    extraParams: extraParam
  };

  // 2.4 开始识别
  this.asrEngine.startListening(recognizerParams);
  result.success(true);
}

// 第3步:setupListener中处理回调
private setupListener(): void {
  this.asrEngine.setListener({
    onStart(sessionId, eventMessage) { /* → speech.onRecognitionStarted */ },
    onResult(sessionId, result) { /* → speech.onSpeech + speech.onRecognitionComplete */ },
    onComplete(sessionId, eventMessage) { /* 识别完成 */ },
    onError(sessionId, errorCode, errorMessage) { /* → speech.onError */ }
  });
}

// 第4步:stop/cancel/destroy
private stop(result: MethodResult): void {
  this.asrEngine.finish(this.sessionId);  // 正常停止
}

private cancel(result: MethodResult): void {
  this.asrEngine.cancel(this.sessionId);  // 取消
}

private destroyEngine(): void {
  this.asrEngine.shutdown();              // 销毁引擎
  this.asrEngine = null;
}

8.2 数据流向图

用户说话
  │
  ▼
麦克风采集音频 (系统自动)
  │
  ▼
Core Speech Kit 处理
  │
  ├── onStart → channel.invokeMethod('speech.onRecognitionStarted')
  │                    │
  │                    ▼
  │              Dart: recognitionStartedHandler()
  │
  ├── onResult(isLast=false) → channel.invokeMethod('speech.onSpeech', text)
  │                                     │
  │                                     ▼
  │                               Dart: recognitionResultHandler(text)
  │                               UI更新:显示实时识别文本
  │
  ├── onResult(isLast=true) → channel.invokeMethod('speech.onRecognitionComplete', text)
  │                                    │
  │                                    ▼
  │                              Dart: recognitionCompleteHandler(text)
  │                              UI更新:显示最终结果,停止动画
  │
  └── onError → channel.invokeMethod('speech.onError', errorCode)
                        │
                        ▼
                  Dart: errorHandler()
                  重新激活引擎

总结

本文全面介绍了OpenHarmony Core Speech Kit的核心知识:

  1. Kit架构:Core Speech Kit包含语音识别和语音合成两大能力,flutter_speech使用语音识别部分
  2. API总览:createEngine → setListener → startListening → finish/cancel → shutdown,流程清晰
  3. 引擎创建:异步创建,需要指定语言和在线/离线模式
  4. 语言限制:目前仅支持中文,这是最大的限制
  5. 在线vs离线:在线准确率高但需要网络,离线无需网络但准确率低
  6. 参数配置:音频参数和VAD参数可以精细调优

到这里,第1-10篇的核心文章就全部完成了。我们已经覆盖了从项目背景到Core Speech Kit的所有基础知识。从第11篇开始,我们将深入具体的功能实现——权限申请、引擎创建、监听器实现等。

如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!


相关资源:

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐