You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Azure Speech Service文本转语音时实现音频播放控制及按钮启停?

实现同一按钮控制播放/停止Azure Speech Service语音合成

核心思路

Azure Speech SDK的SpeechSynthesizer提供了stopSpeakingAsync方法来终止正在进行的语音合成与播放,我们只需要添加状态标记区分按钮的两种操作模式(播放/停止),并在合适时机更新状态即可。无需保存为WAV文件就能实现控制,如果有离线播放需求,也可以结合Audio元素控制已保存的音频文件。

修改后的完整代码

const speechConfig = SpeechSDK.SpeechConfig.fromSubscription("key", "region");
let synthesizer = null;
let isPlaying = false; // 标记当前是否正在播放

function initializeSynthesizer() {
    const audioConfig = SpeechSDK.AudioConfig.fromDefaultSpeakerOutput();
    synthesizer = new SpeechSDK.SpeechSynthesizer(speechConfig, audioConfig);
    
    synthesizer.synthesizing = (s, e) => {
        console.log(`Synthesizing: ${e.result.audioData.byteLength} bytes`);
    };

    // 合成完成或取消时重置播放状态
    synthesizer.synthesisCompleted = () => {
        isPlaying = false;
        updateButtonText();
    };

    synthesizer.synthesisCanceled = () => {
        isPlaying = false;
        updateButtonText();
    };
}

function convertTextToSpeech(text) {
    if (!synthesizer) {
        initializeSynthesizer();
    }

    isPlaying = true;
    updateButtonText();

    let selectedLanguage = TranslationModule.getSelectedLanguage();
    TranslationModule.translateText(text, selectedLanguage).then(translatedText => {
        synthesizer.speakTextAsync(
            translatedText,
            result => {
                if (result.reason === SpeechSDK.ResultReason.SynthesizingAudioCompleted) {
                    console.log("Speech synthesis completed.");
                } else {
                    console.error("Speech synthesis canceled, " + result.errorDetails);
                }
            },
            error => {
                console.error("Error during speech synthesis:", error);
                isPlaying = false;
                updateButtonText();
            }
        );

        console.log("Speech synthesis started:", text);
    }).catch(error => {
        console.error('Error translating text for speech:', error);
        isPlaying = false;
        updateButtonText();
    });
}

function stopSpeech() {
    if (synthesizer && isPlaying) {
        synthesizer.stopSpeakingAsync(
            () => {
                console.log("Speech stopped successfully.");
                isPlaying = false;
                updateButtonText();
            },
            error => {
                console.error("Error stopping speech:", error);
                isPlaying = false;
                updateButtonText();
            }
        );
    }
}

// 更新按钮显示文本,提升用户体验
function updateButtonText() {
    const btn = document.getElementById('btnread');
    btn.textContent = isPlaying ? '停止播放' : '朗读文本';
}

$(document).off('click').on('click', '#btnread', function () {
    let textToRead = this.getAttribute('data-text');
    if (isPlaying) {
        stopSpeech();
    } else {
        convertTextToSpeech(textToRead);
    }
});

关键修改点说明

  • 添加isPlaying状态变量:跟踪当前播放状态,决定按钮的点击行为。
  • 新增stopSpeech函数:封装SDK的stopSpeakingAsync方法,终止语音合成与播放并更新状态。
  • 状态重置逻辑:在合成完成、取消、出错时自动重置isPlaying,避免状态不一致。
  • 按钮文本更新:通过updateButtonText切换按钮显示文本,让用户清晰知晓当前操作。
  • 按钮点击事件逻辑:根据isPlaying状态判断执行播放还是停止操作。

关于保存WAV文件的控制方式

如果需要先保存合成音频为WAV文件再播放,可通过HTML5的Audio元素实现控制:

  • 合成时将audioConfig改为AudioConfig.fromAudioOutputBytesStream()获取音频数据,转为Blob后创建Audio对象。
  • 调用Audio对象的play()和pause()方法实现播放/停止,同时跟踪Audio的播放状态。
    但这种方式需要额外处理音频数据转换,原生SDK的stopSpeakingAsync方法更直接高效,无需保存文件。

内容的提问来源于stack exchange,提问作者Shivani Valaboju

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 11:50:09