Skip to content

Instantly share code, notes, and snippets.

@anchetaWern
Created May 16, 2015 09:44
Show Gist options
  • Save anchetaWern/ed6e841555602656e6ae to your computer and use it in GitHub Desktop.
Save anchetaWern/ed6e841555602656e6ae to your computer and use it in GitHub Desktop.
responsive-voice.js
//Look for other responsivevoice instances
/*if (window.parent != null) {
var iframes = window.parent.document.getElementsByTagName('iframe');
for (var i = 0; i < iframes.length; i++) {
//iframes[i].style.width = "300px"
}
}*/
if (typeof responsiveVoice != 'undefined') {
console.log('ResponsiveVoice already loaded');
console.log(responsiveVoice);
} else {
var ResponsiveVoice = function () {
var self = this;
self.version = 3;
console.log("ResponsiveVoice r" + self.version);
// Our own collection of voices
var responsivevoices = [
{name: 'UK English Female', voiceIDs: [3, 5, 1, 6, 7, 8]},
{name: 'UK English Male', voiceIDs: [0, 4, 2, 6, 7, 8]},
{name: 'US English Female', voiceIDs: [39, 40, 41, 42, 43, 44]},
{name: 'Spanish Female', voiceIDs: [19, 16, 17, 18, 20, 15]},
{name: 'French Female', voiceIDs: [21, 22, 23, 26]},
{name: 'Deutsch Female', voiceIDs: [27, 28, 29, 30, 31, 32]},
{name: 'Italian Female', voiceIDs: [33, 34, 35, 36, 37, 38]},
{name: 'Greek Female', voiceIDs: [62, 63, 64]},
{name: 'Hungarian Female', voiceIDs: [9, 10, 11]},
{name: 'Russian Female', voiceIDs: [47,48,49]},
{name: 'Dutch Female', voiceIDs: [45]},
{name: 'Swedish Female', voiceIDs: [65]},
{name: 'Japanese Female', voiceIDs: [50,51,52,53]},
{name: 'Korean Female', voiceIDs: [54,55,56,57]},
{name: 'Chinese Female', voiceIDs: [58,59,60,61]},
{name: 'Hindi Female', voiceIDs: [66,67]},
{name: 'Serbian Male', voiceIDs: [12]},
{name: 'Croatian Male', voiceIDs: [13]},
{name: 'Bosnian Male', voiceIDs: [14]},
{name: 'Romanian Male', voiceIDs: [46]},
{name: 'Fallback UK Female', voiceIDs: [8]}
];
//All voices available on every system and device
var voicecollection = [
{name: 'Google UK English Male'}, //0 male uk android/chrome
{name: 'Agnes'}, //1 female us safari mac
{name: 'Daniel Compact'}, //2 male us safari mac
{name: 'Google UK English Female'}, //3 female uk android/chrome
{name: 'en-GB', rate: 0.25, pitch: 1}, //4 male uk IOS
{name: 'en-AU', rate: 0.25, pitch: 1}, //5 female english IOS
{name: 'inglés Reino Unido'}, //6 spanish english android
{name: 'English United Kingdom'}, //7 english english android
{name: 'Fallback en-GB Female', lang: 'en-GB', fallbackvoice: true}, //8 fallback english female
{name: 'Eszter Compact'}, //9 Hungarian mac
{name: 'hu-HU', rate: 0.4}, //10 Hungarian iOS
{name: 'Fallback Hungarian', lang: 'hu', fallbackvoice: true}, //11 Hungarian fallback
{name: 'Fallback Serbian', lang: 'sr', fallbackvoice: true}, //12 Serbian fallback
{name: 'Fallback Croatian', lang: 'hr', fallbackvoice: true}, //13 Croatian fallback
{name: 'Fallback Bosnian', lang: 'bs', fallbackvoice: true}, //14 Bosnian fallback
{name: 'Fallback Spanish', lang: 'es', fallbackvoice: true}, //15 Spanish fallback
{name: 'Spanish Spain'}, //16 female es android/chrome
{name: 'español España'}, //17 female es android/chrome
{name: 'Diego Compact', rate: 0.3}, //18 male es mac
{name: 'Google Español'}, //19 male es chrome
{name: 'es-ES', rate: 0.20}, //20 male es iOS
{name: 'Google Français'}, //21 FR chrome
{name: 'French France'}, //22 android/chrome
{name: 'francés Francia'}, //23 android/chrome
{name: 'Virginie Compact', rate: 0.5}, //24 mac
{name: 'fr-FR', rate: 0.25}, //25 iOS
{name: 'Fallback French', lang: 'fr', fallbackvoice: true}, //26 fallback
{name: 'Google Deutsch'}, //27 DE chrome
{name: 'German Germany'}, //28 android/chrome
{name: 'alemán Alemania'}, //29 android/chrome
{name: 'Yannick Compact', rate: 0.5}, //30 mac
{name: 'de-DE', rate: 0.25}, //31 iOS
{name: 'Fallback Deutsch', lang: 'de', fallbackvoice: true}, //32 fallback
{name: 'Google Italiano'}, //33 IT chrome
{name: 'Italian Italy'}, //34 android/chrome
{name: 'italiano Italia'}, //35 android/chrome
{name: 'Paolo Compact', rate: 0.5}, //36 mac
{name: 'it-IT', rate: 0.25}, //37 iOS
{name: 'Fallback Italian', lang: 'it', fallbackvoice: true}, //38 fallback
{name: 'Google US English', timerSpeed:1}, //39 EN chrome
{name: 'English United States'}, //40 android/chrome
{name: 'inglés Estados Unidos'}, //41 android/chrome
{name: 'Vicki'}, //42 mac
{name: 'en-US', rate: 0.2, pitch: 1, timerSpeed:1.3}, //43 iOS
{name: 'Fallback English', lang: 'en-US', fallbackvoice: true, timerSpeed:0}, //44 fallback
{name: 'Fallback Dutch', lang: 'nl', fallbackvoice: true, timerSpeed:0}, //45 fallback
//{name: 'Simona Compact'}, //NaN Romanian mac female
//{name: 'ro-RO', rate: 0.25}, //NaN iOS female
{name: 'Fallback Romanian', lang: 'ro', fallbackvoice: true}, //46 Romanian Male fallback
{name: 'Milena Compact'}, //47 Romanian mac
{name: 'ru-RU', rate: 0.25}, //48 iOS
{name: 'Fallback Russian', lang: 'ru', fallbackvoice: true}, //49 Romanian fallback
{name: 'Google 日本人', timerSpeed:1}, //50 JP Chrome
{name: 'Kyoko Compact'}, //51 Japanese mac
{name: 'ja-JP', rate: 0.25}, //52 iOS
{name: 'Fallback Japanese', lang: 'ja', fallbackvoice: true}, //53 Japanese fallback
{name: 'Google 한국의', timerSpeed:1}, //54 KO Chrome
{name: 'Narae Compact'}, //55 Korean mac
{name: 'ko-KR', rate: 0.25}, //56 iOS
{name: 'Fallback Korean', lang: 'ko', fallbackvoice: true}, //57 Korean fallback
{name: 'Google 中国的', timerSpeed:1}, //58 CN Chrome
{name: 'Ting-Ting Compact'}, //59 Chinese mac
{name: 'zh-CN', rate: 0.25}, //60 iOS
{name: 'Fallback Chinese', lang: 'zh-CN', fallbackvoice: true}, //61 Chinese fallback
{name: 'Alexandros Compact'}, //62 Greek Male Mac
{name: 'el-GR', rate: 0.25}, //63 iOS
{name: 'Fallback Greek', lang: 'el', fallbackvoice: true}, //64 Greek Female fallback
{name: 'Fallback Swedish', lang: 'sv', fallbackvoice: true}, //65 Swedish Female fallback
{name: 'hi-IN', rate: 0.25}, //66 iOS
{name: 'Fallback Hindi', lang: 'hi', fallbackvoice: true} //67 Hindi Female fallback
];
self.iOS = /(iPad|iPhone|iPod)/g.test( navigator.userAgent );
//Fallback cache voices
var cache_ios_voices = [{"name":"he-IL","voiceURI":"he-IL","lang":"he-IL"},{"name":"th-TH","voiceURI":"th-TH","lang":"th-TH"},{"name":"pt-BR","voiceURI":"pt-BR","lang":"pt-BR"},{"name":"sk-SK","voiceURI":"sk-SK","lang":"sk-SK"},{"name":"fr-CA","voiceURI":"fr-CA","lang":"fr-CA"},{"name":"ro-RO","voiceURI":"ro-RO","lang":"ro-RO"},{"name":"no-NO","voiceURI":"no-NO","lang":"no-NO"},{"name":"fi-FI","voiceURI":"fi-FI","lang":"fi-FI"},{"name":"pl-PL","voiceURI":"pl-PL","lang":"pl-PL"},{"name":"de-DE","voiceURI":"de-DE","lang":"de-DE"},{"name":"nl-NL","voiceURI":"nl-NL","lang":"nl-NL"},{"name":"id-ID","voiceURI":"id-ID","lang":"id-ID"},{"name":"tr-TR","voiceURI":"tr-TR","lang":"tr-TR"},{"name":"it-IT","voiceURI":"it-IT","lang":"it-IT"},{"name":"pt-PT","voiceURI":"pt-PT","lang":"pt-PT"},{"name":"fr-FR","voiceURI":"fr-FR","lang":"fr-FR"},{"name":"ru-RU","voiceURI":"ru-RU","lang":"ru-RU"},{"name":"es-MX","voiceURI":"es-MX","lang":"es-MX"},{"name":"zh-HK","voiceURI":"zh-HK","lang":"zh-HK"},{"name":"sv-SE","voiceURI":"sv-SE","lang":"sv-SE"},{"name":"hu-HU","voiceURI":"hu-HU","lang":"hu-HU"},{"name":"zh-TW","voiceURI":"zh-TW","lang":"zh-TW"},{"name":"es-ES","voiceURI":"es-ES","lang":"es-ES"},{"name":"zh-CN","voiceURI":"zh-CN","lang":"zh-CN"},{"name":"nl-BE","voiceURI":"nl-BE","lang":"nl-BE"},{"name":"en-GB","voiceURI":"en-GB","lang":"en-GB"},{"name":"ar-SA","voiceURI":"ar-SA","lang":"ar-SA"},{"name":"ko-KR","voiceURI":"ko-KR","lang":"ko-KR"},{"name":"cs-CZ","voiceURI":"cs-CZ","lang":"cs-CZ"},{"name":"en-ZA","voiceURI":"en-ZA","lang":"en-ZA"},{"name":"en-AU","voiceURI":"en-AU","lang":"en-AU"},{"name":"da-DK","voiceURI":"da-DK","lang":"da-DK"},{"name":"en-US","voiceURI":"en-US","lang":"en-US"},{"name":"en-IE","voiceURI":"en-IE","lang":"en-IE"},{"name":"hi-IN","voiceURI":"hi-IN","lang":"hi-IN"},{"name":"el-GR","voiceURI":"el-GR","lang":"el-GR"},{"name":"ja-JP","voiceURI":"ja-JP","lang":"ja-JP"}];
var systemvoices;
var CHARACTER_LIMIT = 100;
var VOICESUPPORT_ATTEMPTLIMIT = 5;
var voicesupport_attempts = 0;
var fallbackMode = false;
var WORDS_PER_MINUTE = 140;
self.fallback_playing = false;
self.fallback_parts = null;
self.fallback_part_index = 0;
self.fallback_audio = null;
self.msgparameters = null;
self.timeoutId = null;
self.OnLoad_callbacks = [];
//Wait until system voices are ready and trigger the event OnVoiceReady
if (typeof speechSynthesis != 'undefined') {
speechSynthesis.onvoiceschanged = function () {
systemvoices = window.speechSynthesis.getVoices();
if (self.OnVoiceReady != null) {
self.OnVoiceReady.call();
}
};
}
self.default_rv = responsivevoices[0];
self.OnVoiceReady = null;
self.init = function() {
//Disable RV on IOS temporally
/*if (self.iOS) {
self.enableFallbackMode();
return;
}*/
if (typeof speechSynthesis === 'undefined') {
console.log('RV: Voice synthesis not supported');
self.enableFallbackMode();
} else {
//Waiting a few ms before calling getVoices() fixes some issues with safari on IOS as well as Chrome
setTimeout(function () {
var gsvinterval = setInterval(function () {
var v = window.speechSynthesis.getVoices();
if (v.length == 0 && (systemvoices == null || systemvoices.length == 0)) {
//console.log('Voice support NOT ready');
voicesupport_attempts++;
if (voicesupport_attempts > VOICESUPPORT_ATTEMPTLIMIT) {
clearInterval(gsvinterval);
//On IOS, sometimes getVoices is just empty, but speech works. So we use a cached voice collection.
if (window.speechSynthesis != null) {
if (self.iOS) {
console.log('RV: Voice support ready (cached)');
self.systemVoicesReady(cache_ios_voices);
}else{
console.log("RV: speechSynthesis present but no system voices found");
self.enableFallbackMode();
}
} else {
//We don't support voices. Using fallback
self.enableFallbackMode();
}
}
} else {
console.log('RV: Voice support ready');
self.systemVoicesReady(v);
clearInterval(gsvinterval);
}
}, 100);
}, 100);
}
self.Dispatch("OnLoad");
}
self.systemVoicesReady = function(v) {
systemvoices = v;
self.mapRVs();
if (self.OnVoiceReady != null)
self.OnVoiceReady.call();
}
self.enableFallbackMode = function() {
fallbackMode = true;
console.log('RV: Enabling fallback mode');
self.mapRVs();
if (self.OnVoiceReady != null)
self.OnVoiceReady.call();
}
self.getVoices = function () {
//Create voices array
var v = [];
for (var i = 0; i < responsivevoices.length; i++) {
v.push({name: responsivevoices[i].name});
}
return v;
}
self.speak = function (text, voicename, parameters) {
self.msgparameters = parameters || {};
self.msgtext = text;
self.msgvoicename = voicename;
//Support for multipart text (there is a limit on characters)
var multipartText = [];
if (text.length > CHARACTER_LIMIT) {
var tmptxt = text;
while (tmptxt.length > CHARACTER_LIMIT) {
//Split by common phrase delimiters
var p = tmptxt.search(/[:!?.;]+/);
var part = '';
//Coludn't split by priority characters, try commas
if (p == -1 || p >= CHARACTER_LIMIT) {
p = tmptxt.search(/[,]+/);
}
//Couldn't split by normal characters, then we use spaces
if (p == -1 || p >= CHARACTER_LIMIT) {
var words = tmptxt.split(' ');
for (var i = 0; i < words.length; i++) {
if (part.length + words[i].length + 1 > CHARACTER_LIMIT)
break;
part += (i != 0 ? ' ' : '') + words[i];
}
} else {
part = tmptxt.substr(0, p + 1);
}
tmptxt = tmptxt.substr(part.length, tmptxt.length - part.length);
multipartText.push(part);
//console.log(part.length + " - " + part);
}
//Add the remaining text
if (tmptxt.length > 0) {
multipartText.push(tmptxt);
}
} else {
//Small text
multipartText.push(text);
}
//Find system voice that matches voice name
var rv;
if (voicename == null) {
rv = self.default_rv;
} else {
rv = self.getResponsiveVoice(voicename);
}
var profile = {};
//Map was done so no need to look for the mapped voice
if (rv.mappedProfile != null) {
profile = rv.mappedProfile;
} else {
profile.systemvoice = self.getMatchedVoice(rv);
profile.collectionvoice = {};
if (profile.systemvoice == null) {
console.log('RV: ERROR: No voice found for: ' + voicename);
return;
}
}
if (profile.collectionvoice.fallbackvoice == true) {
fallbackMode = true;
self.fallback_parts = [];
} else {
fallbackMode = false;
}
self.msgprofile = profile;
//console.log("Start multipart play");
//Play multipart text
for (var i = 0; i < multipartText.length; i++) {
if (!fallbackMode) {
//Use SpeechSynthesis
//Create msg object
var msg = new SpeechSynthesisUtterance();
msg.voice = profile.systemvoice;
msg.voiceURI = profile.systemvoice.voiceURI;
msg.volume = profile.collectionvoice.volume || profile.systemvoice.volume || 1; // 0 to 1
msg.rate = profile.collectionvoice.rate || profile.systemvoice.rate || 1; // 0.1 to 10
msg.pitch = profile.collectionvoice.pitch || profile.systemvoice.pitch || 1; //0 to 2*/
msg.text = multipartText[i];
msg.lang = profile.collectionvoice.lang || profile.systemvoice.lang;
msg.rvIndex = i;
msg.rvTotal = multipartText.length;
if (i == 0) {
msg.onstart = self.speech_onstart;
}
self.msgparameters.onendcalled = false;
if (parameters != null) {
if (i < multipartText.length - 1 && multipartText.length > 1) {
msg.onend = parameters.onchunkend;
msg.addEventListener('end',parameters.onchuckend);
} else {
msg.onend = self.speech_onend;
msg.addEventListener('end',self.speech_onend);
}
msg.onerror = parameters.onerror || function (e) {
console.log('RV: Error');
console.log(e);
};
msg.onpause = parameters.onpause;
msg.onresume = parameters.onresume;
msg.onmark = parameters.onmark;
msg.onboundary = parameters.onboundary;
} else {
msg.onend = self.speech_onend;
msg.onerror = function (e) {
console.log('RV: Error');
console.log(e);
};
}
//console.log(JSON.stringify(msg));
speechSynthesis.speak(msg);
} else {
//var url = 'http://www.corsproxy.com/translate.google.com/translate_tts?ie=UTF-8&q=' + multipartText[i] + '&tl=' + profile.collectionvoice.lang || profile.systemvoice.lang || 'en-US';
var url = 'http://responsivevoice.org/responsivevoice/getvoice.php?t=' + multipartText[i]+ '&tl=' + profile.collectionvoice.lang || profile.systemvoice.lang || 'en-US';
var audio = document.createElement("AUDIO");
audio.src = url;
audio.playbackRate = 1;
audio.preload = 'auto';
audio.volume = profile.collectionvoice.volume || profile.systemvoice.volume || 1; // 0 to 1;
self.fallback_parts.push(audio);
//console.log(audio);
}
}
if (fallbackMode) {
self.fallback_part_index = 0;
self.fallback_startPart();
}
}
self.startTimeout = function (text, callback) {
//if (self.iOS) {
// multiplier = 0.5;
//}
var multiplier = self.msgprofile.collectionvoice.timerSpeed;
if (self.msgprofile.collectionvoice.timerSpeed==null)
multiplier = 1;
//console.log(self.msgprofile.collectionvoice.name);
if (multiplier <=0)
return;
self.timeoutId = setTimeout(callback, multiplier * 1000 * (60 / WORDS_PER_MINUTE) * text.split(/\s+/).length); //avg 140 words per minute read time
//console.log("Timeout " + self.timeoutId + " started: " + (multiplier * 1000 * (60 / WORDS_PER_MINUTE) * text.split(/\s+/).length).toString());
}
self.checkAndCancelTimeout = function () {
if (self.timeoutId != null) {
//console.log("Timeout " + self.timeoutId + " cancelled");
clearTimeout(self.timeoutId);
self.timeoutId = null;
}
}
self.speech_timedout = function() {
//console.log("Speech cancelled: Timeout " + self.timeoutId + " ended");
self.cancel();
//if (!self.iOS) //On iOS, cancel calls msg.onend
self.speech_onend();
}
self.speech_onend = function () {
self.checkAndCancelTimeout();
//Avoid this being automatically called just after calling speechSynthesis.cancel
if (self.cancelled === true) {
self.cancelled = false;
return;
}
//console.log("on end fired");
if (self.msgparameters != null && self.msgparameters.onend != null && self.msgparameters.onendcalled!=true) {
//console.log("Speech on end called -" + self.msgtext);
self.msgparameters.onendcalled=true;
self.msgparameters.onend();
}
}
self.speech_onstart = function () {
//if (!self.iOS)
//console.log("Speech start");
if (self.iOS)
self.startTimeout(self.msgtext,self.speech_timedout);
self.msgparameters.onendcalled=false;
if (self.msgparameters != null && self.msgparameters.onstart != null) {
self.msgparameters.onstart();
}
}
self.fallback_startPart = function () {
if (self.fallback_part_index == 0) {
self.speech_onstart();
}
self.fallback_audio = self.fallback_parts[self.fallback_part_index];
if (self.fallback_audio == null) {
//Fallback audio is not working. Just wait for the timeout event
console.log("RV: Fallback Audio is not available");
} else {
self.fallback_audio.play();
self.fallback_audio.addEventListener('ended', self.fallback_finishPart);
}
}
self.fallback_finishPart = function (e) {
self.checkAndCancelTimeout();
if (self.fallback_part_index < self.fallback_parts.length - 1) {
//console.log('chunk ended');
self.fallback_part_index++;
self.fallback_startPart();
} else {
//console.log('msg ended');
self.speech_onend();
}
}
self.cancel = function () {
self.checkAndCancelTimeout();
if (fallbackMode){
if (self.fallback_audio!=null)
self.fallback_audio.pause();
}else{
self.cancelled = true;
speechSynthesis.cancel();
}
}
self.voiceSupport = function () {
return ('speechSynthesis' in window);
}
self.OnFinishedPlaying = function (event) {
//console.log("OnFinishedPlaying");
if (self.msgparameters != null) {
if (self.msgparameters.onend != null)
self.msgparameters.onend();
}
}
//Set default voice to use when no voice name is supplied to speak()
self.setDefaultVoice = function (voicename) {
var vr = self.getResponsiveVoice(voicename);
if (vr != null) {
self.default_vr = vr;
}
}
//Map responsivevoices to system voices
self.mapRVs = function() {
for (var i = 0; i < responsivevoices.length; i++) {
var rv = responsivevoices[i];
for (var j = 0; j < rv.voiceIDs.length; j++) {
var vcoll = voicecollection[rv.voiceIDs[j]];
if (vcoll.fallbackvoice != true) { // vcoll.fallbackvoice would be null instead of false
// Look on system voices
var v = self.getSystemVoice(vcoll.name);
if (v != null) {
rv.mappedProfile = {
systemvoice: v,
collectionvoice: vcoll
};
//console.log("Mapped " + rv.name + " to " + v.name);
break;
}
} else {
//Pick the fallback voice
rv.mappedProfile = {
systemvoice: {},
collectionvoice: vcoll
};
//console.log("Mapped " + rv.name + " to " + vcoll.lang + " fallback voice");
break;
}
}
}
}
//Look for the voice in the system that matches the one in our collection
self.getMatchedVoice = function(rv) {
for (var i = 0; i < rv.voiceIDs.length; i++) {
var v = self.getSystemVoice(voicecollection[rv.voiceIDs[i]].name);
if (v != null)
return v;
}
return null;
}
self.getSystemVoice = function(name) {
if (typeof systemvoices === 'undefined')
return null;
for (var i = 0; i < systemvoices.length; i++) {
if (systemvoices[i].name == name)
return systemvoices[i];
}
return null;
}
self.getResponsiveVoice = function(name) {
for (var i = 0; i < responsivevoices.length; i++) {
if (responsivevoices[i].name == name) {
return responsivevoices[i];
}
}
return null;
}
self.Dispatch = function(name) {
if (self.hasOwnProperty(name + "_callbacks") &&
self[name + "_callbacks"].length > 0) {
var callbacks = self[name + "_callbacks"];
for(var i=0; i<callbacks.length; i++) {
callbacks[i]();
}
}
}
self.AddEventListener = function(name,callback) {
if (self.hasOwnProperty(name + "_callbacks")) {
self[name + "_callbacks"].push(callback);
}else{
console.log("RV: Event listener not found: " + name);
}
}
//We should use jQuery if it's available
if (typeof $ === 'undefined') {
document.addEventListener('DOMContentLoaded', function () {
self.init();
});
} else {
$(document).ready(function () {
self.init();
});
}
}
var responsiveVoice = new ResponsiveVoice();
}
@AbdullahNauman
Copy link

