OpenHarmony 英语学习 App 实战:TTS、端侧 AI 与元服务能力集成思路

摘要

AI 不应该只是学习 App 里的一个“智能问答按钮”。在真实学习流程中,AI 更适合被拆进每个关键环节:单词读音、语境讲解、错题分析、难度调整、作文批改、学习报告和口语陪练。🤖📖

本文以我的 OpenHarmony/HarmonyOS 英语学习项目「英语视界 YingYu」为例,分享当前项目中已经实现的 TTS 语音朗读能力,以及后端预留的 AI Agent 接口设计。同时,也会讨论后续如何扩展端侧 AI、人脸识别开放能力和元服务能力。

需要说明的是:当前项目已经具备 TTS 和 AI 接口预留,人脸识别与元服务属于后续集成思路,本文不会把未完成能力写成已上线功能。

一、项目中的 AI 能力应该服务哪些学习场景?

「英语视界」是一个面向中小学生的英语学习 App,核心功能包括:

  • 词汇学习;
  • 听力训练;
  • 每日一句;
  • 语法专题;
  • 短语学习;
  • 趣味英语;
  • 自定义生词本;
  • 艾宾浩斯复习;
  • 学习成就系统。

这些功能背后有很多适合 AI 介入的点:

学习场景 AI 能力
不会读单词 TTS 标准发音
不理解单词 AI 语境讲解
做错语法题 AI 错因分析
题目太简单/太难 自适应难度
写作文 AI 作文批改
学习坚持困难 AI 学习陪伴
复习效率低 端侧复习计划

因此我更倾向于把 AI 做成“学习流程增强器”,而不是一个单独页面。

二、已实现能力:TTS 英语听力朗读

项目中已经有 ListeningTtsHelper.ets,用于听力材料和英文文本朗读。它基于 @kit.CoreSpeechKittextToSpeech 能力实现。

import { textToSpeech } from '@kit.CoreSpeechKit'
import { BusinessError } from '@kit.BasicServicesKit'

创建引擎时,优先使用在线引擎:

const initParams: textToSpeech.CreateEngineParams = {
  language: 'en-US',
  person: 0,
  online: 1,
  extraParams: {
    'style': 'interaction-broadcast',
    'locate': 'US',
    'name': 'ListeningTts'
  }
}

textToSpeech.createEngine(initParams, (err: BusinessError, engine: textToSpeech.TextToSpeechEngine) => {
  if (err) {
    console.error(`[ListeningTts] createEngine(online) failed: ${err.code} ${err.message}`)
    this.createEngineOffline(callback)
    return
  }

  this.ttsEngine = engine
  this.attachListener()
  onReady()
})

这个设计比较实用:在线引擎效果通常更好,但如果失败,可以降级到离线引擎,保证学习流程不中断。

三、离线兜底:弱网环境下也能学习

在线引擎失败时,项目会尝试创建离线引擎:

private createEngineOffline(
  callback: (err: BusinessError, engine: textToSpeech.TextToSpeechEngine) => void
): void {
  const initParams: textToSpeech.CreateEngineParams = {
    language: 'en-US',
    person: 0,
    online: 0,
    extraParams: {
      'style': 'interaction-broadcast',
      'locate': 'US',
      'name': 'ListeningTts'
    }
  }

  textToSpeech.createEngine(initParams, (err, engine) => {
    callback(err, engine)
  })
}

对学习 App 来说,离线兜底非常重要。因为用户可能在地铁、学校、宿舍等网络环境不稳定的地方学习,如果语音朗读完全依赖网络,就会影响连续性。

四、播放监听:让 UI 状态可控

创建 TTS 引擎后,需要监听播放状态:

private attachListener(): void {
  if (!this.ttsEngine) return

  this.ttsEngine.setListener({
    onStart: (_rid, _resp) => {
      console.info('[ListeningTts] onStart')
      this.clearSafetyTimer()
      this.startSafetyTimer(() => {
        this.safeStop()
        this.invokeEnd()
      })
    },
    onComplete: (_rid, _resp) => {
      console.info('[ListeningTts] onComplete')
      this.invokeEnd()
    },
    onStop: (_rid, _resp) => {
      console.info('[ListeningTts] onStop')
      this.invokeEnd()
    },
    onError: (_rid, code: number, msg: string) => {
      console.error(`[ListeningTts] onError code=${code} msg=${msg}`)
      this.invokeError()
    }
  })
}

这样页面就可以根据播放状态切换按钮:

  • 播放中;
  • 已完成;
  • 播放失败;
  • 用户主动停止。

学习类产品要特别注意这种状态控制,否则用户可能不知道当前到底是在加载、播放还是失败。

五、安全定时器:避免静默失败

语音播放中最难受的问题是:用户点击播放后没有声音,但按钮一直处于播放状态。为了解决这个问题,项目加入了安全定时器。

