SEO技术

SEO技术

Products

当前位置:首页 > SEO技术 >

如何为Flutter项目集成OpenHarmony平台,使用flutter_speech库创建语音识别引擎?

96SEO 2026-02-20 07:44 0


如何为Flutter项目集成OpenHarmony平台,使用flutter_speech库创建语音识别引擎?

xmlns="http://www.w3.org/2000/svg"

style="display:

none;">

前言

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

上一篇搞定了权限申请,今天来讲语音识别引擎的创建——speechRecognizer.createEngine

这是整个语音识别流程中最关键的一步,引擎创建成功了,后面的监听、识别、停止都是顺水推舟的事。

说实话,createEngine这个API看起来很简单——就两个参数嘛。

但实际用起来,参数格式、异步处理、异常捕获、能力检测,每一个环节都有讲究。

我在适配过程中,光是language参数的格式转换就折腾了好一会儿——Dart层传过来的是zh_CN(下划线),Core

Speech

Kit要求的是zh-CN(连字符),差一个符号引擎就创建失败。

今天把activate方法中引擎创建相关的所有细节都讲透。

💡本文对应源码FlutterSpeechPlugin.etsactivate方法,第80-131行。

一、speechRecognizer.createEngine

参数详解

1.1

API签名

speechRecognizer.createEngine(params:CreateEngineParams):Promise<SpeechRecognitionEngine>

这是一个异步方法,返回Promise

必须用await等待引擎创建完成。

/>

1.2

参数

interfaceCreateEngineParams{language:string;//

识别语言,BCP

47格式online:number;//

识别模式:1=在线,0=离线}

flutter_speech中的调用:

this.asrEngine=awaitspeechRecognizer.createEngine({language:language,//

"zh-CN"online:1//

在线识别});

参数类型必填说明flutter_speech的值
languagestringBCP

47语言代码

由Dart层传入,经convertLocale转换
onlinenumber1=在线,0=离线固定为1

1.3

为什么是异步的

Android的SpeechRecognizer.createSpeechRecognizer()是同步的,为什么OpenHarmony的createEngine是异步的?

原因是Core

Speech

Kit在创建引擎时需要做一些耗时操作

  1. 检查系统AI服务是否可用
  2. 加载语音识别模型
  3. 建立与AI引擎服务的连接
  4. 初始化音频采集管道

如果这些操作是同步的,会阻塞主线程,导致UI卡顿。

所以设计成异步是合理的。

//

