Resuming a paused speech using speechSynthesis.resume() on chrome android doesn't work
Asked Answered
D

2

6

using the browser api speechSynthesis.resume() I'm trying to resume a paused speech on android chrome

I've tested the code below on chrome desktop version 78.0.3904.97 on mac os mojave and it resumes a speech without any problem after the speech is paused. But the same code can not resume a speech on android chrome version 77.x and 78.x

steps to reproduce

  1. run the code below
  2. press play to hear a speech
  3. pause the speech midway
  4. press resume
  5. speech is resumed on desktop chrome but not on android chrome

is this a bug in chrome?

<!DOCTYPE html>
<html>
  <head>
    <title>Parcel Sandbox</title>
    <meta charset="UTF-8" />
  </head>

  <body>
    <button id="play">Play</button>
    <button id="pause">Pause</button>
    <button id="resume">Resume</button>

    <div id="data"></div>

    <script>
      const play = document.getElementById("play");
      const pause = document.getElementById("pause");
      const resume = document.getElementById("resume");

      play.addEventListener("click", function() {
        document.getElementById("data").innerText = "play";
        var utterance = new SpeechSynthesisUtterance(
          "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15"
        );

        utterance.lang = "en-US";
        speechSynthesis.cancel();
        speechSynthesis.speak(utterance);
      });

      pause.addEventListener("click", function() {
        document.getElementById("data").innerText = "pause";
        speechSynthesis.pause();
      });
      
      resume.addEventListener("click", function() {
        document.getElementById("data").innerText = "resume";
        speechSynthesis.resume();
      });
    </script>
  </body>
</html>
Dannica answered 20/11, 2019 at 11:59 Comment(0)
F
7

Yes it's a bug: https://github.com/mdn/browser-compat-data/issues/4500

The status is fixed so maybe it'll work in a beta or development version, or Chronium.

As it stands, when you pause speechSynthesis its pause status is not updated and all further speak commands are put into the pending queue, giving the impression that speechSynthesis has stopped working altogether. Your code avoids this with the 'cancel' line before each 'speak' command.

Incidentally, do you want this code to work in Firefox?

EDIT: Hope you don't mind, I changed your code a bit and added a 'status' button to demonstrate this bug. The Status button shows the speaking, paused and pending status.

Click 'Play' then 'Status': speaking is true, paused is false and pending is false. Then click 'Pause' and 'Status'. In Windows speaking is true and paused true, with pending false. However in Andriod the statuses are true, false, false respectively. So resume cannot do anything because paused is false.

Thereafter, if you clicked 'Play' again the utterance just goes into the pending queue, so the statuses are true, false, true.

<!DOCTYPE html>
<html>
  <head>
    <title>Parcel Sandbox</title>
    <meta charset="UTF-8" />
  </head>

  <body>
    <button id="play">Play</button>
    <button id="pause">Pause</button>
    <button id="resume">Resume</button>
    <button id="status">Status</button>
    <button id="ssCancel">Cancel</button>

    <div id="data"></div>

    <script>
      const play = document.getElementById("play");
      const pause = document.getElementById("pause");
      const resume = document.getElementById("resume");
      const status = document.getElementById("status");
      const ssCancel = document.getElementById("ssCancel");
      const data = document.getElementById("data");

      play.addEventListener("click", () => {
        data.innerText = "play";
        var utterance = new SpeechSynthesisUtterance(
          "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15"
        );
        utterance.lang = "en-US";
        //speechSynthesis.cancel();
        speechSynthesis.speak(utterance);
      });

      pause.addEventListener("click", () => {
        data.innerText = 'pause';
        speechSynthesis.pause();
      });
      
      resume.addEventListener("click", () => {
        data.innerText = "resume";
        speechSynthesis.resume();
      });
      
      status.addEventListener('click', () => {
        data.innerText = `
          Speaking: ${speechSynthesis.speaking},
          Paused: ${speechSynthesis.paused},
          Pending: ${speechSynthesis.pending}.`;
      });
      
      ssCancel.addEventListener('click', () => {
          speechSynthesis.cancel();
      });
    </script>
  </body>
</html>

(To better show the bug I commented out your cancel line and added a separate cancel button)

Fatty answered 20/11, 2019 at 13:15 Comment(2)
just a note, the fix is to add a note on a documentation indicating that chrome has a bug on android. its not a fix for the actual bugDannica
The note: "In Android, pause() ends the current utterance. As such, pause() behaves just like cancel()".Lindahl
P
1

In fact the problem is that the status is not updated automatically by some browsers and the Mozilla website specifies that this is an experimental feature and that not all browsers support it, suggesting that we should also check how far this support goes, in the case of chromiun and its derivatives, the statement is only suspended, a brief solution for this is this:

var synth = window.speechSynthesis;
    var voice = new SpeechSynthesisUtterance('hello');
    var voices = speechSynthesis.getVoices();
   //Put this on the play button
    synth.resume();
    synth.speak(voice);

So, if there is something to be resumed, it returns from where it left off, otherwise, it starts, an if () is not necessary for this, the resume () function itself starts the statement, but if there is a failure, the speak function does its job, no error is generated.

Prau answered 3/10, 2020 at 10:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.