@jason775844895, you can simply add this to the beginning of your script.

responsiveVoice.setDefaultVoice("US English Female");

@Lau-po
Copy link

Lau-po commented Apr 19, 2016

Thank you! You saved one of my projects ;)

@maher17
Copy link

maher17 commented Apr 24, 2016

how can I insert 3D model please ??

@gabouh
Copy link

gabouh commented May 8, 2016

does anyone knows how to save the audio to an .mp3 file?

@joeforjoomla
Copy link

All websites http://responsivevoice.com/ and http://responsivevoice.org/ are currently offline... is anyone aware of this?

@aldrienht
Copy link

Hi there, why I'm getting RV: ERROR: No voice found for: Japanese Female for japanese language?

@Handresito
Copy link

I have the same issue RV: ERROR: No voice found for: UK English Male, I've changed to another language but I got the same error.
Thanks in advanced

@joramkimata
Copy link

joramkimata commented Jun 20, 2016

Try this

<script type="text/javascript">
        function sayIt(){
            responsiveVoice.setDefaultVoice("US English Female");
            responsiveVoice.speak('Jaji Hamisi Munene \nRoom Number 101 \nCase Number CS/FL/NO/20293');
        }
        setTimeout(sayIt, 3000);
    </script>

@Nomat1x
Copy link

Nomat1x commented Jul 6, 2016

Hi all. Can i somehow save audio stream to object?

@edmundtfy
Copy link

Hello... on mobile devices, the first 2-3 responsivevoice.speak event doesn't work --> it's somehow empty voice. Does anybody know how to solve this?
and second, on desktop Chrome, all words are spoken. However on any other platform, I could only play 3-4 seconds of voice and then it stops abruptly. Any idea what I am doing wrong?
Thanks!

@atchyut-re
Copy link

atchyut-re commented Jul 29, 2016

Is there any function we can call to check if the audio is playing?

Something like:

if(responsiveVoice.isPlaying()) {
  console.log("I hope you are listening");
}

@rezwansaki
Copy link

Is it free ? Can I use it in offline mode? How can I get javascript library for offline text to speech?

@dsemerida
Copy link

dsemerida commented Feb 7, 2017

on ios this plugin not working ResponsiveVoice.JS http://responsivevoice.org/api/, can help me?

@GigiP13
Copy link

GigiP13 commented May 29, 2017

@rezwansaki did you manage to use responsivevoice in offline mode? I have the same problem: if I add teh source responsivevoice.js in my script it does not work offline.

@Benchaqroun
Copy link

please someone help me to to include ResponsiveVoice in a React Project using webpack

@RagedElimanator
Copy link

RagedElimanator commented Nov 9, 2018

@atchyut-re

Try this

<script type="text/javascript">
        function sayIt(){
            responsiveVoice.setDefaultVoice("US English Female");
            responsiveVoice.speak('Jaji Hamisi Munene \nRoom Number 101 \nCase Number CS/FL/NO/20293');
        }
        setTimeout(sayIt, 3000);
    </script>

Noting that setTimeout works as you stated any chance there is way I can timeout all responsiveVoice.speak statements with this function on the else if and if would clear that timeout?

    if (MaterialToggleYellow00.checked == 1){
      responsiveVoice.resume();
    } else if (MaterialToggleYellow00.checked == 0){
      responsiveVoice.cancel();
    }
  }

@Allan-an
Copy link

languages like hindi,turkish & vietnamise not working when used in android.When the link is used directly with the language code as the parameter,it shows 403 forbidden.Request forbidden by administrative rules.

@robiafs
Copy link

robiafs commented Apr 25, 2019

it's just js file. but how to work it ? some missing full form, play button.

@MKR2554
Copy link

MKR2554 commented Dec 14, 2020

How can i Remove Default Play Audio "Hello Friends" when API start

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment