更新记录
1.1.0(2026-09-08)
- fix: iOS 文件合成失败、取消或停止时正确拒绝 Promise,并保留插件错误码和错误信息。
- fix: iOS 支持并发文件合成,默认输出路径互不覆盖;文件写入完成并关闭后才返回成功,取消后的回调不会影响新任务。
- fix: Android 暂停期间新增朗读会继续排队;恢复时不会重复触发
onStart,并从最近的边界继续播放。 - fix: Android 文件合成支持对生成的 WAV 应用
volume,写入或音量处理失败时 Promise 会拒绝。 - fix: 传统 uni-app 在 HBuilderX 5.24 及以上版本中可以通过
catch接收 Android 文件合成错误。 - fix: Harmony 的
onDone在整段文本播放完成后触发;连续朗读、暂停恢复和文件合成队列行为得到修正。 - fix: Harmony 停止时会取消当前及排队中的文件合成任务,并为并发文件任务生成独立的默认路径。
- feat: 支持音量调节(
volume0.0 ~ 1.0)在 Android 和 iOS 原生生效 - feat: 新增国内 Android 机型 TTS 引擎检测(
getEnginesAsync,isEngineAvailableAsync)与一键跳转系统设置(openTtsSettings) - fix: Harmony
resume()现在会重新提交暂停时未播完的语句(原先静默无效),从暂停分句开头重播 - fix: Harmony 引擎初始化并发等待改为共享 Promise,去除轮询忙等
- fix: 三端
stop()打断synthesizeToFile时现在会以失败落定 Promise(原先永久挂起) - fix: Android TTS 初始化失败后会释放坏实例并在下次调用时重试(原先后续 speak 永久静默挂起)
- fix: iOS 暂停后调用
stop()会先恢复合成器,修复之后speak()静音不播的问题 - fix: Android 引擎回调 Map 改为并发安全;修复
getVoicesAsync遇到未知 ISO3 国家码时的崩溃风险
1.0.0(2026-01-27)
- feat: 提供语音合成(TTS)核心 API(Android/iOS)
- feat: 新增 playground 验证页(
uniappx-speech-playground/pages/index/index.uvue) - docs: 完善使用文档与发布/实现说明
平台兼容性
uni-app(4.87)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| √ | √ | - | - | √ | √ | √ | √ | √ |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| - | - | - | - | - | - | - | - | - | - | - | - |
uni-app x(4.87)
| Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|
| - | - | √ | √ | √ | - |
hans-speech
uni-app / uni-app x App 端语音合成(TTS)插件(Android / iOS / Harmony)。
平台
- Android / iOS / Harmony:支持(App 端)
- Web / 小程序:不支持
说明:
- 本插件为 TTS(语音合成),不需要麦克风/语音识别权限
- Android
onBoundary仅在 API 26+ 触发(系统限制);Harmony 暂不触发onBoundary
安装
- 插件市场安装后,会在项目根目录生成
uni_modules/hans-speech/ - 或将
hans-speech文件夹复制到你的项目uni_modules/下
引入
import {
speak,
stop,
pause,
resume,
getAvailableVoicesAsync,
isSpeakingAsync,
synthesizeToFileAsync,
maxSpeechInputLength,
getMaxSpeechInputLength,
setLogEnabled,
isLogEnabled,
getEnginesAsync,
isEngineAvailableAsync,
openTtsSettings,
// 类型(仅 uni-app x 支持)
type Voice,
type TtsEngineInfo,
type SpeechOptions,
type SynthesizeToFileOptions,
type AudioFocusMode,
type HansSpeechError,
} from '@/uni_modules/hans-speech'
类型导入(uni-app x)
uni-app x 页面可以通过 type X 显式导入插件导出的类型,获得完整的 IDE 补全与编译期类型检查:
import {
speak,
getAvailableVoicesAsync,
type Voice,
type SpeechOptions,
} from '@/uni_modules/hans-speech'
const options: SpeechOptions = {
language: 'zh-CN',
onDone: () => console.log('done'),
}
speak('你好', options)
const voices: Array<Voice> = await getAvailableVoicesAsync()
const first: Voice | null = voices.length > 0 ? voices[0] : null
可导入的类型:
| 类型 | 说明 |
|---|---|
Voice |
发音人:identifier / name / language / quality |
TtsEngineInfo |
TTS 引擎信息:name / label / icon |
SpeechOptions |
speak() 的参数(含全部回调) |
SynthesizeToFileOptions |
synthesizeToFileAsync() 的参数 |
AudioFocusMode |
音频焦点模式:'duck' \| 'pauseOthers' \| 'mix' \| 'none' |
VoiceQuality |
音质标记:'Default' \| 'Enhanced' |
HansSpeechError / HansSpeechErrorCode |
插件错误对象与错误码 |
NativeBoundaryEvent / NativeBoundaryEventCallback |
onBoundary 边界事件 |
说明:type X 导入仅 uni-app x(uts)页面支持;经典 uni-app(JS)页面直接调用函数即可,不要导入类型。
快速开始
speak('你好', {
language: 'zh-CN',
rate: 1.0,
pitch: 1.0,
onStart: () => console.log('start'),
onDone: () => console.log('done'),
onStopped: () => console.log('stopped'),
onBoundary: (e) => console.log(e.charIndex, e.charLength),
onError: (e) => console.error(e.message),
})
停止/暂停/恢复/状态:
await stop()
const speaking = await isSpeakingAsync()
await pause()
await resume()
各端 pause()/resume() 语义见下方「平台差异」。
语音列表与选择发音人
const voices = await getAvailableVoicesAsync()
const v = voices.length > 0 ? voices[0] : null
speak('Hello', {
voice: v?.identifier ?? '',
})
Voice 字段:
identifier: string(用于SpeechOptions.voice)name: stringlanguage: string(例如zh-CN/en-US)quality: string(通常为Default/Enhanced,平台返回值可能略有差异)
speak(text, options)
SpeechOptions:
language?: string:语言/地区(例如zh-CN/en-US),不传则使用系统默认语言rate?: number:语速,建议范围0.1 ~ 2.0(不传则使用系统默认)pitch?: number:语调,建议范围0.5 ~ 2.0(不传则使用系统默认)volume?: number:音量,范围0.0 ~ 1.0(0.0 静音,1.0 最大音量,默认 1.0)voice?: string:发音人 identifier(来自getAvailableVoicesAsync())audioFocusMode?: string:音频焦点模式'duck' | 'pauseOthers' | 'mix' | 'none'(Android,默认'duck')useApplicationAudioSession?: boolean:仅 iOS 13+,不传则使用系统默认autoChunk?: boolean:超长文本自动按句子分块播报,默认true- 回调:
onStart / onBoundary / onDone / onStopped / onError
说明:
- 多次调用
speak()会追加到队列;需要“打断并重播”请先await stop()再speak() onDone表示整段文本播放完成;暂停不会触发onDone或onStopped,恢复不会重复触发该段文本的onStart。speak()的错误通过options.onError(error)回调返回(error.message中会包含错误码信息,例如HansSpeechError(9010002): ...)
TTS 引擎检测与设置(Android 优化)
针对国内部分定制 ROM 可能缺失默认引擎或语音包的问题,提供以下辅助 API:
// 检查是否有可用引擎
const available = await isEngineAvailableAsync()
// 获取已安装引擎列表
const engines = await getEnginesAsync()
// 打开系统 TTS 设置页(引导用户安装或切换引擎)
openTtsSettings()
说明:iOS 与 Harmony 使用系统内置唯一引擎,getEnginesAsync() 返回固定的系统引擎信息、isEngineAvailableAsync() 返回 true。
离线合成到文件
const filePath = await synthesizeToFileAsync('需要转成音频的文本', {
language: 'zh-CN',
// targetFilePath: '/path/to/output.pcm', // 不传则写入应用缓存目录
})
- Android / iOS 输出
.wav,Harmony 输出.pcm;不传targetFilePath时写入应用缓存目录并返回完整路径 - iOS 支持并发提交,文件请求按顺序合成,与朗读使用独立队列;WAV 写入并关闭后返回路径,默认路径每个任务独立。写入失败或
stop()取消当前及排队文件时,Promise 以9010005拒绝;取消后可继续提交新任务,已创建的未完成文件会删除。并发时若自行指定targetFilePath,请为每个任务使用不同路径。 - Android 的
volume会应用到合成后的 WAV 数据,0输出静音,0.5将采样幅度减半;Promise 在音量处理完成后返回,写入或处理失败时拒绝并返回9010005。传统 uni-app 的错误回传适配需使用 HBuilderX 5.24 或更新版本。 - Harmony 的文件合成与朗读共用提交队列,合成 Promise 在文件写入完成后返回;
stop()会取消当前及排队任务。暂停朗读不会中断正在写入的文件,但后续排队任务需在resume()后继续。
文本长度限制
maxSpeechInputLength: number:Android 为系统限制;iOS 为Number.MAX_VALUE;Harmony 为10000getMaxSpeechInputLength(): number:获取当前限制值(用于兼容少量场景下导入常量失败的问题)
平台差异
pause()/resume():iOS 为系统原生暂停/恢复;Android 从引擎最后上报的边界恢复,未上报边界时从当前分段开头重播,暂停期间新增朗读继续排队;Harmony 恢复时从暂停的分句开头重新播报(CoreSpeechKit 无暂停/恢复 API)onBoundary:Android 仅 API 26+ 触发;iOS 正常触发;Harmony 暂不支持- 超长文本自动分块(
autoChunk)三端均支持,由插件内部分句后依次播报
日志
插件内部默认会打印关键行为与事件,可按需关闭:
setLogEnabled(false)
const enabled = isLogEnabled()
错误码
统一错误码段:90xxxxx
9010001:not supported(保留码,当前版本未使用)9010002:input too long(Android)9010003:invalid voice(iOS)9010004:get voices failed9010005:unknown
提示:
pause()/resume()/stop()/getAvailableVoicesAsync()通过Promisereject 返回错误对象(通常包含errCode/errMsg/errSubject)speak()的错误通过options.onError(error)回调返回

收藏人数:
https://github.com/sujianqingfeng/uniappx-speech
购买普通授权版(
试用
使用 HBuilderX 导入示例项目
赞赏(0)
下载 392
赞赏 0
下载 12590184
赞赏 1949
赞赏
京公网安备:11010802035340号