Applets feature
- Text-to-speech
- Multi-platform multi-pronunciator optional
- Adjustable speed
- Audio downloads are available
- Conscience products without advertising 😆
Small program code
The online voice recognition service has been connected
- Spitzer DUI platform (over 40 free speakers)
- Iflytek Open Platform (5 free speakers)
- Baidu Voice (4 free speakers optional)
Applet screenshot
Server main code
class TTSController extends Controller {
async tts () {
let params = this.ctx.query
letResult = null // Call different interfaces based on plAT parametersif (params.plat === 'xf') {
result = await this.ctx.service.xftts.getTts(params)
} else if (params.plat === 'baidu') {
result = await this.ctx.service.baidutts.getTts(params)
} else{result = await this. CTX. Service. Aispeechtts. GetTts (params)} / / set the type of the response, The client receives a file stream this.ctx.response.type ='audio/mpeg'
this.ctx.body = result
}
}
Copy the code
Applet client Template code (using MPvue)
<template>
<div class="container">
<div class="preview">
<textarea :class="textAreaFocus? 'focus' : ''"
auto-height @focus="bindTextAreaFocus"
@blur="bindTextAreaBlur" placeholder="Please enter text"
v-model="text" maxlength="256"/>
</div>
<div class="setting">
<picker @change="bindPlatChange" v-model="platIndex" range-key="name" :range="platArr">
<div class="item">
<div class="label"> Select platform </div> <div class="value voice">
{{platArr[platIndex].name}}
</div>
</div>
</picker>
<picker @change="bindPickerChange" v-model="index" range-key="name" :range="array">
<div class="item">
<div class="label"> select the speaker </div> <div class="value voice">
{{array[index].name}}
</div>
</div>
</picker>
<div class="item speed">
<div class="label"<div > <div class="value">
<slider @change="onSpeedChange" :value="speedObj.default" :step='speedObj.step' activeColor="#6F8FFF" :min="speedObj.min" :max="speedObj.max" show-value />
</div>
</div>
</div>
<div style="height: 140rpx;">
<div class="btn-group">
<div class="item"><button @click="audioPlay" type="main"</button> </div> <div class="item"> <button @click="audioDownload" type="submain"</button> </div> </div> <div class="desc"< span style = "max-width: 100%; clear: both; min-height: 1emtype="default-light"
session-from="weapp"</ contacts-button > </div> </div> </template>Copy the code
The script code
<script>
import voiceIdArray from './voiceIdArray'
export default {
data () {
return {
array: voiceIdArray.aispeech,
platArr: [{id: 'xf', name: IFlytek}, {id: 'aispeech', name: Spitz}, {id: 'baidu', name: "Baidu"}], platIndex: 1, index: 26, text: 'Reform breeze blows everywhere, breeze blows everywhere, spring breeze blows everywhere. \n The Chinese people are true to their spirit, true to their spirit, true to their spirit. \n It's such a crazy world that rats serve cats as bridesmaids. \n Qi Delong, Qi Dongqiang. \n Chidelong's Dong Delong Dong Qiang. `, voiceId:'lili1f_diantai',
speed: 1,
textAreaFocus: false,
audioCtx: null,
ttsServer: 'https://tts.server.com',
audioSrc: ' ',
downloadUrl: ' ', xfSpeedObj: {min: 0, Max: 100, default: 50, step: 1}, aispeechSpeedObj: {min: 0.7, Max: 2, default: 1, step: 0.1}, baiduSpeedObj: {min: 0, Max: 9, default: 5, step: 1}, speedObj: {}}, watch: {platIndex (newVal, oldVal) {if (newVal === 2) {
this.array = voiceIdArray.baidu
this.index = 0
this.speedObj = this.baiduSpeedObj
}
if (newVal === 1) {
this.array = voiceIdArray.aispeech
this.index = 26
this.speedObj = this.aispeechSpeedObj
}
if (newVal === 0) {
this.array = voiceIdArray.xf
this.index = 0
this.speedObj = this.xfSpeedObj
}
}
},
onShareAppMessage () {
return {
title: 'Text-to-speech service, optional for multiple pronunciators'
}
},
methods: {
onSpeedChange (e) {
this.speedObj.default = e.target.value
},
bindPlatChange (e) {
this.platIndex = e.target.value * 1
},
bindPickerChange (e) {
this.index = e.target.value
},
getAudioSrc () {
if (this.text === ' ') {
return false
}
const speed = this.speedObj.default
const voiceId = this.array[this.index].id
const plat = this.platArr[this.platIndex].id
return encodeURI(`${this.ttsServer}/tts? plat=${plat}&voiceId=${voiceId}&speed=${speed}&text=${this.text}`)},getDownloadUrl () {
const plat = this.platArr[this.platIndex].id
const voiceId = this.array[this.index].id
wx.showLoading({
title: 'Loading'
})
wx.request({
url: 'https://tts.server.com/getdownloadurl',
data: {
plat: plat,
voiceId: voiceId,
speed: this.speedObj.default,
text: this.text
},
header: {
'content-type': 'application/json'// Default value}, success (res) {wx.hideloading () wx.setclipboardData ({data: res.data.short_url, success (res) { wx.showToast({ title:'Link has been copied, please download it with your browser (not available on ios)',
icon: 'none',
duration: 3000
})
}
})
}
})
},
audioPlay () {
this.audioCtx.src = this.getAudioSrc()
if(! this.audioCtx.src) { wx.showToast({ title:'Please enter text first',
icon: 'none',
duration: 2000
})
return false
}
wx.showLoading({
title: 'Loading'
})
this.audioCtx.play()
},
audioDownload () {
this.getDownloadUrl()
},
bindTextAreaBlur (e) {
this.textAreaFocus = false
this.text = e.target.value
},
bindTextAreaFocus () {
this.textAreaFocus = true}},created () {
this.speedObj = this.aispeechSpeedObj
},
mounted () {
this.audioCtx = wx.createInnerAudioContext()
this.audioCtx.onEnded((res) => {
wx.hideLoading()
})
this.audioCtx.onPlay((res) => {
wx.hideLoading()
})
wx.showShareMenu({
withShareTicket: true
})
}
}
</script>
Copy the code
In the process of interface docking, Baidu’s is the most convenient because it can be used directly with SDK, while Iflytek’s is the most troublesome and requires to do parameter encryption by itself. Although Spitz duI does not provide SDK, the document is written in detail and the docking process is convenient and fast.
One thing that can’t be fixed is the fact that you can’t download the app directly inside the app, only provide a link, and then the user can open a browser to download it (iPhone seems to have no solution).