更新记录
1.0.3(2026-01-08)
- 适配鸿蒙
1.0.2(2026-01-08)
- 优化代码实现,处理回调函数被释放的问题
- 更新说明文件,增加使用示例
1.0.1(2024-11-13)
- 增加只有文本输入的方法
查看更多
平台兼容性
uni-app(3.91)
| Vue2 |
Vue3 |
Chrome |
Safari |
app-vue |
app-nvue |
Android |
iOS |
鸿蒙 |
鸿蒙插件版本 |
| - |
- |
- |
- |
- |
- |
- |
- |
11 |
1.0.3 |
| 微信小程序 |
支付宝小程序 |
抖音小程序 |
百度小程序 |
快手小程序 |
京东小程序 |
鸿蒙元服务 |
QQ小程序 |
飞书小程序 |
小红书小程序 |
快应用-华为 |
快应用-联盟 |
| - |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
yk-tts
uts实现安卓语音播报功能
方法
| 方法名 |
说明 |
参数 |
| init |
初始化监听设置 |
{ onStart, onDone, onError, onStop } |
| speak |
开始播报 |
SpeekOptions |
| speakString |
开始播报(纯文本) |
text: string |
| stop |
停止播报 |
- |
SpeekOptions 参数说明
// bundle参数
BundleOptions = {
pan ?: number, // 参数键用于指定说话时文字从左向右平移的方式。 平移指定为范围从-1到+1的浮点,其中-1映射到硬左平移,0为中心(默认行为),+1为右移
stream ?: string, // STREAM_MUSIC、STREAM_NOTIFICATION、STREAM_RING
volume ?: number, //音量 0-1
}
// 播报参数
SpeekOptions = {
id ?: string, // 播报id
text : string, // 播报文本
mode ?: 'flush' | 'add' , // flush = 抢占模式播报 | add = 排队模式播报
bundle ?: BundleOptions, // 其他参数
listener ?: () => void
}
使用示例
import * as yktts from '@/uni_modules/yk-tts'
// 初始化(设置监听回调)
yktts.init({
onStart: (utteranceId) => {
console.log('onStart: ', utteranceId);
},
onDone: (utteranceId) => {
console.log('onDone: ', utteranceId);
},
onError: (utteranceId, errorCode) => {
console.log('onError: ', utteranceId, errorCode);
},
onStop: (utteranceId, interrupted) => {
console.log('onStop: ', utteranceId, interrupted);
},
})
// 播报
yktts.speak({
text: '你好呀',
id: 'text',
bundle: {
volume: 1
}
})
// 停止播报
yktts.stop()
完整示例(快速使用)
<template>
<view class="container">
<view class="title">TTS 语音播报</view>
<view class="input-area">
<textarea
v-model="ttsText"
placeholder="输入要播报的文字"
class="input"
auto-height="true"
/>
</view>
<view class="controls">
<button @click="speakText" class="btn primary">开始播报</button>
<button @click="speakTextDirect" class="btn">直接播报</button>
<button @click="stopTTS" class="btn">停止播报</button>
</view>
<view class="settings">
<view class="setting-item">
<text class="label">音量:</text>
<input
v-model="volume"
type="number"
placeholder="0-1之间"
class="setting-input"
/>
</view>
<view class="setting-item">
<text class="label">播报ID:</text>
<input
v-model="utteranceId"
placeholder="唯一标识"
class="setting-input"
/>
</view>
</view>
<view class="logs">
<view class="log-title">事件日志</view>
<scroll-view class="log-content" scroll-y="true">
<view
v-for="(log, index) in logs"
:key="index"
class="log-item"
>
{{ log }}
</view>
</scroll-view>
<button @click="clearLogs" class="btn small">清空日志</button>
</view>
</view>
</template>
<script setup>
import * as yktts from '@/uni_modules/yk-tts'
import { ref } from 'vue'
// 状态变量
const ttsText = ref('你好呀,欢迎使用TTS语音播报功能')
const volume = ref('1')
const utteranceId = ref('tts_001')
const logs = ref([])
// 初始化(设置监听回调)
yktts.init({
onStart: (id) => {
addLog(`onStart: ${id}`)
},
onDone: (id) => {
addLog(`onDone: ${id}`)
},
onError: (id, errorCode) => {
addLog(`onError: ${id}, 错误码: ${errorCode}`)
},
onStop: (id, interrupted) => {
addLog(`onStop: ${id}, 被中断: ${interrupted}`)
},
})
// 添加日志
function addLog(message) {
const timestamp = new Date().toLocaleTimeString()
logs.value.unshift(`${timestamp} - ${message}`)
}
// 开始播报
function speakText() {
const volumeNum = parseFloat(volume.value) || 1
if (volumeNum < 0 || volumeNum > 1) {
uni.showToast({
title: '音量应在0-1之间',
icon: 'none'
})
return
}
yktts.speak({
text: ttsText.value,
id: utteranceId.value,
bundle: {
volume: volumeNum
}
})
addLog(`开始播报: ${ttsText.value.substring(0, 20)}${ttsText.value.length > 20 ? '...' : ''}`)
}
// 直接播报(纯文本)
function speakTextDirect() {
yktts.speakString(ttsText.value)
addLog(`直接播报: ${ttsText.value.substring(0, 20)}${ttsText.value.length > 20 ? '...' : ''}`)
}
// 停止播报
function stopTTS() {
yktts.stop()
addLog('停止播报')
}
// 清空日志
function clearLogs() {
logs.value = []
}
</script>
<style>
.container {
padding: 40rpx;
background-color: #f5f5f5;
min-height: 100vh;
box-sizing: border-box;
}
.title {
font-size: 48rpx;
font-weight: bold;
text-align: center;
margin: 40rpx 0 60rpx;
color: #333;
}
.input-area {
margin-bottom: 40rpx;
}
.input {
width: 100%;
min-height: 200rpx;
padding: 20rpx;
background: white;
border-radius: 20rpx;
border: 1rpx solid #ddd;
box-sizing: border-box;
font-size: 32rpx;
}
.controls {
display: flex;
flex-wrap: wrap;
gap: 20rpx;
margin-bottom: 40rpx;
}
.btn {
flex: 1;
min-width: 200rpx;
height: 80rpx;
line-height: 80rpx;
font-size: 32rpx;
text-align: center;
border-radius: 10rpx;
background-color: #f0f0f0;
border: none;
color: #333;
}
.btn.primary {
background-color: #007aff;
color: white;
}
.settings {
background: white;
padding: 30rpx;
border-radius: 20rpx;
margin-bottom: 40rpx;
}
.setting-item {
display: flex;
align-items: center;
margin-bottom: 20rpx;
}
.setting-item:last-child {
margin-bottom: 0;
}
.label {
width: 120rpx;
font-size: 30rpx;
color: #666;
}
.setting-input {
flex: 1;
height: 60rpx;
padding: 0 20rpx;
border: 1rpx solid #ddd;
border-radius: 10rpx;
font-size: 28rpx;
}
.logs {
background: white;
border-radius: 20rpx;
overflow: hidden;
}
.log-title {
padding: 20rpx 30rpx;
background: #f9f9f9;
font-size: 32rpx;
font-weight: bold;
color: #333;
border-bottom: 1rpx solid #eee;
}
.log-content {
height: 400rpx;
padding: 20rpx;
background: #fafafa;
}
.log-item {
padding: 10rpx 0;
font-size: 26rpx;
color: #555;
border-bottom: 1rpx solid #eee;
word-break: break-all;
}
.log-item:last-child {
border-bottom: none;
}
.small {
width: 160rpx;
height: 60rpx;
line-height: 60rpx;
font-size: 28rpx;
margin: 20rpx auto 0;
display: block;
}
</style>