正确:用await等待this.asrEngine=awaitspeechRecognizer.createEngine({...});console.info(TAG,'engine

created');//

引擎已就绪//

错误:不等待直接使用speechRecognizer.createEngine({...});//

返回Promise,引擎还没创建好this.asrEngine.startListening(...);//

asrEngine是undefined,崩溃!

📌这也是为什么activate方法是async:因为内部需要await两个异步操作——权限申请和引擎创建。

二、language

参数格式转换:locale

问题背景

Dart层传过来的locale格式是下划线分隔的(如zh_CN),这是Dart/Flutter的标准格式。

但Core

Speech

47格式(连字符分隔,如zh-CN)。

Dart层:

"zh_CN"

"fr-FR"

2.2

convertLocale

实现

flutter_speech的转换逻辑非常简洁:

privateconvertLocale(locale:string):string{returnlocale.replace('_','-');}

就一行代码,把下划线替换成连字符。

2.3

为什么不用更复杂的转换

你可能会想:是不是应该做更完整的BCP

47解析?比如处理zh-Hans-CN这种三段式格式?

实际上不需要。

flutter_speech的Dart层只传两段式的locale(如zh_CNen_US),而且Core

Speech

Kit目前只支持中文,所以简单的replace就够了。

但如果你在做一个更通用的插件,可能需要更健壮的转换:

//

更健壮的转换(flutter_speech不需要这么复杂)privateconvertLocale(locale:string):string{//

"zh_CN"

"zh-Hans-CN"returnlocale.replace(/_/g,'-');//

全局替换所有下划线}

💡注意:flutter_speech用的是replace('_',

'-')(不带g标志),只替换第一个下划线。

对于两段式locale来说足够了。

如果有三段式locale,需要用正则的全局替换replace(/_/g,

'-')

2.4

locale转换的调用位置

//

activate方法中的调用链constlanguage=this.convertLocale(locale);//

"zh_CN"

"zh-CN"if(!this.isSupportedLocale(language)){//

语言不支持,返回错误result.error('ERROR_LANGUAGE_NOT_SUPPORTED',...);return;}//

用转换后的language创建引擎this.asrEngine=awaitspeechRecognizer.createEngine({language:language,//

"zh-CN"online:1});

三、online

参数含义

模式网络要求准确率延迟
1在线识别需要网络取决于网络
0离线识别不需要中等较低

3.2

flutter_speech的选择

flutter_speech硬编码了online:

1(在线模式):

this.asrEngine=awaitspeechRecognizer.createEngine({language:language,online:1//

固定在线模式});

为什么选在线模式:

  1. 准确率更高:在线模式使用云端大模型,识别准确率明显优于离线
  2. 词汇量更大:云端模型的词汇覆盖面更广
  3. 大多数场景有网络:手机用户通常都有网络连接

3.3

未来改进方向

如果要支持用户选择在线/离线模式,可以通过Dart层传参:

//

Dart层(未来可能的改进)Futureactivate(Stringlocale,{bool

online=true})=>_channel.invokeMethod("speech.activate",{'locale':locale,'online':online,});

//

原生端接收参数case"speech.activate":constargs=call.argsasRecord<string,Object>;constlocale=String(args['locale']);constonline=args['online']asboolean;this.activate(locale,online?1:0,result);break;

📌当前flutter_speech的Dart层只传一个locale字符串,所以原生端用String(call.args)直接获取。

如果要传多个参数,需要改成Map格式。

四、SystemCapability.AI.SpeechRecognizer

能力检测

4.1

为什么需要能力检测

不是所有OpenHarmony设备都支持语音识别。

在创建引擎之前,应该先检测设备是否具备这个能力:

if(!canIUse('SystemCapability.AI.SpeechRecognizer')){result.error('ERROR_NO_SPEECH_RECOGNITION_AVAILABLE','Device

does

recognition',null);return;}

4.2

canIUse

API

canIUse是OpenHarmony的全局函数,用于检测系统能力:

functioncanIUse(syscap:string):boolean
参数说明示例
syscap系统能力标识“SystemCapability.AI.SpeechRecognizer”

返回true表示设备支持该能力,false表示不支持。

4.3

哪些设备可能不支持

设备类型是否支持语音识别原因
手机(旗舰)

通常支持

有AI芯片和麦克风
手机(入门)⚠️

可能不支持

硬件能力不足
平板

通常支持

和手机类似
智慧屏⚠️

取决于型号

部分型号无麦克风
穿戴设备

通常不支持

算力和存储不足
开发板

通常不支持

无AI服务

4.4

能力检测的位置

flutter_speech把能力检测放在权限申请之后、引擎创建之前:

//

权限申请//

在这里if(!canIUse('SystemCapability.AI.SpeechRecognizer')){result.error('ERROR_NO_SPEECH_RECOGNITION_AVAILABLE',...);return;}//

语言校验//

...

为什么不把能力检测放在最前面?因为即使设备支持语音识别,没有权限也用不了。

先检查权限可以更早地给用户反馈。

💡不过这个顺序见仁见智

有人觉得应该先检测能力再申请权限——如果设备不支持,就没必要弹权限弹窗了。

两种方式都有道理,flutter_speech选择了先权限后能力的顺序。

五、引擎创建失败的异常处理与降级方案

5.1

可能的失败原因

createEngine可能因为多种原因失败,抛出异常:

失败原因错误表现发生概率
语言不支持异常:language

not

supported

高(非中文时)
网络不可用异常:network

error

中(在线模式)
AI服务未启动异常:service

not

available

系统资源不足异常:resource

exhausted

极低
引擎已存在异常:engine

already

exists

5.2

flutter_speech的异常处理

try{this.asrEngine=awaitspeechRecognizer.createEngine({language:language,online:1});console.info(TAG,`engine

created

successfully`);this.setupListener();this.channel?.invokeMethod('speech.onSpeechAvailability',true);result.success(true);}catch(e){console.error(TAG,`activate

error:${JSON.stringify(e)}`);result.error('SPEECH_ACTIVATION_ERROR',`Failed

activate

recognition:${JSON.stringify(e)}`,null);}

整个activate方法被try-catch包裹,任何异常都会被捕获并通过result.error返回给Dart层。

5.3

错误信息的序列化

注意异常对象e的序列化方式:

//

用JSON.stringify序列化错误对象console.error(TAG,`activate

error:${JSON.stringify(e)}`);

为什么用JSON.stringify而不是e.message?因为OpenHarmony的异常对象结构可能和标准的Error不同,JSON.stringify可以输出完整的错误信息,包括错误码和详细描述。

//

典型的错误对象结构{"code":1002003,"message":"Language

not

supported"}

5.4

降级方案

如果在线模式创建失败,可以尝试降级到离线模式(flutter_speech当前未实现,但这是一个好的改进方向):

//

降级方案示例privateasynccreateEngineWithFallback(language:string):Promise<boolean>{//

先尝试在线try{this.asrEngine=awaitspeechRecognizer.createEngine({language:language,online:1});console.info(TAG,'online

engine

created');returntrue;}catch(onlineErr){console.warn(TAG,`online

failed:${JSON.stringify(onlineErr)}`);}//

降级到离线try{this.asrEngine=awaitspeechRecognizer.createEngine({language:language,online:0});console.info(TAG,'offline

engine

(fallback)');returntrue;}catch(offlineErr){console.error(TAG,`offline

also

failed:${JSON.stringify(offlineErr)}`);returnfalse;}}

5.5

重复创建的处理

如果用户多次调用activate,需要先销毁旧引擎再创建新的:

//

当前flutter_speech没有显式处理这种情况//

建议改进:privateasyncactivate(locale:string,result:MethodResult):Promise<void>{//

如果已有引擎,先销毁if(this.asrEngine){console.info(TAG,'destroying

existing

one');this.destroyEngine();}//

创建新引擎...}

🤦实际踩坑:我测试时连续调用了两次activate,第二次创建引擎时偶尔会失败。

后来加了先销毁旧引擎的逻辑就好了。

虽然Core

Speech

Kit理论上应该能处理这种情况,但保险起见还是自己管理好引擎的生命周期。

六、activate

流程图

activate(locale,

result)

error('SPEECH_CONTEXT_ERROR')

return

error('SPEECH_PERMISSION_DENIED')

return

error('ERROR_NO_SPEECH_RECOGNITION_AVAILABLE')

return

error('ERROR_LANGUAGE_NOT_SUPPORTED')

return

error('SPEECH_ACTIVATION_ERROR')

return

channel.invokeMethod('speech.onSpeechAvailability',

true)

result.success(true)

6.2

完整源码(带注释)

privateasyncactivate(locale:string,result:MethodResult):Promise<void>{try{console.info(TAG,`activate

called

locale:${locale}`);//

==========

第1步:权限申请

==========if(this.abilityContext){console.info(TAG,`requesting

microphone

permission...`);constatManager=abilityAccessCtrl.createAtManager();constgrantResult=awaitatManager.requestPermissionsFromUser(this.abilityContext,['ohos.permission.MICROPHONE']);constallGranted=grantResult.authResults.every((status:number)=>status===abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED);console.info(TAG,`permission

granted:${allGranted}`);if(!allGranted){result.error('SPEECH_PERMISSION_DENIED','Microphone

permission

denied',null);return;}}else{console.error(TAG,`abilityContext

null`);result.error('SPEECH_CONTEXT_ERROR','UIAbilityContext

not

available',null);return;}//

==========

第2步:能力检测

==========if(!canIUse('SystemCapability.AI.SpeechRecognizer')){result.error('ERROR_NO_SPEECH_RECOGNITION_AVAILABLE','Device

does

recognition',null);return;}//

==========

第3步:语言校验

==========constlanguage=this.convertLocale(locale);if(!this.isSupportedLocale(language)){result.error('ERROR_LANGUAGE_NOT_SUPPORTED',`Language

"${locale}"

not

HarmonyOS.`,null);return;}//

==========

第4步:创建引擎

==========console.info(TAG,`creating

engine

language:${language}`);this.asrEngine=awaitspeechRecognizer.createEngine({language:language,online:1});console.info(TAG,`engine

created

successfully`);//

==========

第5步:设置监听器

==========this.setupListener();//

==========

==========this.channel?.invokeMethod('speech.onSpeechAvailability',true);result.success(true);}catch(e){console.error(TAG,`activate

error:${JSON.stringify(e)}`);result.error('SPEECH_ACTIVATION_ERROR',`Failed

activate

recognition:${JSON.stringify(e)}`,null);}}

6.3

各步骤的耗时分析

步骤预估耗时是否异步说明
权限申请0-5秒

await

取决于用户操作速度
能力检测<1ms

同步

系统调用,极快
语言校验<1ms

同步

字符串比较
引擎创建500ms-3秒

await

取决于网络和系统状态
设置监听器<1ms

同步

注册回调
通知Dart<1ms

异步发送

不等待结果

📌整个activate方法的总耗时:最快约500ms(权限已授予+引擎快速创建),最慢可能超过5秒(首次权限弹窗+网络慢)。

Dart层应该在调用activate时显示loading状态。

七、引擎创建成功后的操作

7.1

setupListener

引擎创建成功后,立即设置监听器:

this.setupListener();

这一步在下一篇(第13篇)会详细讲解。

简单来说就是注册onStartonResultonCompleteonError四个回调。

7.2

通知Dart层

this.channel?.invokeMethod('speech.onSpeechAvailability',true);

这行代码通过MethodChannel向Dart层发送一个事件,告诉Dart层"语音识别引擎已就绪"。

Dart层收到后会调用availabilityHandler(true)回调。

7.3

返回结果

result.success(true);

最后通过result.success(true)告诉Dart层activate方法执行成功。

Dart层的Future会以true完成。

💡注意区分两种通知result.success(true)是对activate方法调用的直接响应(同步语义),channel.invokeMethod('speech.onSpeechAvailability',

true)是一个异步事件通知。

两者都需要,因为Dart层可能分别监听方法返回值和事件回调。

八、与Android引擎创建的对比

8.1

代码对比

Android

privatevoidactivate(Stringlocale,MethodChannel.Resultresult){//

同步创建speechRecognizer=SpeechRecognizer.createSpeechRecognizer(activity);speechRecognizer.setRecognitionListener(recognitionListener);//

检查是否可用if(SpeechRecognizer.isRecognitionAvailable(activity)){channel.invokeMethod("speech.onSpeechAvailability",true);result.success(true);}else{result.success(false);}}

OpenHarmony

privateasyncactivate(locale:string,result:MethodResult):Promise<void>{//

异步创建this.asrEngine=awaitspeechRecognizer.createEngine({language:language,online:1});this.setupListener();this.channel?.invokeMethod('speech.onSpeechAvailability',true);result.success(true);}

8.2

关键差异

差异点AndroidOpenHarmony
创建方式同步异步(await)
语言参数不在创建时指定创建时指定
在线/离线不在创建时指定创建时指定
能力检测isRecognitionAvailable()canIUse()
权限申请分离在另一个方法集成在activate中

🎯OpenHarmony的设计更"前置":语言和模式在创建引擎时就确定了,而Android是在startListening时通过Intent指定。

这意味着OpenHarmony如果要切换语言,需要重新创建引擎。

总结

本文详细讲解了flutter_speech中语音识别引擎的创建过程:

  1. createEngine参数:language(BCP

    47格式)和online(1=在线,0=离线)

  2. locale转换convertLocale将下划线格式转为连字符格式
  3. 能力检测canIUse('SystemCapability.AI.SpeechRecognizer')
  4. 异步创建:必须用await等待引擎创建完成
  5. 异常处理:try-catch捕获所有异常,通过result.error返回
  6. 创建后操作:setupListener

    +

    返回成功

下一篇我们深入语音识别监听器的实现——setupListener方法中四个回调的详细解析。

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

/>

相关资源:

  • Core

    Speech

    createEngine文档

  • canIUse系统能力检测
  • Android

    SpeechRecognizer.createSpeechRecognizer

  • flutter_speech

    OpenHarmony源码

  • OpenHarmony

    AI能力概述

  • 开源鸿蒙跨平台社区
  • Flutter-OHOS适配指南



SEO优化服务概述

作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。

百度官方合作伙伴 白帽SEO技术 数据驱动优化 效果长期稳定

SEO优化核心服务

网站技术SEO

  • 网站结构优化 - 提升网站爬虫可访问性
  • 页面速度优化 - 缩短加载时间,提高用户体验
  • 移动端适配 - 确保移动设备友好性
  • HTTPS安全协议 - 提升网站安全性与信任度
  • 结构化数据标记 - 增强搜索结果显示效果

内容优化服务

  • 关键词研究与布局 - 精准定位目标关键词
  • 高质量内容创作 - 原创、专业、有价值的内容
  • Meta标签优化 - 提升点击率和相关性
  • 内容更新策略 - 保持网站内容新鲜度
  • 多媒体内容优化 - 图片、视频SEO优化

外链建设策略

  • 高质量外链获取 - 权威网站链接建设
  • 品牌提及监控 - 追踪品牌在线曝光
  • 行业目录提交 - 提升网站基础权威
  • 社交媒体整合 - 增强内容传播力
  • 链接质量分析 - 避免低质量链接风险

SEO服务方案对比

服务项目 基础套餐 标准套餐 高级定制
关键词优化数量 10-20个核心词 30-50个核心词+长尾词 80-150个全方位覆盖
内容优化 基础页面优化 全站内容优化+每月5篇原创 个性化内容策略+每月15篇原创
技术SEO 基本技术检查 全面技术优化+移动适配 深度技术重构+性能优化
外链建设 每月5-10条 每月20-30条高质量外链 每月50+条多渠道外链
数据报告 月度基础报告 双周详细报告+分析 每周深度报告+策略调整
效果保障 3-6个月见效 2-4个月见效 1-3个月快速见效

SEO优化实施流程

我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:

1

网站诊断分析

全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。

2

关键词策略制定

基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。

3

技术优化实施

解决网站技术问题,优化网站结构,提升页面速度和移动端体验。

4

内容优化建设

创作高质量原创内容,优化现有页面,建立内容更新机制。

5

外链建设推广

获取高质量外部链接,建立品牌在线影响力,提升网站权威度。

6

数据监控调整

持续监控排名、流量和转化数据,根据效果调整优化策略。

SEO优化常见问题

SEO优化一般需要多长时间才能看到效果?
SEO是一个渐进的过程,通常需要3-6个月才能看到明显效果。具体时间取决于网站现状、竞争程度和优化强度。我们的标准套餐一般在2-4个月内开始显现效果,高级定制方案可能在1-3个月内就能看到初步成果。
你们使用白帽SEO技术还是黑帽技术?
我们始终坚持使用白帽SEO技术,遵循搜索引擎的官方指南。我们的优化策略注重长期效果和可持续性,绝不使用任何可能导致网站被惩罚的违规手段。作为百度官方合作伙伴,我们承诺提供安全、合规的SEO服务。
SEO优化后效果能持续多久?
通过我们的白帽SEO策略获得的排名和流量具有长期稳定性。一旦网站达到理想排名,只需适当的维护和更新,效果可以持续数年。我们提供优化后维护服务,确保您的网站长期保持竞争优势。
你们提供SEO优化效果保障吗?
我们提供基于数据的SEO效果承诺。根据服务套餐不同,我们承诺在约定时间内将核心关键词优化到指定排名位置,或实现约定的自然流量增长目标。所有承诺都会在服务合同中明确约定,并提供详细的KPI衡量标准。

SEO优化效果数据

基于我们服务的客户数据统计,平均优化效果如下:

+85%
自然搜索流量提升
+120%
关键词排名数量
+60%
网站转化率提升
3-6月
平均见效周期

行业案例 - 制造业

  • 优化前:日均自然流量120,核心词无排名
  • 优化6个月后:日均自然流量950,15个核心词首页排名
  • 效果提升:流量增长692%,询盘量增加320%

行业案例 - 电商

  • 优化前:月均自然订单50单,转化率1.2%
  • 优化4个月后:月均自然订单210单,转化率2.8%
  • 效果提升:订单增长320%,转化率提升133%

行业案例 - 教育

  • 优化前:月均咨询量35个,主要依赖付费广告
  • 优化5个月后:月均咨询量180个,自然流量占比65%
  • 效果提升:咨询量增长414%,营销成本降低57%

为什么选择我们的SEO服务

专业团队

  • 10年以上SEO经验专家带队
  • 百度、Google认证工程师
  • 内容创作、技术开发、数据分析多领域团队
  • 持续培训保持技术领先

数据驱动

  • 自主研发SEO分析工具
  • 实时排名监控系统
  • 竞争对手深度分析
  • 效果可视化报告

透明合作

  • 清晰的服务内容和价格
  • 定期进展汇报和沟通
  • 效果数据实时可查
  • 灵活的合同条款

我们的SEO服务理念

我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。

提交需求或反馈

Demand feedback