0

我正在使用文本到语音服务 (TTS) 从 Yelp API 读取结果。我遇到了时间问题:

  1. 如果我太快调用 TTS 函数,语音会自行中断。

我的想法是编写一个信号量来检查音频是否正在播放,并且只有在完成后才将下一个命令变为红色。很遗憾:

  1. 如果我等到音频没有播放(audio.paused == true),程序挂起/不会跳出while循环。

有没有人对如何解决第一个问题而不遇到第二个问题有任何想法?

//check if command isn't already queued, and then add command to the queue
function voiceSynth (string, name) { 
if(voiceQueue.indexOf(string)== -1){
    voiceQueue.push(string) 
    voiceQueue.push(name) //used to keep track of the current item being read
}       
//Iterate over items in the queue
while (voiceQueue.length > 1){
    if (voiceBusy == false && audio.paused == true) {   
        voiceCall.call(undefined, voiceQueue.shift(),voiceQueue.shift())
    }
    }
}
//ajax call to the TTS service
function voiceCall (string, name) {
    voiceBusy = true
    console.log('synth called on ' + string)
    $.ajax('read/?string=' + string + '&speed=' + speed, {
        type: 'GET',
        success: function(src) {
            audio.setAttribute('src', src)  
            audio.play()
            voiceBusy = false
            voiceCursor = name  
        },
        error: function(xhr, ajaxOptions, thrownError) {
            console.log(xhr)
            console.log(ajaxOptions)
            console.log(thrownError)
            }
    })
    }
4

1 回答 1

3

信号量用于多线程/IPC 环境。使用 javascript 引擎,您没有这个。您正在尝试在 Javascript 中进行轮询,这在其单线程环境中不起作用,除非您使用 setTimeout 或 setInteval。

在您的设置中,您似乎有三种类型的事件:一个新的语音任务出现(并且应该被排队),一个 Yelp AJAX 调用返回,以及音频播放结束。您似乎已经处理了前两个事件,并且您正试图弄清楚如何处理音频结束事件。

我会将所有队列服务代码移动到它自己的函数中,然后只要发生有趣的事件就调用它。让队列服务代码弄清楚要做什么。其余代码只需要处理事件并跟踪状态。像这样的东西可能会起作用:

    var ajaxOutstanding = false;
    var audioOutstanding = false;

    function voiceSynth(string, name) {
       if(voiceQueue.indexOf(string)== -1){
          voiceQueue.push(string) 
          voiceQueue.push(name) //used to keep track of the current item being read
       }
       serviceQueue();
    }

    //ajax call to the TTS service
    function voiceCall (string, name) {
        console.log('synth called on ' + string)
        $.ajax('read/?string=' + string + '&speed=' + speed, {
            type: 'GET',
            success: function(src) {
                ajaxOutstanding = false;
                audio.setAttribute('src', src);
                audioOutstanding = true;
                audio.play();
                voiceCursor = name;
                serviceQueue();
            },
            error: function(xhr, ajaxOptions, thrownError) {
                ajaxOutstanding = false;
                console.log(xhr);
                console.log(ajaxOptions);
                console.log(thrownError);
                serviceQueue();
            }
        });
    }

    function handleAudioEnded() {
        audioOutstanding = false;
        serviceQueue();
    }

    audio.addEventListener('ended', handleAudioEnded);

    function serviceQueue() {
        if (voiceQueue.length > 1 && !ajaxOustanding && !audioOutstanding) {
        voiceCall.call(undefined, voiceQueue.shift(),voiceQueue.shift());
        }
    }

顺便一提,

    voiceCall.call(undefined, voiceQueue.shift(),voiceQueue.shift());

是相同的

    voiceCall(voiceQueue.shift(), voiceQueue.shift());

并且更清晰。

于 2013-02-08T21:14:11.173 回答