HarmonyOS APP开发:语音识别ASR技术深度实践

举报
Jack20 发表于 2026/06/21 12:08:20 2026/06/21
【摘要】 HarmonyOS APP开发:语音识别ASR技术深度实践核心要点:掌握HarmonyOS语音识别(ASR)能力调用、实时流式识别、离线识别配置,以及识别结果的后处理与业务集成。 一、背景与动机你有没有这样的体验——开车时想给朋友发条消息,但双手握着方向盘根本腾不出手来打字?或者做菜时想查个食谱,手上全是油渍不方便碰手机?这些场景下,语音输入就成了最自然的交互方式。语音识别(Automat...

HarmonyOS APP开发:语音识别ASR技术深度实践

核心要点:掌握HarmonyOS语音识别(ASR)能力调用、实时流式识别、离线识别配置,以及识别结果的后处理与业务集成。


一、背景与动机

你有没有这样的体验——开车时想给朋友发条消息,但双手握着方向盘根本腾不出手来打字?或者做菜时想查个食谱,手上全是油渍不方便碰手机?这些场景下,语音输入就成了最自然的交互方式。

语音识别(Automatic Speech Recognition,ASR)就是把人说的话转成文字的技术。听起来简单,但背后涉及声学模型、语言模型、解码器等一整套深度学习管线。好在HarmonyOS已经把这些能力封装成了标准API,我们作为应用开发者,只需要关心"怎么调用"和"怎么用好"。

HarmonyOS的语音识别能力有几个亮点:

  • 支持实时流式识别:边说边出字,用户体验丝滑
  • 支持离线识别:没网也能用,保护隐私
  • 多语言支持:中文、英文、粤语等主流语种全覆盖
  • 端云协同:本地轻量模型+云端大模型,灵活切换

今天这篇文章,我们就来深入聊聊HarmonyOS上ASR的完整开发实践。


二、核心原理

2.1 ASR技术架构总览

语音识别的核心流程可以概括为:音频采集 → 预处理 → 特征提取 → 声学解码 → 语言模型修正 → 输出文本

在HarmonyOS中,这个流程被封装为speechRecognizer模块,开发者通过SpeechRecognizer引擎与系统服务交互。

flowchart TD
    A[用户语音输入] --> B[音频采集模块]
    B --> C[预处理:降噪/VAD]
    C --> D[特征提取:MFCC/Fbank]
    D --> E{识别模式选择}
    E -->|在线模式| F[云端ASR引擎]
    E -->|离线模式| G[端侧ASR引擎]
    F --> H[声学模型解码]
    G --> H
    H --> I[语言模型修正]
    I --> J[输出识别文本]
    J --> K[业务逻辑处理]
    
    classDef primary fill:#4FC3F7,stroke:#0288D1,color:#000
    classDef warning fill:#FFB74D,stroke:#F57C00,color:#000
    classDef error fill:#EF5350,stroke:#C62828,color:#FFF
    classDef info fill:#81C784,stroke:#388E3C,color:#000
    classDef purple fill:#CE93D8,stroke:#7B1FA2,color:#000
    
    class A,B primary
    class C,D info
    class E warning
    class F,G purple
    class H,I,J,K primary

2.2 端云协同机制

HarmonyOS的ASR采用端云协同架构:

维度 端侧识别 云端识别
延迟 极低(<100ms) 较高(200-500ms)
准确率 中等(92-95%) 高(97%+)
网络依赖 必须联网
隐私性 高,数据不出设备 低,音频上传云端
适用场景 简单指令、隐私敏感 长文本、专业术语

2.3 流式识别原理

流式识别是ASR体验的关键。传统识别是"说完再出结果",而流式识别是"边说边出",核心区别在于解码策略:

  • 全量解码:等整段音频录完,一次性解码,准确率最高但延迟大
  • 流式解码:按固定帧长(通常100-200ms)增量解码,实时输出中间结果,最终输出确认结果

HarmonyOS的onResult回调中,isFinal字段标识了当前结果是中间结果还是最终结果。


三、代码实战

3.1 基础语音识别——一次性识别

最简单的用法:点击按钮开始录音,说完后获取识别结果。

// ASR基础识别示例
import { speechRecognizer } from '@kit.AISpeechKit';
import { BusinessError } from '@kit.BasicServicesKit';

@Entry
@Component
struct BasicASRPage {
  // 识别结果状态
  @State recognizeText: string = '点击按钮开始识别';
  @State isListening: boolean = false;
  
  // 语音识别引擎实例
  private asrEngine: speechRecognizer.SpeechRecognizer | null = null;

  aboutToAppear(): void {
    this.initASREngine();
  }

  // 初始化ASR引擎
  private initASREngine(): void {
    try {
      // 创建语音识别引擎,使用中文普通话
      const extraParams: Record<string, Object> = {
        'locate': 'CN',        // 地区:中国
        'language': 'zh-CN',   // 语言:中文普通话
      };
      const initParams: speechRecognizer.CreateEngineParams = {
        language: 'zh-CN',
        extraParams: extraParams
      };
      
      this.asrEngine = speechRecognizer.createEngine(initParams);
      console.info('[ASR] 引擎创建成功');
      
      // 设置识别结果回调
      this.setupCallbacks();
    } catch (error) {
      const err = error as BusinessError;
      console.error(`[ASR] 引擎创建失败: code=${err.code}, msg=${err.message}`);
    }
  }

  // 设置识别回调监听
  private setupCallbacks(): void {
    if (!this.asrEngine) return;

    // 识别结果回调
    this.asrEngine.on('result', (callback: speechRecognizer.Result) => {
      if (callback.isFinal) {
        // 最终结果
        this.recognizeText = callback.result;
        this.isListening = false;
        console.info(`[ASR] 最终结果: ${callback.result}`);
      } else {
        // 中间结果(流式识别时使用)
        this.recognizeText = callback.result + '...';
        console.info(`[ASR] 中间结果: ${callback.result}`);
      }
    });

    // 识别完成回调
    this.asrEngine.on('complete', () => {
      this.isListening = false;
      console.info('[ASR] 识别完成');
    });

    // 错误回调
    this.asrEngine.on('error', (callback: speechRecognizer.Error) => {
      this.isListening = false;
      console.error(`[ASR] 识别错误: code=${callback.code}, msg=${callback.message}`);
    });
  }

  // 开始识别
  private startListening(): void {
    if (!this.asrEngine) {
      console.error('[ASR] 引擎未初始化');
      return;
    }

    try {
      const listenerInfo: speechRecognizer.ListenerInfo = {
        sessionId: 'basic_asr_session_001'
      };
      
      this.asrEngine.startListening(listenerInfo);
      this.isListening = true;
      this.recognizeText = '正在聆听...';
      console.info('[ASR] 开始监听');
    } catch (error) {
      const err = error as BusinessError;
      console.error(`[ASR] 启动监听失败: code=${err.code}, msg=${err.message}`);
    }
  }

  // 停止识别
  private stopListening(): void {
    if (!this.asrEngine) return;
    try {
      this.asrEngine.finish('basic_asr_session_001');
      console.info('[ASR] 停止监听');
    } catch (error) {
      const err = error as BusinessError;
      console.error(`[ASR] 停止监听失败: code=${err.code}, msg=${err.message}`);
    }
  }

  build() {
    Column({ space: 20 }) {
      // 标题
      Text('语音识别')
        .fontSize(28)
        .fontWeight(FontWeight.Bold)
        .fontColor('#E0E0E0')

      // 识别结果展示区
      Column() {
        Text(this.recognizeText)
          .fontSize(20)
          .fontColor('#FFFFFF')
          .textAlign(TextAlign.Center)
          .padding(20)
      }
      .width('90%')
      .minHeight(200)
      .borderRadius(16)
      .backgroundColor('rgba(255,255,255,0.08)')
      .backdropBlur(20)
      .justifyContent(FlexAlign.Center)

      // 控制按钮
      Button(this.isListening ? '停止识别' : '开始识别')
        .width('80%')
        .height(56)
        .fontSize(18)
        .fontColor('#FFFFFF')
        .backgroundColor(this.isListening ? '#EF5350' : '#4FC3F7')
        .borderRadius(28)
        .onClick(() => {
          if (this.isListening) {
            this.stopListening();
          } else {
            this.startListening();
          }
        })
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#1A1A2E')
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
  }

  aboutToDisappear(): void {
    // 释放引擎资源
    if (this.asrEngine) {
      this.asrEngine.off('result');
      this.asrEngine.off('complete');
      this.asrEngine.off('error');
      this.asrEngine = null;
    }
  }
}

3.2 流式识别——实时语音转写

流式识别是语音输入法、会议记录等场景的核心能力。关键在于处理中间结果与最终结果的差异。

// 流式语音识别示例——会议实时转写
import { speechRecognizer } from '@kit.AISpeechKit';
import { BusinessError } from '@kit.BasicServicesKit';

interface TranscriptEntry {
  text: string;       // 识别文本
  isFinal: boolean;   // 是否为最终结果
  timestamp: number;  // 时间戳
}

@Entry
@Component
struct StreamingASRPage {
  @State transcriptList: TranscriptEntry[] = [];
  @State currentPartial: string = '';
  @State isRecording: boolean = false;
  @State elapsedTime: string = '00:00';
  
  private asrEngine: speechRecognizer.SpeechRecognizer | null = null;
  private startTime: number = 0;
  private timerId: number = -1;

  aboutToAppear(): void {
    this.initStreamingASR();
  }

  // 初始化流式识别引擎
  private initStreamingASR(): void {
    try {
      const extraParams: Record<string, Object> = {
        'locate': 'CN',
        'language': 'zh-CN',
        'vadBegin': 6000,   // 语音起始超时:6秒无语音自动结束
        'vadEnd': 2000,     // 语音尾端超时:2秒静音自动结束
        'maxAudioDuration': 60000, // 最大录音时长60秒
      };
      
      const initParams: speechRecognizer.CreateEngineParams = {
        language: 'zh-CN',
        extraParams: extraParams
      };
      
      this.asrEngine = speechRecognizer.createEngine(initParams);
      this.setupStreamingCallbacks();
      console.info('[StreamingASR] 流式引擎初始化成功');
    } catch (error) {
      const err = error as BusinessError;
      console.error(`[StreamingASR] 初始化失败: ${err.code} - ${err.message}`);
    }
  }

  // 设置流式识别回调
  private setupStreamingCallbacks(): void {
    if (!this.asrEngine) return;

    // 流式结果回调——核心!
    this.asrEngine.on('result', (callback: speechRecognizer.Result) => {
      if (callback.isFinal) {
        // 最终结果:追加到历史记录
        this.transcriptList.push({
          text: callback.result,
          isFinal: true,
          timestamp: Date.now()
        });
        this.currentPartial = '';
        console.info(`[StreamingASR] 最终: ${callback.result}`);
      } else {
        // 中间结果:更新当前行(实时刷新)
        this.currentPartial = callback.result;
        console.info(`[StreamingASR] 中间: ${callback.result}`);
      }
    });

    // 识别完成——自动重启实现连续识别
    this.asrEngine.on('complete', () => {
      if (this.isRecording) {
        // 如果还在录音状态,自动重新开始下一轮识别
        this.restartListening();
      }
    });

    this.asrEngine.on('error', (callback: speechRecognizer.Error) => {
      console.error(`[StreamingASR] 错误: ${callback.code} - ${callback.message}`);
      if (this.isRecording && callback.code !== 11200002) {
        // 非用户主动取消的错误,尝试重启
        this.restartListening();
      }
    });
  }

  // 重新开始监听(连续识别的关键)
  private restartListening(): void {
    if (!this.asrEngine) return;
    try {
      const listenerInfo: speechRecognizer.ListenerInfo = {
        sessionId: `stream_session_${Date.now()}`
      };
      this.asrEngine.startListening(listenerInfo);
    } catch (error) {
      console.error('[StreamingASR] 重启监听失败');
    }
  }

  // 开始录音
  private startRecording(): void {
    if (!this.asrEngine) return;
    
    this.isRecording = true;
    this.transcriptList = [];
    this.currentPartial = '';
    this.startTime = Date.now();
    
    // 启动计时器
    this.timerId = setInterval(() => {
      const elapsed = Math.floor((Date.now() - this.startTime) / 1000);
      const min = String(Math.floor(elapsed / 60)).padStart(2, '0');
      const sec = String(elapsed % 60).padStart(2, '0');
      this.elapsedTime = `${min}:${sec}`;
    }, 1000);

    const listenerInfo: speechRecognizer.ListenerInfo = {
      sessionId: `stream_session_${Date.now()}`
    };
    this.asrEngine.startListening(listenerInfo);
  }

  // 停止录音
  private stopRecording(): void {
    if (!this.asrEngine) return;
    this.isRecording = false;
    clearInterval(this.timerId);
    this.asrEngine.finish(`stream_session_${Date.now()}`);
  }

  build() {
    Column({ space: 16 }) {
      // 顶部状态栏
      Row({ space: 12 }) {
        Text('实时转写')
          .fontSize(24)
          .fontWeight(FontWeight.Bold)
          .fontColor('#E0E0E0')
        
        if (this.isRecording) {
          // 录音指示灯
          Circle({ width: 12, height: 12 })
            .fill('#EF5350')
          Text(this.elapsedTime)
            .fontSize(16)
            .fontColor('#EF5350')
            .fontFamily('monospace')
        }
      }
      .width('90%')
      .justifyContent(FlexAlign.SpaceBetween)

      // 转写内容区域
      Scroll() {
        Column({ space: 8 }) {
          ForEach(this.transcriptList, (entry: TranscriptEntry, index: number) => {
            Row() {
              Text(entry.text)
                .fontSize(16)
                .fontColor('#E0E0E0')
                .width('100%')
            }
            .width('100%')
            .padding(12)
            .borderRadius(8)
            .backgroundColor('rgba(255,255,255,0.05)')
          }, (entry: TranscriptEntry, index: number) => `${index}`)

          // 当前正在识别的中间结果
          if (this.currentPartial) {
            Row() {
              Text(this.currentPartial)
                .fontSize(16)
                .fontColor('#4FC3F7')
                .fontStyle(FontStyle.Italic)
                .width('100%')
            }
            .width('100%')
            .padding(12)
            .borderRadius(8)
            .backgroundColor('rgba(79,195,247,0.1)')
            .border({ width: 1, color: 'rgba(79,195,247,0.3)' })
          }
        }
      }
      .width('90%')
      .layoutWeight(1)
      .align(Alignment.Top)

      // 底部控制区
      Row({ space: 20 }) {
        Button(this.isRecording ? '停止' : '开始转写')
          .width(160)
          .height(56)
          .fontSize(18)
          .fontColor('#FFFFFF')
          .backgroundColor(this.isRecording ? '#EF5350' : '#4FC3F7')
          .borderRadius(28)
          .onClick(() => {
            if (this.isRecording) {
              this.stopRecording();
            } else {
              this.startRecording();
            }
          })

        // 导出按钮
        Button('导出文本')
          .width(120)
          .height(56)
          .fontSize(16)
          .fontColor('#81C784')
          .backgroundColor('rgba(129,199,132,0.15)')
          .borderRadius(28)
          .enabled(this.transcriptList.length > 0)
          .onClick(() => {
            const fullText = this.transcriptList
              .map(e => e.text)
              .join('\n');
            console.info(`[导出] ${fullText}`);
          })
      }
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#1A1A2E')
    .justifyContent(FlexAlign.Start)
    .padding({ top: 40 })
  }

  aboutToDisappear(): void {
    clearInterval(this.timerId);
    if (this.asrEngine) {
      this.asrEngine.off('result');
      this.asrEngine.off('complete');
      this.asrEngine.off('error');
      this.asrEngine = null;
    }
  }
}

3.3 离线识别——无网络环境下的语音输入

离线识别对于隐私敏感场景(如金融、医疗)和弱网环境至关重要。HarmonyOS支持端侧ASR引擎,需要在创建引擎时指定离线模式。

// 离线语音识别示例
import { speechRecognizer } from '@kit.AISpeechKit';
import { BusinessError } from '@kit.BasicServicesKit';

@Entry
@Component
struct OfflineASRPage {
  @State offlineResult: string = '等待离线识别...';
  @State isListening: boolean = false;
  @State engineMode: string = 'offline'; // offline / online
  @State confidence: number = 0;
  
  private asrEngine: speechRecognizer.SpeechRecognizer | null = null;

  aboutToAppear(): void {
    this.initOfflineEngine();
  }

  // 初始化离线识别引擎
  private initOfflineEngine(): void {
    try {
      // 关键:通过extraParams指定离线模式
      const extraParams: Record<string, Object> = {
        'locate': 'CN',
        'language': 'zh-CN',
        // 指定使用端侧引擎(离线模式)
        'recognizerMode': 'offline',
        // 离线识别的音频格式
        'audioFormat': 'pcm',
        'sampleRate': 16000,
      };
      
      const initParams: speechRecognizer.CreateEngineParams = {
        language: 'zh-CN',
        extraParams: extraParams
      };
      
      this.asrEngine = speechRecognizer.createEngine(initParams);
      this.setupOfflineCallbacks();
      console.info('[OfflineASR] 离线引擎初始化成功');
    } catch (error) {
      const err = error as BusinessError;
      console.error(`[OfflineASR] 初始化失败: ${err.code} - ${err.message}`);
      // 离线引擎不可用时,降级到在线模式
      this.fallbackToOnline();
    }
  }

  // 降级到在线模式
  private fallbackToOnline(): void {
    try {
      const extraParams: Record<string, Object> = {
        'locate': 'CN',
        'language': 'zh-CN',
        'recognizerMode': 'online',
      };
      const initParams: speechRecognizer.CreateEngineParams = {
        language: 'zh-CN',
        extraParams: extraParams
      };
      this.asrEngine = speechRecognizer.createEngine(initParams);
      this.setupOfflineCallbacks();
      this.engineMode = 'online';
      console.info('[OfflineASR] 降级到在线模式');
    } catch (error) {
      console.error('[OfflineASR] 在线模式也不可用');
    }
  }

  // 设置离线识别回调
  private setupOfflineCallbacks(): void {
    if (!this.asrEngine) return;

    this.asrEngine.on('result', (callback: speechRecognizer.Result) => {
      if (callback.isFinal) {
        this.offlineResult = callback.result;
        this.isListening = false;
        // 离线识别通常带有置信度信息
        console.info(`[OfflineASR] 离线结果: ${callback.result}`);
      }
    });

    this.asrEngine.on('complete', () => {
      this.isListening = false;
    });

    this.asrEngine.on('error', (callback: speechRecognizer.Error) => {
      this.isListening = false;
      this.offlineResult = `识别错误: ${callback.message}`;
      console.error(`[OfflineASR] 错误: ${callback.code}`);
    });
  }

  // 开始离线识别
  private startOfflineListening(): void {
    if (!this.asrEngine) return;
    
    this.isListening = true;
    this.offlineResult = '正在聆听(离线模式)...';
    
    const listenerInfo: speechRecognizer.ListenerInfo = {
      sessionId: `offline_session_${Date.now()}`
    };
    this.asrEngine.startListening(listenerInfo);
  }

  build() {
    Column({ space: 20 }) {
      Text('离线语音识别')
        .fontSize(28)
        .fontWeight(FontWeight.Bold)
        .fontColor('#E0E0E0')

      // 引擎模式指示
      Row({ space: 8 }) {
        Circle({ width: 8, height: 8 })
          .fill(this.engineMode === 'offline' ? '#81C784' : '#FFB74D')
        Text(this.engineMode === 'offline' ? '端侧引擎' : '云端引擎(降级)')
          .fontSize(14)
          .fontColor(this.engineMode === 'offline' ? '#81C784' : '#FFB74D')
      }

      // 结果展示
      Column() {
        Text(this.offlineResult)
          .fontSize(20)
          .fontColor('#FFFFFF')
          .textAlign(TextAlign.Center)
          .padding(20)
      }
      .width('90%')
      .minHeight(180)
      .borderRadius(16)
      .backgroundColor('rgba(255,255,255,0.08)')
      .backdropBlur(20)

      // 开始按钮
      Button(this.isListening ? '停止' : '开始离线识别')
        .width('80%')
        .height(56)
        .fontSize(18)
        .fontColor('#FFFFFF')
        .backgroundColor(this.isListening ? '#EF5350' : '#81C784')
        .borderRadius(28)
        .onClick(() => {
          if (this.isListening) {
            this.asrEngine?.finish(`offline_session_${Date.now()}`);
          } else {
            this.startOfflineListening();
          }
        })

      // 提示信息
      Text('离线识别无需联网,数据不出设备,适合隐私敏感场景')
        .fontSize(12)
        .fontColor('#9E9E9E')
        .width('80%')
        .textAlign(TextAlign.Center)
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#1A1A2E')
    .justifyContent(FlexAlign.Center)
  }

  aboutToDisappear(): void {
    if (this.asrEngine) {
      this.asrEngine.off('result');
      this.asrEngine.off('complete');
      this.asrEngine.off('error');
      this.asrEngine = null;
    }
  }
}

四、踩坑与注意事项

4.1 权限配置

语音识别需要申请麦克风权限,在module.json5中添加:

{
  "requestPermissions": [
    {
      "name": "ohos.permission.MICROPHONE",
      "reason": "$string:microphone_reason",
      "usedScene": {
        "abilities": ["EntryAbility"],
        "when": "inuse"
      }
    }
  ]
}

⚠️ 注意:麦克风权限是用户授权权限,必须动态申请,不能静默获取。首次使用时务必调用requestPermissionsFromUser()

4.2 引擎生命周期管理

这是新手最容易踩的坑:

  1. 引擎只能创建一次:不要在每次识别时都createEngine(),应该在页面初始化时创建,页面销毁时释放。
  2. sessionId必须唯一:每次startListening()时使用不同的sessionId,避免与上一次冲突。
  3. 回调必须先注册再启动:先调用on('result')注册回调,再调用startListening(),否则可能丢失结果。
  4. 页面销毁时必须off:在aboutToDisappear()中调用off()移除所有回调,否则会内存泄漏。

4.3 VAD参数调优

VAD(Voice Activity Detection)参数直接影响识别体验:

参数 默认值 建议值 说明
vadBegin 6000ms 3000-6000ms 开始后多久没检测到语音就结束
vadEnd 2000ms 1500-3000ms 静音多久后认为说完
maxAudioDuration 60000ms 按需设置 单次最大录音时长

调优建议

  • 会议转写场景:vadEnd设大一些(3000ms),避免说话停顿被误判为结束
  • 语音指令场景:vadEnd设小一些(1500ms),快速响应
  • 长文本输入:maxAudioDuration设大(300000ms),支持5分钟长录音

4.4 离线模型可用性检查

离线识别依赖设备端预装的语音模型,并非所有设备都支持。务必做好降级处理:

// 检查离线引擎是否可用
private async checkOfflineAvailability(): Promise<boolean> {
  try {
    const extraParams: Record<string, Object> = {
      'recognizerMode': 'offline',
      'language': 'zh-CN',
    };
    const initParams: speechRecognizer.CreateEngineParams = {
      language: 'zh-CN',
      extraParams: extraParams
    };
    const testEngine = speechRecognizer.createEngine(initParams);
    // 创建成功说明离线可用
    return true;
  } catch {
    // 创建失败,离线不可用
    return false;
  }
}

4.5 多语言识别切换

切换识别语言时,需要重新创建引擎,不能在运行时切换:

// 错误做法:直接切换语言
// this.asrEngine.startListening({ language: 'en-US' }); // ❌ 不支持

// 正确做法:销毁旧引擎,创建新引擎
private switchLanguage(lang: string): void {
  // 先释放旧引擎
  if (this.asrEngine) {
    this.asrEngine.off('result');
    this.asrEngine.off('complete');
    this.asrEngine.off('error');
    this.asrEngine = null;
  }
  // 用新语言创建引擎
  const initParams: speechRecognizer.CreateEngineParams = {
    language: lang,
    extraParams: { 'locate': lang === 'zh-CN' ? 'CN' : 'US' }
  };
  this.asrEngine = speechRecognizer.createEngine(initParams);
  this.setupCallbacks();
}

五、HarmonyOS 6适配

5.1 API变更

HarmonyOS 6对语音识别API做了以下调整:

变更项 HarmonyOS 5 HarmonyOS 6
引擎创建 createEngine() createEngine()不变,但extraParams新增preferOnline字段
离线模型 部分设备不支持 全线设备预装端侧模型,准确率提升5%
流式回调 on('result') 新增on('partialResult')分离中间结果回调
错误码 11200001-11200010 新增11200011(模型加载超时)、11200012(并发限制)

5.2 迁移指南

// HarmonyOS 6 推荐的引擎创建方式
const extraParams: Record<string, Object> = {
  'locate': 'CN',
  'language': 'zh-CN',
  // HarmonyOS 6新增:优先使用在线引擎
  'preferOnline': true,
  // HarmonyOS 6新增:自动降级到离线
  'autoFallback': true,
};

5.3 新增能力

HarmonyOS 6的ASR新增了以下能力:

  • 标点符号预测:自动在识别结果中添加标点,extraParams中设置'punctuation': true
  • 逆文本正则化(ITN):将"一百二十三"转为"123",设置'itn': true
  • 敏感词过滤:云端识别支持敏感词屏蔽,设置'filterProfanity': true

六、总结

mindmap
  root((HarmonyOS ASR))
    引擎管理
      创建 createEngine
      释放 aboutToDisappear
      生命周期管理
    识别模式
      在线识别 高准确率
      离线识别 隐私安全
      端云协同 自动降级
    核心回调
      on result 识别结果
      on complete 识别完成
      on error 错误处理
    参数调优
      VAD超时配置
      最大录音时长
      多语言切换
    HarmonyOS 6
      preferOnline字段
      partialResult回调
      标点预测 ITN
    踩坑要点
      麦克风权限动态申请
      sessionId唯一性
      回调注册顺序
      离线模型可用性检查
    
    classDef primary fill:#4FC3F7,stroke:#0288D1,color:#000
    classDef warning fill:#FFB74D,stroke:#F57C00,color:#000
    classDef error fill:#EF5350,stroke:#C62828,color:#FFF
    classDef info fill:#81C784,stroke:#388E3C,color:#000
    classDef purple fill:#CE93D8,stroke:#7B1FA2,color:#000
知识点 关键内容
引擎创建 speechRecognizer.createEngine(),指定language和extraParams
流式识别 on('result')中通过isFinal区分中间/最终结果
离线识别 extraParams设置recognizerMode: 'offline',注意降级处理
VAD调优 vadBegin/vadEnd/maxAudioDuration按场景调整
权限管理 麦克风权限需动态申请,不能静默获取
生命周期 引擎只创建一次,回调先注册再启动,页面销毁时off
HarmonyOS 6 新增preferOnline、autoFallback、标点预测、ITN

语音识别是语音智能的"耳朵",是所有语音交互的起点。掌握了ASR,你就掌握了让应用"听懂"用户的能力。下一篇我们将聊聊"嘴巴"——语音合成TTS,让应用能"说话"。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。