更新记录
1.0.0(2026-09-03) 下载此版本
- 首个版本:Android TextToSpeech / iOS AVSpeechSynthesizer 双端支持(Native.js 纯 JS 实现,免原生插件与自定义基座)
- 朗读控制:播放/暂停/继续/停止;朗读中重复播放自动打断旧朗读
- 参数调节:语速、音高、音量(Android 播放中调参为估算断点续播)
- 失败处理:五类错误码分类上报;Android 引擎缺失一键跳系统 TTS 设置页
- iOS:静音键无声规避、中文语音检测与降级
- Android:引擎包名检测、中文语音数据缺失检测
平台兼容性
uni-app(3.8.3)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| - | - | - | - | √ | - | √ | √ | - |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| - | - | - | - | - | - | - | - | - | - | - | - |
Parrot 学舌鹦鹉 · 系统语音合成(TTS)模块(uni_modules 插件 zqj-parrot-tts)
Parrot = 「鹦鹉学舌」:让 App 复述你给它的文字。取名自 TTS 的本质——你说(写),它学(读)。
适用项目:uni-app 3.x(Vue 3)项目,HBuilderX ≥ 3.6,编译目标为 App(app-android / app-ios)。 环境限制:模块依赖 5+ Runtime(全局对象
plus),只能在 uni-app App 端真机/自定义基座上运行;H5、小程序端会返回降级实现(init()时上报UNSUPPORTED_PLATFORM);纯 Node / 浏览器环境无法运行(没有plus,也没有系统语音引擎),本文示例请在 uni-app App 端执行。 不适用于 uni-app x(uts 项目)。
一、这是什么
一段纯 JS 封装,让你的 App 不写一行原生代码、不装原生插件,就能调用手机系统自带的语音引擎把文字读出来:
| 平台 | 系统能力 | 调用方式 |
|---|---|---|
| Android | android.speech.tts.TextToSpeech |
Native.js(plus.android) |
| iOS | AVFoundation.AVSpeechSynthesizer |
Native.js(plus.ios) |
典型用途:播报通知、朗读文章、无障碍辅助、验证码语音提示等。两端都不需要任何系统权限(TTS 不涉及麦克风),标准基座(HBuilderX 直接「运行到手机」)即可调试。
模块内部已经处理好了这些脏活:
- 平台判断与双端分流(条件编译 +
platform二次判断); - Android 引擎初始化是异步回调、iOS 是同步——统一成
Promise; - Android 部分厂商引擎(如小米)忽略语速/音高参数——提供当前引擎包名查询与「打开系统 TTS 设置」引导;
- Android 没有暂停接口、拿不到播放进度——按「时长 × 语速」估算断点续播;
- iOS 静音键导致无声、中文语音(婷婷)未下载、部分基座
plus.ios.import()+invoke()链路失效——分别做了规避、检测引导与双路径调用兜底。
二、快速开始
引入路径(注意是文件夹 + index):
import { createSystemTts } from '@/uni_modules/zqj-parrot-tts/js_sdk/index'
// 1. 创建实例(一个页面创建一个即可)
const tts = createSystemTts((state, err) => {
// 所有失败都不抛异常,统一从这里拿到原因
if (err) {
// err.code: UNSUPPORTED_PLATFORM / NOT_READY / INIT_FAILED / VOICE_MISSING / PLAY_FAILED
uni.showModal({ title: '语音不可用', content: err.message, showCancel: false })
}
console.log('引擎状态:', state) // init → ready → speaking ⇄ paused;异常为 error
})
// 2. 初始化(进入页面时调用一次;Android 是异步回调,必须 await)
onMounted(async () => {
const pick = await tts.init()
if (!pick.voiceFound) {
// iOS:系统没装经典中文语音(新机型常见)
// 引导用户:设置 > 辅助功能 > 朗读内容 > 声音 > 中文(中国)> 下载「婷婷」
// 下载完成后调用 await tts.init() 重新初始化即可,无需重启应用
}
})
// 3. 朗读
function play() {
tts.speak('你好,这是系统语音引擎朗读的文本', {
rate: 1.0, // 语速倍率,1.0 正常(0.5~2)
pitch: 1.0, // 音高,1.0 正常(0.5~2)
volume: 1.0, // 相对媒体音量 0~1,1.0 跟随系统媒体音量
})
}
// 4. 控制
// tts.pause() / tts.resume() / tts.stop()
// 5. 页面卸载时释放(Android 会 shutdown 引擎)
onUnmounted(() => tts.destroy())
核心参数(TtsSpeakOptions):
| 参数 | 类型 | 范围 | 说明 |
|---|---|---|---|
rate |
number | 0.5~2(建议) | 语速倍率,1.0 = 正常。iOS 端内部映射为 AVSpeechUtterance.rate = 0.5 × rate |
pitch |
number,默认 1 | 0.5~2 | 音高。Android setPitch / iOS pitchMultiplier |
volume |
number,默认 1 | 0~1 | 相对媒体音量的缩放。Android 经 KEY_PARAM_VOLUME 播放参数下发;iOS setVolume: |
三个参数都只对下一次 speak() 生效;Android 端播放中调参可改用 changeParamsLive() 立即生效(估算断点续播)。
三、API 参考
createSystemTts(onChange: TtsStateListener): SystemTts
唯一工厂函数。按运行平台返回对应实现(接口 SystemTts 约束),onChange 在状态变化和错误发生时被调用。所有方法不抛异常,失败一律经 onChange(state, err) 上报。
SystemTts 实例方法
| 方法 | 签名 | 返回 | 说明 |
|---|---|---|---|
init |
(): Promise<TtsVoicePick> |
语音挑选结果 | 初始化引擎,进入 ready。失败时返回值中带诊断信息,同时 onChange 收到 error |
speak |
(text: string, opts: TtsSpeakOptions): void |
— | 朗读。朗读中/暂停中重复调用 = 打断旧朗读、播新的 |
pause |
(): void |
— | 暂停。iOS 真断点;Android 估算位置后停止 |
resume |
(): void |
— | 继续播放 |
changeParamsLive |
(opts: Partial<TtsSpeakOptions>): void |
— | 播放中实时调参,仅 Android 立即生效;iOS 下次播放生效 |
stop |
(): void |
— | 停止并复位进度 |
getState |
(): TtsState |
当前状态 | 'init' \| 'ready' \| 'speaking' \| 'paused' \| 'error' |
getEngineName |
(): string |
引擎包名 | 仅 Android 有值(如 com.google.android.tts);用于排查引擎兼容问题 |
destroy |
(): void |
— | 释放资源,页面 onUnmounted 时调用 |
openSystemTtsSettings |
(): void |
— | 跳系统 TTS 设置页,仅 Android;跳转失败时自动弹手动路径提示 |
另外导出:getTtsPlatform(): TtsPlatform('android' | 'ios' | 'other')与全部类型(SystemTts / TtsState / TtsError / TtsErrorCode / TtsSpeakOptions / TtsVoicePick / TtsStateListener)。
错误码(TtsError.code)
| code | 含义 | 建议处理 |
|---|---|---|
UNSUPPORTED_PLATFORM |
H5/小程序环境 | 隐藏朗读相关 UI |
NOT_READY |
引擎未就绪(init 未完成或 error 态) | 提示稍候/引导重新初始化 |
INIT_FAILED |
Android 无可用 TTS 引擎 | 调 openSystemTtsSettings() 引导安装 |
VOICE_MISSING |
缺中文语音数据 | Android 跳设置下载语音数据;iOS 引导下载「婷婷」后重新 init() |
PLAY_FAILED |
播放调用失败(含无声诊断信息) | 按 message 提示;iOS 看 [tts-ios] 控制台日志 |
四、最小可运行示例
⚠️ 运行前提:本模块依赖 uni-app App 端的 5+ Runtime(
plus)与手机系统语音引擎,Node.js / 浏览器 / H5 都跑不起来。下面的页面请放进 uni-app 项目,用 HBuilderX「运行到手机基座」在真机执行(Android 手机开 USB 调试;iOS 需数据线 + 免费 Apple ID 证书,首次启动需在 设置→通用→VPN与设备管理 信任开发者)。
最小完整页面(复制到 pages/test/tts.vue 即可运行):
<template>
<view style="padding: 24rpx">
<input v-model="text" placeholder="输入要朗读的文字" />
<button :disabled="state !== 'ready'" @click="play">播放</button>
<button :disabled="state !== 'speaking'" @click="tts.pause()">暂停</button>
<button :disabled="state !== 'paused'" @click="tts.resume()">继续</button>
<button @click="tts.stop()">停止</button>
</view>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
import { createSystemTts, type TtsState } from '@/uni_modules/zqj-parrot-tts/js_sdk/index'
const text = ref('你好,系统语音合成测试')
const state = ref<TtsState>('init')
const tts = createSystemTts((s, err) => {
state.value = s
if (err) uni.showToast({ title: err.message, icon: 'none' })
})
function play() {
tts.speak(text.value, { rate: 1.0, pitch: 1.0, volume: 1.0 })
}
onMounted(async () => {
const pick = await tts.init()
if (!pick.voiceFound) uni.showToast({ title: '未找到中文语音,请到系统设置下载', icon: 'none' })
})
onUnmounted(() => tts.destroy())
</script>
五、文件结构
uni_modules/zqj-parrot-tts/
├── package.json # 插件描述文件(发布上架用;本地可直接用)
├── readme.md # 本文档
├── changelog.md # 版本日志
├── PUBLISH.md # 发布到 DCloud 插件市场的步骤与前置清单
└── js_sdk/
├── index.ts # 出口:createSystemTts 工厂 + 类型导出 + H5 降级实现
├── types.ts # 全部 TS 类型(SystemTts 接口约束双端实现)
├── platform.ts # getTtsPlatform():条件编译 + platform 二次分流
├── android.ts # Android TextToSpeech 实现
└── ios.ts # iOS AVSpeechSynthesizer 实现(含 Native.js 双路径调用层)
六、常见问题(FAQ)
1. Android 点播放没反应 / 报 INIT_FAILED?
设备没装 TTS 引擎(国行常见)。调 tts.openSystemTtsSettings() 跳过去装「Google 文字转语音」或厂商引擎并下载中文语音数据,回来重新 init()。
2. Android 语速/音高拖了没变化?
先看 tts.getEngineName():部分厂商引擎(小米等)会忽略 setSpeechRate/setPitch,属引擎限制。换 Google 文字转语音引擎即可。另外注意 setSpeechRate 只对下一次合成生效——播放中拖动请用 changeParamsLive()(会从估算断点以新参数续播)。
3. Android 暂停后继续,位置差了几秒? Android TTS 没有暂停接口、也拿不到播放进度(进度回调是抽象类,Native.js 代理不了),模块按「时长 × 语速」估算,1~2 秒偏差是预期行为。要精确续播需写原生插件。
4. iOS 没声音?
按顺序查:① 系统是否下载了经典中文语音(设置→辅助功能→朗读内容→声音→中文(中国)→「婷婷」;注意 Siri 声音≠这套语音)→ 下载后重新 init();② 控制台看 [tts-ios] 日志定位断在哪一步;③ 静音键问题模块已通过 AVAudioSession playback 类别规避。
5. 权限?缓存?跨域?
两端均不需要任何权限声明(不涉及麦克风/网络);无缓存与跨域问题(纯本地系统调用)。唯一资源管理点是页面卸载时调 destroy()。
6. H5 / 小程序能编译通过吗?
能。非 App 端工厂返回降级实现,init() 上报 UNSUPPORTED_PLATFORM,平台实现模块在编译期被条件编译剔除,不会把 plus 打进 H5 包。
7. iOS 免费证书相关? 与本模块无关,但影响调试:免费 Apple ID 签名的基座 7 天过期,到期重新运行即可。
发布到 DCloud 插件市场的步骤、package.json 说明与前置清单见 PUBLISH.md。

收藏人数:
下载插件并导入HBuilderX
下载插件ZIP
赞赏(0)
下载 1
赞赏 0
下载 12559264
赞赏 1948
赞赏
京公网安备:11010802035340号