更新记录

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

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集任何数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议

暂无用户评论。