22. TextReader 朗读与语音交互

本章导读

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


在这里插入图片描述

22.1 TextReader 初始化

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

// EntryAbility.ets
import { TextReader } from '@kit.SpeechKit';
import { BusinessError } from '@ohos.base';

export default class EntryAbility extends UIAbility {
  async onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): Promise<void> {
    if (this.context) {
      const readerParams: TextReader.ReaderParam = {
        isVoiceBrandVisible: true,
        businessBrandInfo: {
          panelName: '小艺朗读',
          panelIcon: $r('app.media.startIcon')
        }
      };
      await TextReader.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}`);
      })
    }
  }
}

关键参数说明:

参数 类型 作用
isVoiceBrandVisible boolean 是否在朗读面板显示语音品牌标识
businessBrandInfo.panelName string 朗读面板标题,如"小艺朗读"
businessBrandInfo.panelIcon Resource 朗读面板图标资源

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


22.2 PoemReader 朗读工具类

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

// PoemReader.ets
import { TextReader } from "@kit.SpeechKit";
import { BusinessError } from "@kit.BasicServicesKit";

export class PoemReader {
  static play(poem: string, title: string = '', author: string = '', date?: string) {
    const readInfoList: TextReader.ReadInfo[] = [{
      id: '001',
      title: {
        text: title,
        isClickable: true
      },
      author: {
        text: author,
        isClickable: true
      },
      date: {
        text: date ?? new Date().toISOString().split('T')[0],
        isClickable: false
      },
      bodyInfo: poem
    }];

    const startParams: 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 数据结构:

interface ReadInfo {
  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
@Builder
buildBottom() {
  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.ets
Canvas(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.ets
Column({ 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.ets
import { AudioEntry, PlayActionCallback, PlayParams, SXPlayer } from '@qtfm/smartxplayer';

const context: common.UIAbilityContext = GlobalUIAbilityContext.getContext()

@Component
export struct TodoView {
  private callback: PlayActionCallback = {
    onPlayPrevious: () => {},
    onPlayNext: () => {},
    onToggleFavorite: (assetId) => {}
  }

  private sxplayer: SXPlayer = new SXPlayer(context, {
    enableLog: true,
    bundleName: "com.youtoo.study.partner",
    abilityName: "EntryAbility",
    playActionCallback: this.callback
  })
}

播放提醒音

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

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

PlayParams 参数说明:

参数 类型 说明
audioEntry AudioEntry[] 音频数据源,支持 fd 文件描述符
playWhenPrepared boolean 准备就绪后自动播放
hasPrevious boolean 是否有上一首
hasNext boolean 是否有下一首
isLive boolean 是否为直播流

smartxplayer 模块导出

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

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

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

选型原则:

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

本章小结

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

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