I made this little script where you can enter some message and it reads it out.
I solved it by using FireFox SpeechSynthesis API.
How can I get more voices and support for more languages?
Note: There is a "bug" in SO. If I edit my question and edit the script and test it from there, then 4 voices are
loading. If I run the code snippet normally, then no voices are
loading, but the default voice.
if ('speechSynthesis' in window) {
// Speech Synthesis supported
} else {
// Speech Synthesis Not Supported
alert("Sorry, your browser doesn't support text to speech!");
}
const voices = speechSynthesis.getVoices();
populateVoiceList();
if (typeof speechSynthesis !== 'undefined' && speechSynthesis.onvoiceschanged !== undefined) {
speechSynthesis.onvoiceschanged = populateVoiceList;
}
var selectedLang = $("#voiceSelect").find("option").attr("data-lang");
var selectedVoice = $("#voiceSelect").find("option").attr("data-pos");
$("#voiceSelect").change(function() {
selectedLang = $(this).find("option:selected").attr("data-lang");
selectedVoice = $(this).find("option:selected").attr("data-pos");
});
$("#start").click(function() {
var msg = new SpeechSynthesisUtterance();
msg.text = $("#message").val();
msg.lang = selectedLang;
msg.voice = voices[selectedVoice];
console.log(msg);
window.speechSynthesis.speak(msg);
});
// Hide Dropdown if there is only one voice
if ($("#voiceSelect option").length == 0) {
$("#voiceSelect").hide();
}
function populateVoiceList()
{
if (typeof speechSynthesis === 'undefined') {
return;
}
for (let i = 0; i < voices.length; i++) {
const option = document.createElement('option');
option.textContent = `${voices[i].name} (${voices[i].lang})`;
if (voices[i].default) {
option.textContent += ' — DEFAULT';
}
option.setAttribute('data-lang', voices[i].lang);
option.setAttribute('data-name', voices[i].name);
option.setAttribute('data-voice-uri', voices[i].voiceURI);
option.setAttribute('data-pos', i);
document.getElementById("voiceSelect").appendChild(option);
}
}
.flex-container {
display: flex;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select id="voiceSelect"></select>
<div class="flex-container">
<textarea id="message" value="test"></textarea>
<button id="start">Start</button>
</div>
JSFiddle
How can I get more voices and support for more languages?
Currently there isn't a browser vendor that supports loading custom/more voices. It doesn't appear to be part of the nascent specification yet either, as there is an open issue asking how to add more voices.
The list of voices is dependent upon the user agent/device because that is how it is specified. User agents are using either a native speech engine provided by the device OS or a network based speech engine, each of which work with a set of supported voices. Here is a comment from a chromium issue about not being able to support boundary events because of the missing capabilities in the native/network based speech engines, as an example of the platform the Web Speech API is dependent upon.
If you want to see what voices are available for various devices/browsers you can go to https://morganney.github.io/tts-react/?path=/story/tts-react--hook and click the "load" button to get an HTML <select> of the SpeechSynthesisVoice's supported.
You can also run the snippet below to see what voices are available:
let voices = []
const btn = document.getElementById('load')
const options = document.getElementById('voices')
const hasSynth = 'speechSynthesis' in window
if (hasSynth) {
voices = speechSynthesis.getVoices()
speechSynthesis.addEventListener('voiceschanged', () => {
voices = speechSynthesis.getVoices()
})
}
btn.addEventListener('click', () => {
const initOpt = document.createElement('option')
if (!voices.length && hasSynth) {
voices = speechSynthesis.getVoices()
}
initOpt.append(document.createTextNode('-- select voice --'))
options.append(initOpt)
voices.forEach(voice => {
const option = document.createElement('option')
option.value = voice.name
option.append(document.createTextNode(`${voice.lang} - ${voice.name}`))
options.append(option)
})
options.style.display = 'inline'
})
options.addEventListener('change', (evt) => {
if (hasSynth) {
const utterance = new SpeechSynthesisUtterance()
utterance.text = 'Testing the selected voice.'
utterance.voice = voices.find(voice => voice.name === evt.target.value)
speechSynthesis.speak(utterance)
}
})
#voices {
display: none;
}
<button id="load">click to load voices</button>
<select id="voices">
</select>
I have slightly altered your code and have a working version here: https://jsfiddle.net/lharby/j36nbhy1/
First we set synth variable and also a let to initialise voices as an empty array which we can push to later
const synth = window.speechSynthesis;
let voices = [];
Then we have to pass voices = synth.getVoices(); inside our populateVoiceList function as the call to it works asynchronously.
Then I changed the for loop, for a forEach function like so:
voices.forEach((item, index) => {
const option = document.createElement('option');
option.textContent = `${item.name} (${item.lang})`;
option.setAttribute('data-lang', item.lang);
option.setAttribute('data-name', item.name);
option.setAttribute('data-voice-uri', item.voiceURI);
option.setAttribute('data-pos', index);
document.getElementById("voiceSelect").appendChild(option);
});
I think the rest is pretty much the same, but let me know if you get issues. I did have to make a couple of edits in order to test.
Related
Upong calling audioElement.duraion returns infinite in chromium based browsers but works find in firefox. The song is stored locally in the same directory.
console.log("Welcome to Spotify | clone");
let songIndex = 0;
const masterPlay = document.getElementById("masterPlay");
const progressBar = document.getElementById("progressBar");
const gif = document.getElementById("gif");
const audioElement=document.getElementById("song")
// let audioElement=new Audio('./1.mp3')
// Handeling play pause and click
masterPlay.addEventListener('click', () => {
if (audioElement.paused || audioElement.currentTime <= 0) {
audioElement.play();
masterPlay.classList.remove("fa-circle-play");
masterPlay.classList.add("fa-circle-pause");
gif.style.opacity = 1;
}
else {
audioElement.pause();
masterPlay.classList.remove("fa-circle-pause");
masterPlay.classList.add("fa-circle-play");
gif.style.opacity = 0;
}
});
//EventListeners
audioElement.addEventListener("timeupdate", () => {
progress = ((audioElement.currentTime / audioElement.duration) * 100);
progressBar.value = progress;
console.log(audioElement.currentTime)
});
Expectations:
It returns the duration of the autio track.
What I tried:
Different browsers. (Works fine on firefox based browsers.)
Different song. (I found that some songs don't work on chrome but on firefox everything works.)
Tried using HTML audio element. (The problem persists)
Tried using JS audio(). (The problem still exists)
At the end of the day I found out that it was a bug with VS code Live Preview extension from Microsoft
https://google.github.io/mediapipe/solutions/face_detection#javascript-solution-api
This is simplest way to add face detection to webcam feed on website using mediapipe by Google.
My laptop have inbuilt webcam and one OBS virtual webcam also. When I try this example code on my laptop sometime virtual webcam get picked up by my webpage randomly.
How can I add webcam selection to this example code so I can avoid getting virtual webcam selected automatailly?
Please try this (link provided to full article)
const video = document.getElementById('video');
const button = document.getElementById('button');
const select = document.getElementById('select');
function gotDevices(mediaDevices) {
select.innerHTML = '';
select.appendChild(document.createElement('option'));
let count = 1;
mediaDevices.forEach(mediaDevice => {
if (mediaDevice.kind === 'videoinput') {
const option = document.createElement('option');
option.value = mediaDevice.deviceId;
const label = mediaDevice.label || `Camera ${count++}`;
const textNode = document.createTextNode(label);
option.appendChild(textNode);
select.appendChild(option);
}
});
}
Source : Select Camera Javascript Mediapipe
I have implemented text to speech in javascript it is a funtion which create speech back to back process for different message. sometime before it was working fine but after updating chrome (auto update of window) it doesn't work so i have used artyom library which was also working fine. but now after update of windows again it does support speech again..
now both of the library is not support text to speech.. please help me somebody.. was stuck in this from last 1 month many times it work and after update it doen't i am not getting any standard solution please help...
if ( 'speechSynthesis' in window )
{
window.speechSynthesis.cancel();
//$(".divRandom").hide();
let speech = new SpeechSynthesisUtterance(msg);
voices = window.speechSynthesis.getVoices();
if ('speechSynthesis' in window) {
speech_voices = window.speechSynthesis.getVoices();
window.speechSynthesis.onvoiceschanged = function() {
speech_voices = window.speechSynthesis.getVoices();
};
}
speech.voice = speech_voices[1];
//speech.lang = "en-US";
speech.volume = 2;
if (speed > 1)
speech.rate = 3;//slow speaking
else
speech.rate = 7;//faster
speech.pitch = 1;
window.speechSynthesis.speak(speech);
}
else
{
/*var Jarvis = new Artyom();
Jarvis.ArtyomVoicesIdentifiers["en-GB"] = ["Google UK English Female", "Google UK English Male", "en-GB", "en_GB"];
//Jarvis.say(msg);
//Jarvis.ArtyomProperties["speed"] = 3;
Jarvis.say(msg.toString(),{
onStart:function(){
setTimeout(function(){
// Most likely to be true
console.log("Speaking : "+ Jarvis.isSpeaking().toString());
},500);
},
onEnd: function(){
setTimeout(function(){
// Most likely to be false
console.log("Speaking : "+ Jarvis.isSpeaking().toString());
},500);
}
});*/
alert("your browser doesn't support audio..");
}
Newbie here. I work on a website where I have to click buttons. I need to be able to click on buttons based on their DIV ID using speech recognition. Lets say a clickable button div has an ID of one, I want to say ONE verbally and have the button clicked.
I am guessing I need Javascript click function combined with a speech recognition API. I can handle using Javascript to manipulate HTML DOM, but how do I interface with an offline speech recognition API. Which one should I use and how do I go about using it?
If you want to test speech recognition you can check MDN docs the page include link to github with demos.
Here is my code based on color example (<com.sun.speech.app.numbers.*> is taken from w3c docs about grammars)
<!DOCTYPE html>
<html>
<body>
<script>
var SpeechRecognition = SpeechRecognition || webkitSpeechRecognition;
var SpeechGrammarList = SpeechGrammarList || webkitSpeechGrammarList;
var SpeechRecognitionEvent = SpeechRecognitionEvent || webkitSpeechRecognitionEvent;
var grammar = '#JSGF V1.0; import <com.sun.speech.app.numbers.*>; grammar numbers; public <number> = <com.sun.speech.app.numbers.*>;'
var recognition = new SpeechRecognition();
var speechRecognitionList = new SpeechGrammarList();
speechRecognitionList.addFromString(grammar, 1);
recognition.grammars = speechRecognitionList;
//recognition.continuous = false;
recognition.lang = 'en-US';
recognition.interimResults = true;
recognition.maxAlternatives = 1;
recognition.onerror = function(event) {
console.log(event.error);
};
document.body.onclick = function() {
recognition.start();
console.log('Ready to receive a number command.');
};
recognition.onresult = function(event) {
var numbers = ['zero', 'one', 'two'];
console.log(event.results);
var last = event.results.length - 1;
var number = event.results[last][0].transcript;
console.log(numbers[number]);
var node = document.querySelector("#" + numbers[number]);
if (node) {
node.style.color = 'red';
}
};
</script>
<div id="one">one</div>
<div id="two">two</div>
</body>
</html>
unfortunetelly speech recognition is disabled for Stack Snippets but here is link to codepen IMO speech recognition in browsers is not very good it don't recognize words you're saying, you need to repeat the word few times to make it work.
I wrote a HTML5 webpage consisting only of:
<input type="text" style="font-size: 40px;" name="speech" size="50" x-webkit-speech/>
What I'm trying to do is to get the x-webkit-speech to start automatically as soon as I enter the page and continously put out the speech recognition results into the text. How would I do that ? I've seen various javascripts relating to that and I tested a lot of them but they don't work for me.
Thanks to anyone who answers ! ;)
You can try to use Web Speech API, for example:
if ('webkitSpeechRecognition' in window) {
var recognition = new webkitSpeechRecognition();
var final_transcript = '';
recognition.continuous = true;
recognition.interimResults = true;
recognition.onresult = function( event ) {
var final_transcript = '';
for (var i = event.resultIndex; i < event.results.length; ++i) {
if (event.results[i].isFinal) {
final_transcript += event.results[i][0].transcript;
}
}
document.getElementById( 'speech' ).value = final_transcript;
};
recognition.start();
}
The only one thing is that you will need to allow page to use microphone at page load
jsFiddle demo