Skip to content

Commit

Permalink
keep the SpeechSynthesis engine active for Chromebooks, see phetsims/…
Browse files Browse the repository at this point in the history
  • Loading branch information
jessegreenberg committed Feb 7, 2022
1 parent 407f2b7 commit c543352
Showing 1 changed file with 23 additions and 0 deletions.
23 changes: 23 additions & 0 deletions js/accessibility/voicing/voicingManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ import KeyboardUtils from '../KeyboardUtils.js';

const DEFAULT_PRIORITY = 1;

// In seconds, how frequently we will use SpeechSynthesis to keep the feature active. After long intervals without
// using SpeechSynthesis Chromebooks will take a long time to produce the next speech. Presumably it is disabling
// the feature as an optimization. But this workaround gets around it and keeps speech fast.
const ENGINE_WAKE_INTERVAL = 10;

const UTTERANCE_OPTION_DEFAULTS = {

// {boolean} - If true and this Utterance is currently being spoken by the speech synth, announcing it
Expand Down Expand Up @@ -73,6 +78,10 @@ class VoicingManager extends Announcer {
// first request for speech.
this.hasSpoken = false;

// @private {number} - In seconds, how long to go before "waking the SpeechSynthesis" engine to keep speech
// fast on Chromebooks, see documentation around ENGINE_WAKE_INTERVAL.
this.timeSinceWakingEngine = 0;

// @public {Emitter} - emits events when the speaker starts/stops speaking, with the Utterance that is
// either starting or stopping
this.startSpeakingEmitter = new Emitter( { parameters: [ { valueType: 'string' }, { valueType: Utterance } ] } );
Expand Down Expand Up @@ -248,6 +257,9 @@ class VoicingManager extends Announcer {
this.speakingProperty.set( true );
synth.speak( voicingQueueElement.speechSynthUtterance );

// We have just used speech synthesis, wait until ENGINE_WAKE_INTERVAL to apply the workaround again
this.timeSinceWakingEngine = 0;

this.assertSpeakingPropertyInSync();
}

Expand Down Expand Up @@ -298,6 +310,17 @@ class VoicingManager extends Announcer {
if ( !this.getSynth().speaking && this.voicingQueue.length === 0 && this.safariWorkaroundUtterances.length > 0 ) {
this.safariWorkaroundUtterances = [];
}

// A workaround to keep SpeechSynthesis responsive on Chromebooks. If there is a long enough interval between
// speech requests, the next time SpeechSynthesis is used it is very slow on Chromebook. We think the browser
// turns "off" the synthesis engine for performance. If it has been long enough since using speech synthesis and
// there is nothing to speak in the queue, requesting speech with empty content keeps the engine active.
// See https://github.com/phetsims/gravity-force-lab-basics/issues/303.
this.timeSinceWakingEngine += dt;
if ( !this.speakingProperty.value && this.voicingQueue.length === 0 && this.timeSinceWakingEngine > ENGINE_WAKE_INTERVAL ) {
this.timeSinceWakingEngine = 0;
this.getSynth().speak( new SpeechSynthesisUtterance( '' ) );
}
}
}

Expand Down

0 comments on commit c543352

Please sign in to comment.