当前位置: 首页 > news >正文

HarmonyOS《柚兔学伴》项目实战22-TextReader 朗读与语音交互

22. TextReader 朗读与语音交互

本章导读

语音交互是儿童教育类应用的核心能力之一。「柚兔学伴」中,诗词朗读、汉字发音、提醒音效等场景均通过 HarmonyOS SpeechKit 的 TextReader 与第三方 SXPlayer 两套方案实现。本章将详解它们的集成方式与实战用法。


22.1 TextReader 初始化

TextReader 是 HarmonyOS@kit.SpeechKit提供的系统级朗读控件,使用前必须在 UIAbility 的onCreate生命周期中完成初始化。

// EntryAbility.etsimport{TextReader}from'@kit.SpeechKit';import{BusinessError}from'@ohos.base';exportdefaultclassEntryAbilityextendsUIAbility{asynconCreate(want:Want,launchParam:AbilityConstant.LaunchParam):Promise<void>{if(this.context){constreaderParams:TextReader.ReaderParam={isVoiceBrandVisible:true,businessBrandInfo:{panelName:'小艺朗读',panelIcon:$r('app.media.startIcon')}};awaitTextReader.init(this.context,readerParams).then(()=>{console.info(`TextReader succeeded in initializing.`);}).catch((e:BusinessError)=>{console.error(`TextReader failed to initialize. Code:${e.code}, message:${e.message}`);})}}}

关键参数说明:

参数类型作用
isVoiceBrandVisibleboolean是否在朗读面板显示语音品牌标识
businessBrandInfo.panelNamestring朗读面板标题,如"小艺朗读"
businessBrandInfo.panelIconResource朗读面板图标资源

初始化必须在onCreate中完成,不能延迟到页面加载阶段,否则后续TextReader.start()调用会失败。


22.2 PoemReader 朗读工具类

为方便多处复用,项目将 TextReader 的调用封装为静态工具类PoemReader

// PoemReader.etsimport{TextReader}from"@kit.SpeechKit";import{BusinessError}from"@kit.BasicServicesKit";exportclassPoemReader{staticplay(poem:string,title:string='',author:string='',date?:string){constreadInfoList:TextReader.ReadInfo[]=[{id:'001',title:{text:title,isClickable:true},author:{text:author,isClickable:true},date:{text:date??newDate().toISOString().split('T')[0],isClickable:false},bodyInfo:poem}];conststartParams:TextReader.StartParams={isMinibarHidden:true,callbackParam:'0'};TextReader.start(readInfoList,undefined,startParams).then(()=>{console.info(`TextReader succeeded in starting`);}).catch((e:BusinessError)=>{console.error(`TextReader failed to start. Code:${e.code}, message:${e.message}`);});}}

ReadInfo 数据结构:

interfaceReadInfo{id:string;// 朗读内容唯一标识title:{text:string;isClickable:boolean};// 标题,可点击跳转author:{text:string;isClickable:boolean};// 作者,可点击跳转date:{text:string;isClickable:boolean};// 日期,不可点击bodyInfo:string;// 朗读正文内容}

StartParams 参数:

参数说明
isMinibarHidden是否隐藏迷你朗读条(true 则全屏朗读面板)
callbackParam回调参数,用于标识本次朗读请求

设计要点:isClickable控制朗读面板中对应区域是否可交互。对于诗词场景,标题和作者可点击查看详情,日期设为不可点击。


22.3 三大使用场景

场景一:PoemPage 诗词播读

在诗词详情页,点击"播读"按钮调用朗读:

// PoemPage.ets@BuilderbuildBottom(){Row(){Button('播读').layoutWeight(1).borderRadius(5).linearGradient({angle:90,colors:[[0xFF33FF,0.0],[0x8E44FF,1]]}).onClick(()=>{PoemReader.play(this.poemInfo?.poem??'');})Blank(10)Button('下一首').layoutWeight(1).borderRadius(5).linearGradient({angle:90,colors:[[0x8E44FF,0.0],[0x1C55FF,1]]}).onClick(()=>{this.generatePoem()})}.width('100%').padding(10)}

此处只传入诗词正文,标题、作者使用默认空值。朗读面板会以全屏模式展示。

场景二:StrokeView 汉字发音

在笔画查询页面,点击 Canvas 区域即可听到当前汉字的读音:

// StrokeView.etsCanvas(this.context!!).width(100).height(100).onReady(()=>{this.canvasReady=true;if(!this.isLoading){this.initializeCanvas();this.strokeManager.startAnimation(this.context!!,()=>{this.updateAnimationInfo();});}}).onClick(()=>{PoemReader.play(this.word);})

this.word是单个汉字(如"样"),TextReader 会自动识别并朗读该字的发音,非常适合儿童识字场景。

场景三:TodoView 诗词卡片朗读

在首页待办视图中,点击诗词卡片触发朗读:

// TodoView.etsColumn({space:12}){Text(this.poem).fontFamily('kaiti').fontWeight(FontWeight.Bold).textAlign(TextAlign.Center).lineSpacing(LengthMetrics.fp(18))}.margin({left:12}).justifyContent(FlexAlign.Center).mainCardStyle().onClick(()=>{PoemReader.play(this.poem);})

诗词内容来自每日推荐,用户轻触即可聆听朗读,实现"看诗即听"的沉浸体验。


22.4 SXPlayer 自定义音频播放

对于非朗读类的音频需求(如计时结束提醒音),项目使用@qtfm/smartxplayer模块的 SXPlayer:

初始化与回调

// TodoView.etsimport{AudioEntry,PlayActionCallback,PlayParams,SXPlayer}from'@qtfm/smartxplayer';constcontext:common.UIAbilityContext=GlobalUIAbilityContext.getContext()@Componentexportstruct TodoView{privatecallback:PlayActionCallback={onPlayPrevious:()=>{},onPlayNext:()=>{},onToggleFavorite:(assetId)=>{}}privatesxplayer:SXPlayer=newSXPlayer(context,{enableLog:true,bundleName:"com.youtoo.study.partner",abilityName:"EntryAbility",playActionCallback:this.callback})}

播放提醒音

倒计时结束时,读取 rawfile 中的铃声文件并播放:

onTimerFinished=async()=>{this.alarmVisible=trueletfileDescriptor=awaitcontext.resourceManager.getRawFd("ringtone_youtoo.mp3");letentity:AudioEntry={fd:fileDescriptor}letparams:PlayParams={audioEntry:[entity],playWhenPrepared:true,hasPrevious:false,hasNext:false,isLive:false}this.sxplayer!.play(params)}

PlayParams 参数说明:

参数类型说明
audioEntryAudioEntry[]音频数据源,支持 fd 文件描述符
playWhenPreparedboolean准备就绪后自动播放
hasPreviousboolean是否有上一首
hasNextboolean是否有下一首
isLiveboolean是否为直播流

smartxplayer 模块导出

export{SXPlayer,SXWorkerPlayer,SXBaseAudioPlayer,SXCastPlayer,ISXAudioPlayer}
  • SXPlayer:标准播放器,适合短音频播放
  • SXWorkerPlayer:Worker 线程播放器,避免阻塞 UI
  • SXBaseAudioPlayer:基础播放器抽象类
  • SXCastPlayer:投播播放器
  • ISXAudioPlayer:播放器接口定义

22.5 两套方案对比与选型建议

对比维度TextReaderSXPlayer
适用场景文本朗读(诗词、汉字)音频文件播放(铃声、音乐)
输入类型文本字符串文件描述符(fd)
系统依赖SpeechKit第三方模块
朗读面板内置 UI 面板无 UI,纯后台播放
个性化支持品牌信息定制支持播放控制回调

选型原则:

  • 需要系统级朗读 UI + 文本转语音 → TextReader
  • 需要播放预置音频文件 + 自定义控制逻辑 → SXPlayer
  • 两者可共存,互不冲突

本章小结

本章介绍了「柚兔学伴」中语音交互的完整实现方案。TextReader 在 EntryAbility.onCreate 中初始化,通过 PoemReader 工具类在诗词页、笔画页、首页卡片三处统一调用;SXPlayer 则负责计时提醒等纯音频播放场景。两者各司其职,共同构建了应用的语音交互体系。下一章将介绍字帖生成与 PDF 导出功能。

http://www.jsqmd.com/news/1254303/

相关文章:

  • Kubernetes核心架构与生产环境实战指南
  • InfiniBand协议深度解析:RDMA的原生网络架构
  • 2026九江黄金回收实测:6家正规实体店行情与避坑攻略 - 观金堂黄金回收
  • MongoDB 4.x——合理使用索引(二)
  • Claude三大模型代码能力对比:Opus、Sonnet、Haiku实战评测
  • 大家能否帮我填一填问卷.....感谢
  • RAG还在用基础版?句子滑动窗口·自动合并·索引·融合·CRAG·Self-RAG全讲透(附代码)
  • 索尼2028年停售实体光盘,光盘时代落幕,“一切在线”可靠吗?
  • 制造业AI转型:智能排产与质量预测的工业实践
  • 江诗丹顿武汉2026年7月最新售后网点地址及服务热线信息 - 江诗丹顿服务中心
  • 智能优化算法与深度学习在轴承故障诊断中的应用
  • 库早报|10亿元转让控股权,这家3D打印上市公司将易主;形朗科技年收入16.9亿元;煜鼎增材IPO获受理王华明退出董事会
  • FTL闪存转换层深度解析:SSD如何在“看不见的地方“完成地址翻译?
  • 还在担心样本的安全吗?如何制定有效的温湿度异常应急预案?
  • AM5718 PRU-ICSS手动IO时序配置:从原理到实战避坑指南
  • LLM 应用怎么省 Token、加速响应——阿里云 Tair 语义缓存实战
  • AI大模型技术架构实战:核心分层与优化策略
  • TI ADS8353/7853 ADC评估套件深度解析:从硬件配置到软件实操全指南
  • Llama3大模型在关系抽取中的实践与优化
  • 大模型商业化落地的核心挑战与实战策略
  • 为什么要把测试重新放回代码平台:Gitee测试体系的能力边界与落地方式
  • 浪琴保养价格查询|维修地址与客服热线权威信息公告(2026年7月最新) - 浪琴官方售后服务中心
  • 谷歌Gemini 3.6 Flash发布即遭群嘲,算力调走、财报压力成主因?
  • WhatsApp 发送频率控制的令牌桶算法实现
  • 【课程设计/毕业设计】基于Django的学生教材申领审核管理系统设计与实现 基于 Web 的高校教材教务管理系统【附源码、数据库、万字文档】
  • 磨损均衡算法(Wear Leveling)——SSD如何让每块闪存“公平退休“?
  • 近期在杭州出手旧金合适吗?盘点2026主流回收渠道,紧贴大盘价门店清单汇总 - 资讯洞察员
  • Langflow 系列 | 第 4 篇:实战案例:构建一个最小可用的 RAG Flow
  • 智能体交互体验升级:从工具到伙伴的六大维度重构
  • DP83826以太网PHY深度解析:扩展寄存器操作与100BASE-TX物理层调试