简体   繁体   中英

In my Google Action, how do I efficiently conclude play of one MP3 and “skip” to another MP3 using a single user utterance?

I have a one-scene Action that calls my webhook ' randomSpeech ' (mentioned below) upon invocation, which plays an MP3. I added a "skip" intent to skip to the next MP3. When I say "skip", the Action should transition (loop) back into the webhook ' randomSpeech ', and since there is a counter, x , the Action should begin playing the 2nd MP3 in the switch statement.

However, I have to say the word "skip" twice in order for it to work.

  1. The 1st time I say "skip", the system intent, MEDIA_STATUS_FINISHED automatically calls the ' mediaStatus ' handler and the text 'Media has finished.' is added to the conversation. Even though I've configured the "skip" intent to call the handler, 'randomSpeech' , it doesn't appear to happen as no new Media is added to the conversation. It's almost like ' randomSpeech ', is completely ignored!
  2. The 2nd time I say "skip", the second MP3 finally begins playing.

My main question is, how can I make it so the user only has to say "skip" one time?


let x = 1;

app.handle('randomSpeech', (conv) => {

  switch(x) {
    case(1):
      conv.add(new Media({
      mediaObjects: [
        {
          name: 'NEVER GIVE UP',
          description: 'some athlete',
          url: 'http://zetapad.com/speeches/nevergiveup.mp3',
          image: {
            large: {
              url: 'https://www.keepinspiring.me/wp-content/uploads/2020/02/motivation-gets-you-started-jim-ryun-quote-min.jpg'
            }
          }
        }
      ],
      mediaType: 'AUDIO',
      optionalMediaControls: ['PAUSED', 'STOPPED'],
      startOffset: '5s'   
      }));
    x++;
    break;

    case(2):
      conv.add(new Media({
        mediaObjects: [
          {
            name: 'SPEECHLESS',
            description: 'Denzel Washington (feat Will Smith)',
            url: 'http://zetapad.com/speeches/denzel.mp3',
            image: {
              large: {
              url: 'https://www.keepinspiring.me/wp-content/uploads/2020/02/motivational-quotes-2-min.jpg'
              }
            }
          }
        ],
        mediaType: 'AUDIO',
        optionalMediaControls: ['PAUSED', 'STOPPED']
      }));   
    break;
  }
});


app.handle('media_status', (conv) => {
  const mediaStatus = conv.intent.params.MEDIA_STATUS.resolved;
  switch(mediaStatus) {
    case 'FINISHED':
      conv.add('Media has finished.');
      break;
    case 'FAILED':
      conv.add('Media has failed.');
      break;
    case 'PAUSED' || 'STOPPED':
      if (conv.request.context) {
        // Persist the media progress value
        const progress = conv.request.context.media.progress;
      }
      conv.add(new Media({
        mediaType: 'MEDIA_STATUS_ACK'
        }));
      break;
    default:
      conv.add('Unknown media status received.');
  }
});


Images from the only scene, "Motivation":

Scene

On enter

Intent handling


Further notes:

  • MEDIA_STATUS_PAUSED / MEDIA_STATUS_FINISHED / MEDIA_STATUS_STOPPED all only call the ' media_status ' wehbook

The issue at the heart of your question is that "skip" is a built-in Media Player command (although this is not clearly documented ), so when the user says "skip", the player treats this as the audio being completed , so it sends the MEDIA_STATUS_FINISHED Intent, just as it the user listened to it all the way through.

The good news is - you actually want to handle both these cases the same way, So if the user skips to the next audio. or finishes the first and it should advance to the next audio - you want to play the next audio.

In your code, "playing the next audio" is all done as part of your switch statement. So you should probably put that into a regular JavaScript function by itself. You can then call that function from the different handlers that you have setup.

It might look something like this (without some of the code details):


function nextAudio( conv ){
  // Code goes here to figure out the next audio to play and send it back
}

app.handle('randomSpeech', (conv) => {
  nextAudio( conv );
}

app.handle('media_status', (conv) => {
  const mediaStatus = conv.intent.params.MEDIA_STATUS.resolved;
  switch(mediaStatus) {
    case 'FINISHED':
      nextAudio( conv );
      break;
    // Other media status cases can go here
  }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM