Sara Ree
Sara Ree

Reputation: 3543

Run a function inside of another function based on some situation

I want to create a function to combine natural human recorded voice with speech synthesis in a very simple way, here is the code:

function speak(text, type){

   switch(type){
    
    case 'answer':
    
    // Initiate Speech Synthesis
    speech('This is the Answer');

    // After Speech Synthesis has finished
    playVoice('voice_1.mp3');

    break;

   }

}


function speech(input){

  // Fetch the available voices.
  const voice = speechSynthesis.getVoices().filter(voice => voice.lang == 'en-US'); 
  
  var msg = new SpeechSynthesisUtterance();
  msg.voice = voice[0];

  // Set the text.
  msg.text = input;

  // Queue this utterance.
  window.speechSynthesis.speak(msg);
  
  // Track if Speech Synthesis has finished
  msg.onend = function(event) {
  console.log('Speech has finished being spoken after ' + event.elapsedTime + ' milliseconds.');
  }

}

So I want to run speech synthesis then after Speech Synthesis has finished in speech function, I want to play audio that is in speak function here:

// After Speech Synthesis has finished
playVoice('voice_1.mp3');

Guys, please tell me if there is any solution to do this that I'm missing?

What would you do if you were me?

Note: I want many different behaviors from speak function and it makes it confusing how I want to deal with my issue:

    function speak(text, type){

       switch(type){

        case 'answer':

        // Initiate Speech Synthesis
        speech('This is the Answer');

        // After Speech Synthesis has finished
        playVoice('voice_1.mp3');

        break;

        case 'question':

        // Play an specific voice
        playVoice('voice_2.mp3');

        // Then Talk the text
        speech('This is the Question');

        // After Speech Synthesis has finished
        playVoice('voice_3.mp3');

        break;

       }
}

Upvotes: 1

Views: 100

Answers (2)

Sara Ree
Sara Ree

Reputation: 3543

This is what I wanted! After Start appears you have 2 seconds to click on anywhere on the page to play the speech synthesis...

console.log('Start')

setTimeout(function(){
  
let promise;
  
speak('this is a text', 'answer');
  
function speak(text, type){

   switch(type){
    
    case 'answer':
    
    // Initiate Speech Synthesis
    speech('This is the Answer');
    // After Speech Synthesis has finished
    onSpeechEnd()

    break;
       
    case 'question':

    // Play an specific voice
     playVoice('voice_2.mp3');

    // Then Talk the text
     speech('This is the Question');  

   }
  
  
   async function onSpeechEnd() {
 
      let result = await promise;
      playVoice(result)
    
   }
  
} 
   // Function
  function speech(input){
    
  // Fetch the available voices.
  const voice = speechSynthesis.getVoices().filter(voice => voice.lang == 'en-US'); 
  
  var msg = new SpeechSynthesisUtterance();
  msg.voice = voice[0];

  // Set the text.
  msg.text = input;

  // Queue this utterance.
  window.speechSynthesis.speak(msg);
  
  // Track if Speech Synthesis has finished
  promise = new Promise((resolve, reject) => {
  msg.onend = function(event) {
  console.log('Speech has finished being spoken');
  resolve('voice_1.mp3');
  }
      
  });
       
  }
                      
},2000)

function playVoice(voice){
  console.log(voice)
}

Upvotes: 0

AuRise
AuRise

Reputation: 2452

Can you pass the mp3's filename to the "speech" function as a parameter, and call it on the "onend" function? Like this?

function speak(text, type){

    switch(type){

        case 'answer':

            // Initiate Speech Synthesis & voice to play when done
            speech('This is the Answer', 'voice_1.mp3');

            break;

        case 'question':

            // Play an specific voice
            playVoice('voice_2.mp3');

            // Then Talk the text & voice to play when done
            speech('This is the Question', 'voice_3.mp3');

            break;

    }
}


function speech(input,voiceToPlay){

    // Fetch the available voices.
    const voice = speechSynthesis.getVoices().filter(voice => voice.lang == 'en-US'); 

    var msg = new SpeechSynthesisUtterance();
    msg.voice = voice[0];

    // Set the text.
    msg.text = input;

    // Queue this utterance.
    window.speechSynthesis.speak(msg);

    // After Speech Synthesis has finished
    msg.onend = function(event) {
        console.log('Speech has finished being spoken after ' + event.elapsedTime + ' milliseconds.');
        if(voiceToPlay) {
            console.log('Play voice.');
            playVoice(voiceToPlay);
        }
    }

}

As for the question's case, where you have an mp3 file playing before and after your speech synthesis, I'd consider something along the lines of this to check what the duration of what the mp3 file is, and then use setTimeout for that length of time before executing the speech() function. I'm sure you can write a function that takes the audio file's path that you're passing to the "speech" function, do a look-up, and then return the duration in ms in a variable.

Here's a pen I forked from yours.

Upvotes: 1

Related Questions