Interface for speech synthesis in the browser
/** | |
* @typedef SpeakerDefaults | |
* @type {object} | |
* @property {string} voiceURI voice that the browser uses | |
* @property {Number} volume loudness. Between 0 and 1.0 | |
* @property {Number} rate speed at which words are spoken. Between 0 and 2. | |
* @property {Number} pitch Between 0 and 2 | |
* @property {string} lang ISO language | |
*/ | |
const SpeakerDefaults = { | |
voiceURI: 'native', | |
volume: .4, | |
rate: 0.8, | |
pitch: 0.0, | |
lang: 'en-EN' | |
}; | |
/** | |
* Class for getting the browser to "talk" | |
* @example //Create an instance | |
* const mySpeaker = new Speaker(); | |
* @example //Get it to talk | |
* mySpeaker.say('something sooper cool'); | |
*/ | |
class Speaker { | |
/** Create an interface for the browser to speak | |
* @param {SpeakerDefaults} defaults=SpeakerDefaults | |
* @param {string} defaults.voiceURI | |
* @param {Number} defaults.volume loudness. Between 0 and 1.0 | |
* @param {Number} defaults.rate speed at which words are spoken. Between 0 and 2. | |
* @param {Number} defaults.pitch Between 0 and 2 | |
* @param {string} defaults.lang ISO language | |
* | |
*/ | |
constructor(defaults = SpeakerDefaults) { | |
this.defaults = Object.assign({},defaults); // make a copy of the defaults | |
Object.freeze(this.defaults); // freeze the defaults; that way we can return to them at any time | |
this.config = defaults; | |
this.messageHistory = []; | |
} | |
/** | |
* Creates a new SpeechSynthesisUtterance | |
* @return SpeechSynthesisUtterance | |
*/ | |
utterance() { | |
const speech = new SpeechSynthesisUtterance(); | |
speech.voiceURI = this.config.voiceURI; | |
speech.volume = this.config.volume; | |
speech.rate = this.config.rate; | |
speech.pitch = this.config.pitch; | |
speech.lang = this.config.lang; | |
return speech; | |
} | |
utteranceHistory(utterance) { | |
const obj = { | |
timestamp: Date.now() | |
}; | |
// screwy object aliasing | |
({ | |
text: obj.text, | |
rate: obj.rate, | |
pitch: obj.pitch, | |
lang: obj.lang, | |
volume: obj.volume, | |
voiceURI: obj.voiceURI | |
} = utterance); | |
return obj; | |
} | |
get eventCallbacks() { | |
return { | |
/** records a history of the utterance once it's ended | |
* @callback Speaker~utterance | |
* @param {} event | |
*/ | |
onend(event) { | |
const history = this.utteranceHistory(event.utterance); | |
this.messageHistory.push(history); | |
console.log(this.messageHistory); | |
console.log('finished in ' + event.elapsedTime); | |
} | |
}; | |
} | |
/** Instructs the browser to speak a message | |
* @param {string} msg | |
*/ | |
say(msg) { | |
const speech = this.utterance(); | |
speech.text = msg; | |
speech.onend = this.eventCallbacks.onend.bind(this); | |
speechSynthesis.speak(speech); | |
} | |
/** | |
* Determine if the browser is currently speaking | |
* @return {boolean} | |
*/ | |
get isSpeaking() { | |
return speechSynthesis.speaking; | |
} | |
/** | |
* Pause the browser | |
*/ | |
pause() { | |
speechSynthesis.pause(); | |
} | |
/** | |
* Tell the browser to start speaking | |
*/ | |
play() { | |
speechSynthesis.play() | |
} | |
/** | |
* Toggle speech | |
*/ | |
toggle() { | |
if (!speechSynthesis.speaking) { | |
this.play(); | |
} else { | |
this.pause(); | |
} | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment