HarmonyOS NEXT-语音服务-智能朗读

介绍

本案例展示了语音类AI能力中的朗读控件能力,模拟了在应用里,通过点击朗读听筒,跳转朗读控件播放面板并对文章进行朗读的场景。需要使用HiAI引擎框架中的@kit.SpeechKit.d.ts接口。

效果预览

工程目录

├─entry/src/main/ets                         // 代码区
│  ├─entryability
│  │  └─EntryAbility.ets       
│  ├─model
│  │  ├─Article.ets                          // 文章数据结构
│  └─pages
│     └─Index.ets                            // 主页界面
├─entry/src/main/resources                   // 应用资源目录
└─screenshots                                // 截图

实现思路

本案例模拟了在应用里,通过点击朗读听筒,跳转朗读控件播放面板并对文章进行朗读的场景。 业务使用时,需要先进行import导入speech kit: import { TextReader, TextReaderIcon, ReadStateCode } from '@kit.SpeechKit';

涉及接口

  • init(context: common.BaseContext, readParams: ReaderParam): Promise<void> 链接
  • start(readInfoList: ReadInfo[], articleId?: string): Promise<void> 链接
  • on(type: 'setArticle', callback: Callback<string>): void 链接
  • on(type: 'clickArticle' | 'clickAuthor' | 'clickNotification', callback: Callback<string>): void 链接
  • on(type: 'showPanel' | 'hidePanel', callback: Callback<void>): void 链接
  • on(type: 'stop' | 'release', callback: Callback<void>): void 链接
  • on(type: 'stateChange', callback: Callback<ReadState>): void 链接
  • on(type: 'requestMore', callback: Callback<void>): void 链接

涉及组件

调用验证结果接口,接收处理返回的结果。参考entry/src/main/ets/pages/index.ets.

相关权限

获取联网权限: ohos.permission.INTERNET

代码实现

EntryAbility.ets

import { hilog } from '@kit.PerformanceAnalysisKit';
import { AbilityConstant, Want, UIAbility } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
import { WindowManager } from '@kit.SpeechKit';

export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
  }

  onDestroy(): void {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    // Main window is created, set main page for this ability
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');

    WindowManager.setWindowStage(windowStage);

    windowStage.loadContent('pages/Index', (err, data) => {
      if (err.code) {
        hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
        return;
      }
      hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
    });
  }

  onWindowStageDestroy(): void {
    // Main window is destroyed, release UI related resources
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
  }

  onForeground(): void {
    // Ability has brought to foreground
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
  }

  onBackground(): void {
    // Ability has back to background
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
  }
}

Article.ets

export interface Article {
  id: string;
  author: string;
  cover: ResourceStr;
  source: string;
  title: string;
  content: string;
  date: string;
}

Index.ets

import { hilog } from '@kit.PerformanceAnalysisKit';
import { TextReader, TextReaderIcon, ReadStateCode } from '@kit.SpeechKit';

const TAG = 'AI_SPEECH_KIT_DEMO'

@Entry
@Component
struct Index {
  @State message: string = '';

  /**
   * 待加载的文章
   */
  @State readInfoList: TextReader.ReadInfo[] = [];
  @State selectedReadInfo: TextReader.ReadInfo = this.readInfoList[0];

  /**
   * 播放状态
   */
  @State readState: ReadStateCode = ReadStateCode.WAITING;

  /**
   * 用于显示当前页的按钮状态
   */
  @State isInit: boolean = false;
  @State isListening: boolean = false;

  async aboutToAppear(){
    /**
     * 加载数据
     */
    console.info('ReadStateCode', JSON.stringify(this.readState))
    let readInfoList: TextReader.ReadInfo[] = [{
      id: '001',
      title: {
        text:'水调歌头.明月几时有',
        isClickable:true
      },
      author:{
        text:'宋.苏轼',
        isClickable:true
      },
      date: {
        text:'2024/01/01',
        isClickable:false
      },
      bodyInfo: '明月几时有?把酒问青天。\n\n不知天上宫阙,今夕是何年。\n\n'
    }];
    this.readInfoList = readInfoList;
    this.selectedReadInfo = readInfoList[0];
    this.init();
  }

  /**
   * 初始化
   */
  async init() {
    const readerParam: TextReader.ReaderParam = {
      isVoiceBrandVisible: true,
      businessBrandInfo: {
        panelName: '小艺朗读',
        panelIcon: $r('app.media.startIcon')
      }
    }
    try{
      await TextReader.init(getContext(this), readerParam);
      this.isInit = true;
    } catch (err) {
      hilog.error(0x0001, TAG, 'init error: %{public}s', JSON.stringify(err))
    }
  }

  // 设置操作监听
  setActionListener() {
    TextReader.on('setArticle',  (id: string) => {});
    TextReader.on('clickArticle',  (id: string) => {});
    TextReader.on('clickAuthor',  (id: string) => {});
    TextReader.on('clickNotification',  (id: string) => { hilog.info(0x0001, TAG, `onClickNotification ${id}`) });
    TextReader.on('showPanel', () => { hilog.info(0x0001, TAG, `onShowPanel`) });
    TextReader.on('hidePanel', () => { hilog.info(0x0001, TAG, `onHidePanel`) });
    TextReader.on('stop', () => { hilog.info(0x0001, TAG, `onStop`) });
    TextReader.on('release', () => { hilog.info(0x0001, TAG, `onRelease`) });
    TextReader.on('stateChange', (state: TextReader.ReadState) => {
      hilog.info(0x1, TAG, `ReadState: %{public}s`, JSON.stringify(state));
      this.onStateChanged(state)
    });
    TextReader.on('requestMore', () => this.onStateChanged);
  }

  onStateChanged = (state: TextReader.ReadState) => {
    hilog.info(0x1, TAG, `selectedReadInfo.id: %{public}s`, this.selectedReadInfo?.id);
    if (this.selectedReadInfo?.id === state.id) {
      hilog.warn(0x1, TAG, `match, changeState to %{public}s`, JSON.stringify(state))
      this.readState = state.state;
    } else {
      this.readState = ReadStateCode.WAITING;
    }
  }

  // 设置事件监听
  setEventListener(){
    TextReader.on('eventNotification',  (event: TextReader.NotificationEvent) => {
      hilog.info(0x0001, TAG, `Notification event: ${JSON.stringify(event)}`)
    })
    TextReader.on('eventPanel',  (event: TextReader.PanelEvent) => {
      hilog.info(0x0001, TAG, `Panel event: ${JSON.stringify(event)}`)
    })
    TextReader.on('eventReadList',  (event: Array<TextReader.ListEventState>) => {
      hilog.info(0x0001, TAG, `ReadList event: ${JSON.stringify(event)}`)
      TextReader.loadMore([], true);
    })
  }

  build() {
    Column() {
      TextReaderIcon({ readState: this.readState })
        .width(32)
        .height(32)
        .onClick(async () => {
          // 已经在播放,拉起播放面板
          if (this.readState === ReadStateCode.PLAYING) {
            TextReader.showPanel();
            return;
          }
          // 若未初始化,先初始化并启动
          try {
            this.setActionListener();
            this.setEventListener();
            await TextReader.start(this.readInfoList, this.selectedReadInfo?.id);
          } catch (err) {
            hilog.error(0x0001, TAG, 'init message: %{public}s', JSON.stringify(err))
          }
        })

      Text(this.readState === ReadStateCode.PLAYING? 'playing' : 'click icon to play').fontSize(10)
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
  }
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数智侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值