Skip to content
vue
<script setup>
    import {ref} from "vue";
    import {ElMessage} from 'element-plus';

    let text = ref('');     // 待播报内容
    let speech = ref();     // 语音合成实例
    let voices = ref();
    let voice = ref();

    // 开始播报
    function speak() {
        if (!text.value) {
            ElMessage.warning('请输入一些文本');
            return;
        }

        // 创建新的语音实例并设置属性
        const utterance = new SpeechSynthesisUtterance(text.value);
        utterance.lang = 'zh-CN';   // 设置语言为中文
        utterance.volume = 1;       // 设置音量
        utterance.rate = 1;         // 设置语速
        utterance.pitch = 1;        // 设置音高
        utterance.voice = voices.value[voice.value];    // 设置音色

        // 开始语音播报
        window.speechSynthesis.speak(utterance);
        speech.value = utterance;
    }


    function handleVoicesChanged() {
        voices.value = window.speechSynthesis.getVoices().filter(e => e.lang === 'zh-CN');
        voice.value = 0;
    }

    // 注册事件监听(关键)
    window.speechSynthesis.onvoiceschanged = handleVoicesChanged;

    // 主动触发一次(部分浏览器需要“唤醒”语音加载)
    window.speechSynthesis.getVoices();

    // 暂停播放
    function pause() {
        if (speech.value) {
            window.speechSynthesis.pause();
        } else {
            ElMessage.warning('没有正在进行的播报!');
        }
    }

    // 继续播放
    function resume() {
        if (speech.value) {
            window.speechSynthesis.resume();
        } else {
            ElMessage.warning('没有正在进行的播报!');
        }
    }

    // 结束播放
    function stop() {
        if (speech.value) {
            window.speechSynthesis.cancel();
            speech.value = null;
            text.value = null;
        } else {
            ElMessage.warning('没有正在进行的播报!');
        }
    }
</script>

<template>
    <el-row :gutter="20">
        <el-col :span="12">
            <el-select v-model="voice">
                <el-option v-for="(item, index) in voices" :key="index" :label="item.name" :value="index" />
            </el-select>
        </el-col>
        <el-col :span="12">
            <el-input v-model="text" placeholder="请输入播报内容" />
        </el-col>
    </el-row>

    <el-button type="primary" @click="speak">开始播报</el-button>
    <el-button type="primary" @click="pause">暂停播放</el-button>
    <el-button type="primary" @click="resume">继续播放</el-button>
    <el-button type="primary" @click="stop">结束播放</el-button>
</template>

<style scoped>
    .el-input {
        margin-bottom: 30px;
    }
</style>
vue
<template>
    <div>
        <h1>离线语音播报</h1>
        <input v-model="textToSpeak" placeholder="输入文本"/>
        <button @click="speak">播报</button>
    </div>
</template>

<script>
export default {
    data() {
        return {
            textToSpeak: '', // 用户输入的文本
            speech: null // 语音合成实例
        };
    },
    methods: {
        speak() {
            // 检查是否有文本输入
            if (!this.textToSpeak) {
                alert('请输入一些文本!');
                return;
            }

            // 创建新的语音实例并设置属性
            const utterance = new SpeechSynthesisUtterance(this.textToSpeak);
            utterance.lang = 'zh-CN'; // 设置语言为中文
            utterance.volume = 1; // 设置音量
            utterance.rate = 1; // 设置语速
            utterance.pitch = 1; // 设置音高

            // 开始语音播报
            window.speechSynthesis.speak(utterance);
            this.speech = utterance; // 保存引用以便之后可以暂停或停止播报
        },
        pause() {
            if (this.speech) {
                window.speechSynthesis.pause(); // 暂停当前播报
            } else {
                alert('没有正在进行的播报!');
            }
        },
        resume() {
            if (this.speech) {
                window.speechSynthesis.resume(); // 恢复当前播报
            } else {
                alert('没有正在进行的播报!');
            }
        },
        stop() {
            if (this.speech) {
                window.speechSynthesis.cancel(); // 停止当前播报并清除引用
                this.speech = null;
            } else {
                alert('没有正在进行的播报!');
            }
        }
    }
};
</script>

基于 MIT 许可发布