更新记录
1.0.20260312(2026-03-12)
- 支持实时语音识别
- 支持语音合成
平台兼容性
uni-app(4.57)
| Vue2 |
Vue3 |
Chrome |
Safari |
app-vue |
app-nvue |
Android |
iOS |
鸿蒙 |
| √ |
√ |
× |
× |
× |
× |
√ |
× |
× |
| 微信小程序 |
支付宝小程序 |
抖音小程序 |
百度小程序 |
快手小程序 |
京东小程序 |
鸿蒙元服务 |
QQ小程序 |
飞书小程序 |
小红书小程序 |
快应用-华为 |
快应用-联盟 |
| × |
× |
× |
× |
× |
× |
× |
× |
× |
- |
× |
× |
uni-app x(4.57)
| Chrome |
Safari |
Android |
iOS |
鸿蒙 |
微信小程序 |
| - |
- |
- |
- |
- |
- |
阿里NUI百炼语音
引入插件
- 点击插件试用引入到项目
- 按下方修改Android需要修改的内容
- 打包自定义基座包
- 按照下方示例测试
- 先插件试用,完全符合需求后购买
SDK Version
useAsr(opt: UseAsrOption):AlibabaAsr 实时语音识别
以下大部分参数都为官方参数可以参考官方文档方便理解,
阿里百炼官方文档说明。
代码示例
import { useAsr } from "@/uni_modules/cms-alibanui";
let asr = useAsr({
apikey: "< your apikey >",
model: "fun-asr-realtime",
onAsrStart() {},
onAsrOver() {},
onSpeechResult(obj) {
console.log('onSpeechResult 识别文本:', obj.payload.output.sentence.text);
},
onSpeechParagraphEnd(obj) {
console.log('onSpeechParagraphEnd 识别文本:', obj.payload.output.sentence.text);
},
onSpeechComplete(str) {
console.log('onSpeechComplete:', str);
}
})
UseAsrOption
| 参数 |
类型 |
描述 |
必填 |
| apikey |
string |
阿里百炼apikey |
是 |
| model |
string |
语音识别模型 |
是 |
| onAsrStart |
function |
识别开始回调 |
否 |
| onAsrOver |
function |
识别结束回调 |
否 |
| onSpeechResult |
function(UTSJSONObject) |
语音实时识别结果回调 |
否 |
| onSpeechParagraphEnd |
function(UTSJSONObject) |
语音段落结束回调 |
否 |
| onSpeechComplete |
function(string) |
语音识别完成回调,会完整回调本次识别信息 |
否 |
| device_id |
string |
设备ID |
否 |
| service_mode |
string |
运行模式。实时语音识别固定为 "1"。 |
否 |
| url |
string |
服务地址,固定为 wss://dashscope.aliyuncs.com/api-ws/v1/inference |
否 |
| service_type |
number |
语音服务类型。实时语音识别固定为 4。 |
否 |
| disfluency_removal_enabled |
boolean |
是否过滤语气词,如“嗯”、“啊”等。默认值:false。 |
否 |
| language_hints |
string[] |
设置待识别语言代码。如果无法提前确定语种,可不设置,模型会自动识别语种。支持的语言代码:zh: 中文 en: 英文 ja: 日语 yue: 粤语 ko: 韩语 de:德语 fr:法语 ru:俄语 该参数仅对支持多语言的模型生效 |
否 |
| semantic_punctuation_enabled |
boolean |
设置断句模式 |
否 |
| max_sentence_silence |
number |
断句的静音时长阈值(单位为ms)。默认值:800 取值范围:[200, 6000] 当一段语音后的静音时长超过该阈值时,系统会判定该句子已结束。 |
否 |
| multi_threshold_mode_enabled |
boolean |
是否开启防过长切割模式。开启可防止VAD断句切割过长 默认值:false(关闭)取值范围:true:开启 false:关闭 该参数仅在semantic_punctuation_enabled参数为false且模型为v2及更高版本时生效。 |
否 |
| punctuation_prediction_enabled |
boolean |
是否在识别结果中自动添加标点符号 默认值:true(是)取值范围:true:是 false:否 该参数仅在模型为v2及更高版本时生效 |
否 |
| heartbeat |
boolean |
是否和服务端保持长连接 默认值:false |
否 |
| inverse_text_normalization_enabled |
boolean |
是否开启ITN(Inverse Text Normalization,逆文本正则化)开启后,中文数字将转换为阿拉伯数字 默认值:true(开启) |
否 |
| vocabulary_id |
string |
热词词表ID,用于提升特定词汇的识别准确率 |
否 |
| resources |
{ resource_id: string,resource_type:string }[] |
热词资源配置,用于v1版本模型。 |
否 |
AlibabaAsr 方法
| 方法 |
描述 |
返回值 |
| startAsr() |
开始语音识别 |
Promise[boolean] |
| stopAsr() |
停止语音识别 |
void |
| release() |
释放资源 |
void |
useTts(opt: UseAsrOption):AlibabaTts 实时语音合成
以下大部分参数都为官方参数可以参考官方文档方便理解,
阿里百炼官方文档说明。
代码示例
import { useTts } from "@/uni_modules/cms-alibanui";
let asr = useTts({
apikey: "< your apikey >",
model: "cosyvoice-v3-flash",
voice: "longanlang_v3",
onPlayStart() {
console.log('onPlayStart');
},
onPlayOver() {
console.log('onPlayOver');
},
onPlaySoundLevel(level) {
console.log('onPlaySoundLevel', level);
},
onPlayInfo(info) {
console.log('onPlayInfo', info);
}
})
UseTtsOption
| 参数 |
类型 |
描述 |
必填 |
| apikey |
string |
阿里百炼apikey |
是 |
| model |
string |
语音合成模型 |
是 |
| voice |
string |
语音音色 |
是 |
| onPlayStart |
function |
播放开始回调 |
否 |
| onPlayOver |
function |
播放结束回调 |
否 |
| onPlaySoundLevel |
function(number) |
播放音量回调 |
否 |
| onPlayInfo |
function(string) |
播放信息回调 |
否 |
| device_id |
string |
设备ID |
否 |
| url |
string |
服务地址,固定为 wss://dashscope.aliyuncs.com/api-ws/v1/inference |
否 |
| complete_waiting_ms |
number |
调用stop接口后,等待合成完成事件(STREAM_INPUT_TTS_EVENT_SYNTHESIS_COMPLETE)的超时时间(毫秒)。默认值:10000。 |
否 |
| volume |
number |
音量 默认值:50取值范围:[0, 100] 50代表标准音量 音量大小与该值呈线性关系,0为静音,100为最大音量 |
否 |
| rate |
number |
语速 默认值:1.0 取值范围:[0.5, 2.0]。1.0为标准语速,小于1.0则减慢,大于1.0则加快 |
否 |
| pitch |
number |
音高 该值作为音高调节的乘数,但其与听感上的音高变化并非严格的线性或对数关系,建议通过测试选择合适的值 默认值:1.0 取值范围:[0.5, 2.0]。1.0为音色自然音高。大于1.0则音高变高,小于1.0则音高变低 |
否 |
| enable_ssml |
boolean |
是否开启SSML功能 默认值:false |
否 |
| word_timestamp_enabled |
boolean |
是否开启字级别时间戳 默认值:false |
否 |
| seed |
number |
生成时使用的随机数种子,使合成的效果产生变化。在模型版本、文本、音色及其他参数均相同的前提下,使用相同的seed可复现相同的合成结果 默认值0 取值范围:[0, 65535] cosyvoice-v1不支持该功能 |
否 |
| language_hints |
string[] |
指定语音合成的目标语言 |
否 |
| instruction |
string |
cosyvoice-v3-flash:需遵照如下要求 |
否 |
| enable_aigc_tag |
boolean |
是否在生成的音频中添加AIGC隐性标识。设置为true时,会将隐性标识嵌入到支持格式(wav/mp3/opus)的音频中 默认值:false |
否 |
| aigc_propagator |
string |
设置AIGC隐性标识中的 ContentPropagator 字段,用于标识内容的传播者。仅在 enable_aigc_tag 为 true 时生效 默认值:阿里云UID 仅cosyvoice-v3-flash、cosyvoice-v3-plus、cosyvoice-v2支持该功能 |
否 |
| aigc_propagate_id |
string |
设置AIGC隐性标识中的 PropagateID 字段,用于唯一标识一次具体的传播行为。仅在 enable_aigc_tag 为 true 时生效 默认值:本次语音合成请求Request ID 仅cosyvoice-v3-flash、cosyvoice-v3-plus、cosyvoice-v2支持该功能 |
否 |
AlibabaTts 方法
| 方法 |
描述 |
返回值 |
| startStreamInputTts(session_id?: string) |
开始流式输入合成 |
void |
| sendStreamInputTts(text:string) |
发送流式输入文本 |
void |
| stopStreamInputTts() |
停止流式输入合成 |
void |
| asyncStopStreamInputTts() |
异步停止流式输入 |
void |
| asyncPlayStreamInputTts(text:string,session_id?: string) |
异步播放流式输入 |
void |
| playStreamInputTts(text:string,session_id?: string) |
播放流式输入 |
void |
| stopTtsPlayAudio() |
停止TTS播放 |
void |
<template>
<view class="container">
<view class="form-item">
apiKey:<input class="input" type="text" v-model="apikey" placeholder="请输入API Key" />
</view>
<view class="tab_ul">
<view :class="['tab-item', tabIndex === 0 ? 'active' : '']" @click="tabIndex = 0">语音合成</view>
<view :class="['tab-item', tabIndex === 1 ? 'active' : '']" @click="tabIndex = 1">语音识别</view>
</view>
<block v-if="tabIndex == 0">
<button :disabled="!!tts" class="btn" @click="initTts" type="primary">初始化TTS</button>
<view class="form-item">
<textarea class="textarea" v-model="ttsMsg" placeholder="请输入文本" />
</view>
<button class="btn" :disabled="!tts || streamInputTtsState" @click="asyncPlayStreamInputTts"
type="primary">一次性异步播放</button>
<button class="btn" :disabled="!tts || streamInputTtsState" @click="playStreamInputTts"
type="primary">一次性同步播放</button>
<button class="btn" :disabled="!tts || streamInputTtsState" @click="startStreamInputTts"
type="primary">流式输入开启</button>
<view v-if="streamInputTtsState">流式输入开启后在不关闭情况下可以一直点击【流式输入文本】按钮播放</view>
<button class="btn" :disabled="!tts || !streamInputTtsState" @click="sendStreamInputTts"
type="primary">流式输入文本</button>
<button class="btn" :disabled="!tts || !streamInputTtsState" @click="stopStreamInputTts"
type="primary">同步流式输入停止</button>
<button class="btn" :disabled="!tts || !streamInputTtsState" @click="asyncStopStreamInputTts"
type="primary">异步流式输入停止</button>
</block>
<block v-if="tabIndex == 1">
<button :disabled="!!asr" class="btn" @click="initAsr" type="primary">初始化实时ASR</button>
<button class="btn" :disabled="!asr || isAsrState" @click="startAsr" type="primary">开始实时语音识别</button>
<button class="btn" :disabled="!asr || !isAsrState " @click="stopAsr" type="primary">结束实时语音识别</button>
<button class="btn" :disabled="!asr " @click="releaseAsr" type="primary">释放ASR</button>
<view class="form-item">
{{asrMsg || "..."}}
</view>
</block>
</view>
</template>
<script setup>
import {
ref
} from "vue";
const tabIndex = ref(0);
const apikey = ref("");
import {
useAsr
} from "@/uni_modules/cms-alibanui";
const asr = ref();
const asrMsg = ref("");
const isAsrState = ref(false);
function initAsr() {
asr.value = useAsr({
apikey: apikey.value,
model: "fun-asr-realtime",
onAsrStart() {
console.log('onAsrStart');
},
onAsrOver() {
console.log('onAsrOver');
},
onSpeechResult(obj) {
console.log('onSpeechResult', obj);
console.log('onSpeechResult 识别文本:', obj.payload.output.sentence.text);
asrMsg.value = obj.payload.output.sentence.text;
},
onSpeechParagraphEnd(obj) {
console.log('onSpeechParagraphEnd', obj);
console.log('onSpeechParagraphEnd 识别文本:', obj.payload.output.sentence.text);
asrMsg.value = obj.payload.output.sentence.text;
},
onSpeechComplete(str) {
console.log('本次语音整体识别到的文本:', str);
asrMsg.value = str;
}
})
}
async function startAsr() {
asrMsg.value = "";
isAsrState.value = await asr.value.startAsr();
}
function stopAsr() {
asr.value.stopAsr();
isAsrState.value = false;
}
function releaseAsr() {
asr.value.release();
asr.value = null;
isAsrState.value = false;
}
import {
useTts
} from "@/uni_modules/cms-alibanui";
const tts = ref();
const ttsMsg = ref("床前明月光,疑是地上霜。")
function initTts() {
tts.value = useTts({
apikey: apikey.value,
model: "cosyvoice-v3-flash",
voice: "longanlang_v3",
onPlayStart() {
console.log('onPlayStart');
},
onPlayOver() {
console.log('onPlayOver');
},
onPlaySoundLevel(level) {
console.log('onPlaySoundLevel', level);
},
onPlayInfo(info) {
console.log('onPlayInfo', info);
}
});
}
function playStreamInputTts() {
console.log('playStreamInputTts');
tts.value.playStreamInputTts(ttsMsg.value, "")
}
function asyncPlayStreamInputTts() {
tts.value.asyncPlayStreamInputTts(ttsMsg.value, "")
}
const streamInputTtsState = ref(false);
function startStreamInputTts() {
streamInputTtsState.value = true;
tts.value.startStreamInputTts();
}
function sendStreamInputTts() {
tts.value.sendStreamInputTts(ttsMsg.value);
}
function stopStreamInputTts() {
streamInputTtsState.value = false;
tts.value.stopStreamInputTts();
}
function asyncStopStreamInputTts() {
streamInputTtsState.value = false;
tts.value.asyncStopStreamInputTts();
}
</script>
<style scoped lang="scss">
.container {
padding: 30rpx;
background-color: #f5f5f5;
min-height: 100vh;
}
.form-item {
display: flex;
align-items: center;
margin-bottom: 30rpx;
background-color: #fff;
padding: 20rpx;
border-radius: 12rpx;
input,
textarea {
flex: 1;
}
}
.input {
width: 100%;
height: 80rpx;
padding: 0 20rpx;
border: 1rpx solid #e0e0e0;
border-radius: 8rpx;
box-sizing: border-box;
font-size: 28rpx;
background-color: #fafafa;
}
.textarea {
width: 100%;
height: 200rpx;
padding: 20rpx;
border: 1rpx solid #e0e0e0;
border-radius: 8rpx;
box-sizing: border-box;
font-size: 28rpx;
background-color: #fafafa;
}
.tab_ul {
display: flex;
margin-bottom: 30rpx;
background-color: #fff;
border-radius: 12rpx;
overflow: hidden;
.tab-item {
flex: 1;
text-align: center;
padding: 30rpx 0;
font-size: 28rpx;
color: #666;
position: relative;
transition: all 0.3s;
&:active {
background-color: #f0f0f0;
}
&.active {
color: #007aff;
background-color: #f0f8ff;
font-weight: bold;
}
}
}
.btn {
margin-bottom: 20rpx;
border-radius: 12rpx;
font-size: 28rpx;
height: 88rpx;
line-height: 88rpx;
}
.btn[disabled] {
opacity: 0.5;
}
</style>