private startSafetyTimer(onTimeout: () => void): void {
  this.clearSafetyTimer()

  this.safetyTimerId = setTimeout(() => {
    this.safetyTimerId = -1
    console.error('[ListeningTts] safety timer fired, triggering timeout')
    onTimeout()
  }, this.SAFETY_TIMEOUT_MS) as number
}

如果超过指定时间还没有正常完成,就主动触发兜底逻辑:

this.startSafetyTimer(() => {
  console.warn('[ListeningTts] safety timeout after onStart, stopping')
  this.safeStop()
  this.invokeEnd()
})

这类细节虽然不起眼,但非常影响体验。特别是听力练习,如果播放状态不可靠,用户会对整个功能失去信心。

六、朗读参数:适配英语学习场景

项目在朗读时设置了语速、音量、音高和语言上下文:

const params: textToSpeech.SpeakParams = {
  requestId: `s_${Date.now()}`,
  extraParams: {
    'queueMode': 0,
    'speed': 0.92,
    'volume': 1,
    'pitch': 1,
    'languageContext': 'en-US',
    'soundChannel': 0,
    'playType': 0
  }
}

this.ttsEngine.speak(text, params)

这里把语速设置为 0.92,比正常语速稍慢一点,更适合学生跟读和听力训练。后续还可以做成用户可配置项:

  • 慢速;
  • 标准;
  • 快速;
  • 美音/英音;
  • 单句循环;
  • 跟读模式。

七、后端 AI Agent 接口预留

除了端侧 TTS,项目后端也预留了 AI Agent 路由,集中在 web/backend/src/routes/ai.ts

单词讲解接口:

router.post('/explain-word', authenticate, asyncHandler(async (req, res) => {
  const { word, context } = req.body

  if (!word) {
    return res.status(400).json({
      success: false,
      error: { message: 'Word is required' }
    })
  }

  const explanation = await explainWord(word, context)
  res.json({
    success: true,
    data: { explanation }
  })
}))

自适应难度接口:

router.post('/adaptive-difficulty', authenticate, asyncHandler(async (req, res) => {
  const { recentResults } = req.body

  if (!recentResults || !Array.isArray(recentResults)) {
    return res.status(400).json({
      success: false,
      error: { message: 'Recent results array is required' }
    })
  }

  const difficulty = await getAdaptiveDifficulty(recentResults)
  res.json({
    success: true,
    data: { difficulty }
  })
}))

这些接口虽然目前部分仍是预留或占位,但架构已经把 AI 能力拆成多个学习服务,而不是写成一个泛化接口。

八、单词讲解:从查词典升级为讲语境

wordExplainer.ts 中定义了单词讲解返回结构:

interface WordExplanation {
  word: string
  phonetic?: string
  definition: string
  partOfSpeech: string
  usage: string
  tips: string
  synonyms?: string[]
  antonyms?: string[]
  examples: Array<{
    sentence: string
    translation: string
  }>
  collocations: string[]
  level: string
}

这个结构比普通词典更适合学习,因为它不仅有释义,还包括:

  • 使用场景;
  • 记忆技巧;
  • 近义词;
  • 反义词;
  • 例句;
  • 常见搭配;
  • CEFR 等级。

后续接入真实 AI 服务后,就可以根据用户年级和上下文生成更适合学生理解的解释。

九、自适应难度:端侧规则算法先打底

AI 不一定所有地方都要依赖大模型。项目中的 adaptiveDifficulty.ts 就使用了规则算法,根据最近答题正确率和响应时间调整难度。

const recent = recentResults.slice(-10)
const correctCount = recent.filter(r => r.correct).length
const accuracy = correctCount / recent.length

const avgResponseTime =
  recent.reduce((sum, r) => sum + r.responseTime, 0) / recent.length

const avgDifficulty =
  recent.reduce((sum, r) => sum + r.difficulty, 0) / recent.length

难度调整逻辑:

if (accuracy >= 0.9 && avgResponseTime < 3000) {
  newLevel = Math.min(5, Math.round(avgDifficulty) + 1)
  recommendations.push('表现优秀,建议挑战更高难度')
} else if (accuracy >= 0.8) {
  newLevel = Math.round(avgDifficulty)
  recommendations.push('继续保持当前节奏')
} else if (accuracy < 0.6) {
  newLevel = Math.max(1, Math.round(avgDifficulty) - 1)
  recommendations.push('建议回到基础题目重新学习')
}

这种方案很适合端侧 AI 思路:

  • 本地快速判断;
  • 不依赖网络;
  • 成本低;
  • 隐私友好;
  • 可以和云端 AI 结合生成解释。

十、推荐 AI 架构:端侧轻判断 + 云端深分析

结合当前项目,后续 AI 架构可以这样演进:

ArkUI 页面
  -> AppStorage / Preferences 保存学习状态
  -> 本地算法生成复习计划和难度建议
  -> TTS 提供听力朗读和跟读反馈
  -> 后端 AI 提供单词讲解、错题分析、作文批改
  -> 学习报告汇总用户表现和下一步建议

端侧适合做:

  • 学习进度统计;
  • 今日任务生成;
  • 艾宾浩斯复习计划;
  • 自适应难度初判;
  • TTS 播放控制;
  • 离线学习状态维护。

云端或大模型适合做:

  • 复杂语义解释;
  • 错因分析;
  • 作文批改;
  • 口语对话;
  • 学习报告;
  • 个性化建议生成。

这样可以兼顾体验、成本和隐私。

十一、人脸识别开放能力的集成思路

当前项目没有接入人脸识别,因此不能把它写成已完成功能。但从教育产品角度看,人脸识别可以作为“可选能力”用于低侵入场景:

  • 学生模式和家长模式快速切换;
  • 学习打卡时确认本人;
  • 多学生共用平板时识别学习档案;
  • 家长授权进入高级设置。

不过,人脸能力必须非常谨慎:

  • 不默认开启;
  • 不保存原始人脸图像;
  • 提供账号密码等替代方案;
  • 明确展示用途;
  • 未成年人场景需要监护人授权;
  • 设置页提供关闭和删除入口。

我的建议是:人脸识别不应该被设计成“学习功能本身”,而应该作为身份确认或模式切换的辅助能力。

十二、元服务能力:把学习入口做轻

英语学习任务通常很碎片化,非常适合元服务或轻量入口:

  • 今日 10 个单词;
  • 1 条每日一句;
  • 3 分钟听力;
  • 5 个待复习词;
  • 一键查看学习报告;
  • 快速打卡。

结合当前项目,可以拆出以下轻入口:

元服务方向 对应页面
今日任务 DailyTask
复习卡片 ReviewCenter
每日一句 DailySentence
听力训练 ListeningContent
学习报告 ShareCenter

元服务的价值在于:用户不一定每次都要完整打开 App,也能完成一次小学习任务。对于英语学习这种高频低时长场景,非常适合。

十三、AI 能力落地路线图

结合项目现状,我会按下面路线推进:

第一阶段:稳定已有能力

  • 优化 TTS 播放体验;
  • 增加语速设置;
  • 增加单词朗读;
  • 增加听力循环播放;
  • 完善播放失败兜底。

第二阶段:接入文本 AI

  • 单词语境讲解;
  • 错题原因分析;
  • 语法知识点解释;
  • 学习报告生成;
  • 作文批改。

第三阶段:端侧智能化

  • 本地学习画像;
  • 本地复习计划;
  • 本地难度调整;
  • 离线可用的学习建议;
  • 更细粒度的学习统计。

第四阶段:系统级入口

  • 元服务每日任务;
  • 实况窗学习进度;
  • 近场分享学习成果;
  • 多设备续学;
  • 可选人脸身份确认。

这条路线不会一上来就堆满 AI 功能,而是从学习流程中最刚需的点开始逐步增强。

十四、实现时的注意事项

1. AI 输出要适合学生年龄

同一个单词,对小学生和高中生的解释方式应该不同。后续接入 AI 时,要把年级、难度和上下文作为参数。

2. TTS 要考虑失败和弱网

语音能力不能只处理成功路径。超时、失败、停止、重复点击都要有兜底。

3. 端侧能解决的不要都丢给云端

难度调整、复习计划、学习统计这类任务,本地算法完全可以先做一版,响应更快,也更省成本。

4. 人脸识别一定要可选

教育类应用不能为了“高级能力”牺牲隐私边界。身份识别能力必须谨慎、透明、可关闭。

5. 元服务要聚焦一个任务

元服务不是迷你版完整 App,而是一个明确任务入口。例如“复习 5 个单词”就比“打开学习中心”更有价值。

十五、小结

本文结合「英语视界 YingYu」项目,梳理了 OpenHarmony/HarmonyOS 英语学习 App 的 AI 能力设计:

  • 当前已实现 TTS 英文朗读;
  • TTS 引擎支持在线优先、离线兜底;
  • 播放流程加入监听和安全定时器;
  • 后端预留了单词讲解、错题分析、自适应难度等 AI 接口;
  • 自适应难度可以先用本地规则算法实现;
  • 推荐“端侧轻判断 + 云端深分析”的架构;
  • 人脸识别适合作为可选身份能力;
  • 元服务适合承载每日任务、复习卡片和每日一句。

AI 在教育场景里的价值,不是让 App 看起来更炫,而是让学习更连续、更个性化、更容易坚持。OpenHarmony/HarmonyOS 的端侧能力、分布式能力和系统级入口,正好可以把 AI 从一个按钮扩展成一套完整的学习陪伴系统。🌟

img

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