HTML5 SpeechSynthesis接口是语音服务的控制接口;它可以用于获取设备上关于可用的合成声音的信息,开始、暂停语音
以下是示例使用代码:
<template>
<el-row :gutter="16">
<el-col :span="12">
<el-form label-width="70px" class="form-speech">
<el-form-item label="播报文本">
<el-input v-model="state.code" type="textarea" rows="8" />
</el-form-item>
<el-form-item label="语言">
<el-select v-model="state.lang" @change="syncConfig" placeholder="请选择">
<el-option
v-for="item in langOptions"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="音调">
<el-slider v-model="state.pitch" @change="syncConfig" :min="0" :max="2" :step="1"></el-slider>
</el-form-item>
<el-form-item label="音速">
<el-slider v-model="state.rate" @change="syncConfig" :min="0.1" :max="10" :step="0.1"></el-slider>
</el-form-item>
<el-form-item label="音量">
<el-slider v-model="state.volume" @change="syncConfig" :min="0" :max="1" :step="0.1"></el-slider>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="addPlay">添加至待播</el-button>
</el-form-item>
</el-form>
</el-col>
<el-col :span="12">
<div class="list-playlist">
<div class="list-head">
<div><span>待播:</span><span style="color:#409EFF">{{ list.length }}</span></div>
<div><span>已播:</span><span style="color:green">{{ playlist.length - list.length }}</span></div>
</div>
<div class="list-body">
<div v-for="(item,i) in list" :key="i + item.code" class="list-item">{{ formatText(item.code) }}</div>
</div>
<div class="list-foot">
<el-button v-if="!speech" type="primary" @click="run">播放</el-button>
<el-button v-if="speech" type="default" @click="stop">停止</el-button>
<el-button v-if="speech && isSpeaking" type="default" @click="pause">暂停</el-button>
<el-button v-if="speech && isPaused" type="default" @click="resume">继续</el-button>
</div>
<div>
</el-col>
</el-row>
</div>
</template>
<script>
export default {
data () {
return {
speech: null,
state: {
code: '',
lang: '',
pitch: 1,
rate: 1,
volume: 1,
},
langOptions: [
{ label: '默认语言', value: '' },
{ label: '中文', value: 'zh' },
{ label: '英文', value: 'en' },
{ label: '法语', value: 'fr' },
{ label: '日语', value: 'ja' },
{ label: '德语', value: 'de' }
],
isSpeaking: false,
isPaused: false,
isStop: false,
playlist: [],
list: []
}
},
mounted() {
this.initView()
},
methods: {
// 初始化视图
initView() {},
// 添加至待播
addPlay () {
if (/^\s*$/.test(this.state.code)) {
this.$message({
message: '请输入播放文本',
type: 'warning'
})
return false
}
// 检查浏览器是否支持Web Speech API
if ('speechSynthesis' in window) {
let node = Object.assign({}, this.state)
this.playlist.push(node)
this.list.push(node)
} else {
this.$message({
message: '浏览器不支持语音播报',
type: 'warning'
})
console.error('浏览器不支持Web Speech API');
}
},
// 开始播放
run () {
if (!this.list[0]) {
this.$message({
message: '请添加播放文本',
type: 'warning'
})
return false
}
// 检查浏览器是否支持Web Speech API
if ('speechSynthesis' in window) {
this.isStop = false
this.play()
} else {
this.$message({
message: '浏览器不支持语音播报',
type: 'warning'
})
console.error('浏览器不支持Web Speech API');
}
},
// 播放
play () {
// 清空未播放完的
speechSynthesis.cancel()
// 创建一个新的SpeechSynthesisUtterance对象
let text = this.list[0].code
let speech = new SpeechSynthesisUtterance(text)
speech.text = text //文字
this.speech = speech
this.syncConfig(this.state)
this.bindEvents()
speechSynthesis.speak(speech) //播放语音
},
// 播放下一个
playNext () {
this.list.shift()
if (!this.list[0]) {
return false
}
this.play()
},
// 同步配置
syncConfig (options) {
let speech = this.speech
if (!speech) {
return true
}
if (options.lang) {
speech.lang = options.lang
}
speech.pitch = options.pitch // 语速
speech.rate = options.rate // 语速
speech.volume = options.volume // 音量
},
// 事件绑定
bindEvents () {
let speech = this.speech
if (!speech) {
return true
}
// 开始语音播放时触发
speech.addEventListener('start', () => {
this.isSpeaking = true
this.isPaused = false
})
// 暂停语音播放时触发
speech.addEventListener('pause', () => {
this.isSpeaking = false
this.isPaused = true
})
// 恢复语音播放时触发
speech.addEventListener('resume', () => {
this.isSpeaking = true
this.isPaused = false
})
// 语音播放结束时触发
speech.addEventListener('end', () => {
this.speech = null
this.isSpeaking = false
if (this.isStop || this.isPaused) {
this.isPaused = false
return true
}
this.isPaused = false
// 播放下一个
this.playNext()
})
// 语音播放错误时触发
speech.addEventListener('error', () => {
this.speech = null
this.isSpeaking = false
this.isPaused = false
})
},
// 停止播放
stop () {
let speech = this.speech
if (!speech) {
return true
}
speechSynthesis.cancel()
this.isStop = true
this.speech = null
},
// 暂停播放
pause () {
let speech = this.speech
if (!speech) {
return true
}
speechSynthesis.pause()
},
// 继续播放
resume () {
let speech = this.speech
if (!speech) {
return true
}
speechSynthesis.resume()
},
// 文本格式化
formatText (value) {
let len = value.length
return value.slice(0, 20) + (len > 20 ? '...' : '')
}
}
}
</script>
<style scoped>
.list-playlist {
.list-head {
display: flex;
justify-content: space-between;
font-weight: 700;
}
.list-body {
overflow: auto;
padding: 8px;
max-height: 240px;
}
}
</style>
低配置云服务器,首次加载速度较慢,请耐心等候
预览页面:http://www.daelui.com/#/tigerlair/saas/preview/lvakef63u84k
演练页面:http://www.daelui.com/#/tigerlair/saas/practice/lvakef63u84k