- 百度语音合成实现步骤
Step1:成为百度AI开放平台的开发者
- 要调用百度AI开放平台的语音合成能力先要成为百度AI开放平台的开发者,
- 首先让我们花5分钟来注册百度AI开放平台的开发者,并新建一个百度语音合成应用。
- 注册地址 https://passport.baidu.com/v2/?reg
- 快速集成指南 https://ai.baidu.com/ai-doc/SPEECH/jk38y8gno
- 配置文档 https://ai.baidu.com/ai-doc/SPEECH/Qk38y8lrl
- 调用流程示例 https://ai.baidu.com/ai-doc/SPEECH/0k38y8mfh
在线语音合成
- 调用流程示例
- 换取token
- 首先在您创建的应用中查找Api Key 和 SecretKey。访问https://openapi.baidu.com/oauth/2.0/token 换取 token
- 访问如下网址, 可用浏览器测试
// appKey = Va5yQRHl********LT0vuXV4
// appSecret = 0rDSjzQ20XUj5i********PQSzr5pVw2
https://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id=appKey4&client_secret=appSecret
- 可以获取如下结果
{
"access_token": "1.a6b7dbd428f731035f771b8d********.86400.1292922000-2346678-124328",
"expires_in": 2592000,
"refresh_token": "2.385d55f8615fdfd9edb7c4b********.604800.1293440400-2346678-124328",
"scope": "public audio_tts_post ...",
"session_key": "ANXxSNjwQDugf8615Onqeik********CdlLxn",
"session_secret": "248APxvxjCZ0VEC********aK4oZExMB",
}
- scope中含有audio_tts_post 表示有语音合成能力,没有该audio_tts_post 的token调用接口会返回502错误。
- 在结果中可以看见 token和expires_in:在2592000秒(30天)后过期。
访问合成接口
let access_token = 1.a6b7dbd428f731035f771b8d********.86400.1292922000-2346678-124328
// 这是一个正常MP3的下载url
// tex在实际开发过程中请urlencode2次
https://tsn.baidu.com/text2audio?per=0&tex=你好&lan=zh&cuid=1&ctp=1&spd=4&tok=access_token
百度语音合成demo
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>语音测试</title>
</head>
<body>
<div>
<input type="text" id="ttsText">
<input type="button" id="tts_btn" onclick="doTTS()" value="播放">
</div>
<div id="bdtts_div_id">
<audio id="tts_autio_id" autoplay="autoplay">
<source id="tts_source_id" src="http://tts.baidu.com/text2audio?lan=zh&ie=UTF-8&spd=9&text=播报内容" type="audio/mpeg">
<embed id="tts_embed_id" height="0" width="0" src="">
</audio>
</div>
</body>
<script type="text/javascript">
function doTTS(){
var ttsDiv = document.getElementById('bdtts_div_id');
var ttsAudio = document.getElementById('tts_autio_id');
var ttsText = document.getElementById('ttsText').value;
ttsDiv.removeChild(ttsAudio);
var au1 = '<audio id="tts_autio_id" autoplay="autoplay">';
/* tsn是正式版 */
var token = 24.04cdb49de323c86d4ed169965b4f6083.2592000.1639813589.282335-25190934
var sss = '<source id="tts_source_id" src="https://tsn.baidu.com/text2audio?per=0&tex='+ttsText+'&lan=zh&cuid=1&ctp=1&spd=4&tok=token" type="audio/mpeg">';
/* tts是测试版 */
/* var sss = '<source id="tts_source_id" src="https://tts.baidu.com/text2audio?cuid=baike&spd=4&lan=ZH&ctp=1&pdt=301&vol=4&rate=32&per=5&tex='+ttsText+'" type="audio/mpeg">';*/
/* var sss = '<source id="tts_source_id" src="http://tts.baidu.com/text2audio?lan=Zh&ie=UTF-8&spd=4&text='+ttsText+'" type="audio/mpeg">';*/
var eee = '<embed id="tts_embed_id" height="0" width="0" src="">';
var au2 = '</audio>';
ttsDiv.innerHTML = au1 + sss + eee + au2;
ttsAudio = document.getElementById('tts_autio_id');
ttsAudio.play();
}
</script>
</html>
Vue中实现百度语音播放demo
voicePlay.js 播报语音方法
export function voicePlay(word) {
let url = "https://tts.baidu.com/text2audio?cuid=baike&spd=5&lan=ZH&ctp=1&pdt=301&vol=4&rate=32&per=0&tex=' " + encodeURI(word);
let n = new Audio(url);
n.src = url;
n.play();//播放阅读
return n
}
语音播报的混入代码 ```javascript / 播报语音方法 / import {voicePlay} from “@/utils/voicePlay” / websocket实时推送接口 / import {cancelVoiceWordMessage,voiceWordMessage} from ‘@/api/socket’
export const voicePlayerMiXin = { data() { return{ isOpenPlay: false, // 浏览器是否开启了语音播报
voicePlayObj: null, // audio对象
voiceWord: '', // 当前语音播报内容
voiceType: '', // 当前播报语音的类型 0 事件,1 联勤
voiceWordNew: '', // 最新推送的播报内容
voicePlayState: false, // 播报状态
voiceWordIsShow: false, // 播报文字是否显示
isPlaying: false, // 语音是否正在播报
eventId: '', // 事件id
orderId: '',// 工单id
}
},
watch:{
'$store.state.connectStatus'() {
this.initVoicePlayerSub()
},
// 监听区域ID变化
'$store.state.region'() {
this.initVoicePlayerSub()
},
//平台实时播报的内容
'$store.state.voiceWord'() {
let data = this.$store.state.voiceWord
// 第一条数据来了之后,就开始播报,
if (!this.isPlaying && this.isOpenPlay) {
this.isPlaying = true
this.voiceWord = ''
this.voiceWordIsShow = false
this.voicePlayMethod(data)
}
},
},
mounted() {
this.initVoicePlayerSub();
},
methods: {
// 监听用户鼠标悬浮事件,启用音频播放 浏览器默认是不播放音频的 需要事件启动
openBrowserPlayVoice() {
if (!this.isOpenPlay) {
this.resetVoice()
this.isOpenPlay = !this.isOpenPlay
voicePlay('-')
}
},
// 初始化语音播报的websocket连接
initVoicePlayerSub() {
cancelVoiceWordMessage()
if (this.$store.state.connectStatus) {
// 实时播报内容
voiceWordMessage(this.$store.state.region.regionCode)
}
},
// 播报语音
voicePlayMethod(data) {
let that = this
// 如果没有开启语音播报,就返回
if (!that.isOpenPlay) {
that.resetVoice()
return
}
// 正在播报,就返回
if (that.voicePlayState) {
return
}
that.orderId = data.orderId
that.eventId = data.eventId
// 没有播报,就开始播报
if (!that.voicePlayState) {
// 存储当前播报的类型和内容
that.voiceType = data.tag
that.eventId = data.eventId
that.orderId = data.orderId
that.voiceWord = data.desc
// 显示播报弹窗
that.voiceWordIsShow = true
// 播报文字内容
that.voicePlayObj = voicePlay(that.voiceWord)
//当浏览器能够开始播放指定的音频/视频时,发生 canplay 事件。
that.voicePlayObj.addEventListener("canplay", function () {
that.voicePlayState = true
});
//当播放完一首歌曲时也会触发
that.voicePlayObj.addEventListener("ended", function () {
// 修改为当前没有语音播报
that.resetVoice()
})
}
},
resetVoice() {
// 修改为当前没有语音播报
this.voicePlayState = false
this.isPlaying = false // 播报完,设置为false
this.voiceWord = ''
this.voiceWordIsShow = false
},
// 点击语音播报,根据播报类型,跳转到新窗口 0 事件,1 联勤工单
jumpNewWindow() {
if (this.voiceType === 1) {
let routeNameStr = this.$route.path
// 根据当前路由名称是否为 /eventProcessing, 如果是联勤联动页面,就直接显示工单详情,如果不是就跳转到联勤联动页面
if(routeNameStr === '/eventProcessing') {
let orderId = this.orderId;
this.curOrderIdName = this.orderId;
if (orderId) {
manageInfo({orderId}).then(res => {
if (res.code == 0) {
this.dialogVisible = true;
this.$refs.workOrderDetails_.initDetailes();
}
})
}
} else {
this.$router.push({
name: 'eventProcessing',
params: {
orderId: this.orderId
}
});
}
return
}
if (this.voiceType === 0) {
this.$store.state.curClickEventId = this.eventId
let routeNameStr = this.$route.path
// 根据当前路由名称是否为 /eventCenter, 如果是事件中心,就调用这个方法this.clickEventItem(null)
if(routeNameStr === '/eventCenter') {
this.clickEventItem(null)
} else {
// 当前路由名称不是 /eventCenter, 就跳转到 事件中心,显示事件详情
this.$router.push({path: '/eventCenter'})
}
}
},
},
destroyed() {
this.voicePlayObj = null
/* 断开webscoket */
cancelVoiceWordMessage()
},
}
- 语音播报文字弹窗组件
```javascript
<template>
<div v-if="voiceWordIsShow" class="flex flex-center">
<div @click="jumpNewWindow" class="voiceWord flex flex-center"
style="z-index: 9999">
<i class="iconfont iconfont_"></i>
<span>{{voiceWord}}</span>
</div>
</div>
</template>
<script>
export default {
name: "voicePlay",
props: {
voiceWordIsShow: {
type: Boolean,
default: false
},
voiceWord: {
type: String,
default: ''
}
},
data() {
return {
}
},
methods: {
jumpNewWindow() {
this.$emit('jumpNewWindow')
}
}
}
</script>
<style lang="less" scoped>
.voiceWord {
position: absolute;
top: calc(var(--num88) * var(--num));
height: calc(var(--num40) * var(--num));
line-height: calc(var(--num40) * var(--num));
border-width: calc(var(--num1) * var(--num));
border-style: solid;
border-radius: calc(var(--num4) * var(--num));
border-color: @primary5;
background: @fill5;
}
.voiceWord span {
margin: 0 calc(var(--num18) * var(--num)) 0 calc(var(--num11) * var(--num));
font-size: calc(var(--num14) * var(--num));
}
.voiceWord i {
margin-left: calc(var(--num18) * var(--num));
}
.iconfont_ {
color: @yellow1 !important;
font-size: calc(var(--num22) * var(--num)) !important;
}
</style>
使用语音播报组件
<template>
<div @mouseover.stop="openBrowserPlayVoice" >
<!--语音播报组件-->
<voicePlayComp
@jumpNewWindow="jumpNewWindow"
:voiceWordIsShow="voiceWordIsShow"
:voiceWord="voiceWord"/>
</div>
</template>
<script>
import {voicePlayerMiXin} from '../../mixins/voicePlayerMiXin';
export default {
data() {
return{}
},
mixins:[ voicePlayerMiXin ],
mounted(){
},
methods:{
}
}
</script>