How to add webcam selection to official mediapipe face detection solution? - javascript

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

Related

HTML audio duration not working in chrome

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

Javascript - How to get more voices for text to speech?

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.

Remove Measure Toolbar Button from Autodesk Forge Viewer

I am using the autodesk forge viewer and want to remove the 'measure' tool from the toolbar. I have tried the following but it will not remove the 'measure' button
const onToolbarCreated = (e) => {
const settingsTools = viewer.toolbar.getControl('settingsTools')
// settingsTools.removeControl('toolbar-modelStructureTool')
// settingsTools.removeControl('toolbar-propertiesTool')
settingsTools.removeControl('toolbar-settingsTool');
settingsTools.removeControl('toolbar-measureTool');
//settingsTools.removeControl('toolbar-fullscreenTool')
}
All of the other removeControl() functions work other than the one for the measure-tool. Any guidance on how I could remove this button from the viewer would be greatly appreciated!
Cheers!
EDIT: I have tried this without success
const onToolbarCreated = (e) => {
const settingsTools = viewer.toolbar.getControl('settingsTools');
const modelTools = viewer.toolbar.getControl('modelTools');
modelTools.removeControl('toolbar-measurementSubmenuTool');
// settingsTools.removeControl('toolbar-modelStructureTool')
// settingsTools.removeControl('toolbar-propertiesTool')
settingsTools.removeControl('toolbar-settingsTool');
//settingsTools.removeControl('toolbar-measurementSubmenuTool');
//settingsTools.removeControl('toolbar-fullscreenTool')
If you are not planning to use it anymore you can simply unload the extension from your project.
viewer.unloadExtension("Autodesk.Measure");
Measure tool is in modelTools group.
const modelTools = viewer.toolbar.getControl('modelTools')
modelTools.removeControl('toolbar-measurementSubmenuTool')

Click button on website using java-script and speech recognition

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.

How to force a media to be loaded at run time, without playing it now?

I am making a web app that can be open for a long time. I don't want to load audio at load time (when the HTML gets downloaded and parsed) to make the first load as fast as possible and to spare precious resources for mobile users. Audio is disabled by default.
Putting the audio in CSS or using preload is not appropriate here because I don't want to load it at load time with the rest.
I am searching for the ideal method to load audio at run time, (after a checkbox has been checked, this can be after 20 minutes after opening the app) given a list of audio elements.
The list is already in a variable allSounds. I have the following audio in a webpage (there are more):
<audio preload="none">
<source src="sound1.mp3">
</audio>
I want to keep the same HTML because after second visit I can easily change it to (this works fine with my server-side HTML generation)
<audio preload="auto">
<source src="sound1.mp3">
</audio>
and it works.
Once the option is turned on, I want to load the sounds, but not play them immediately. I know that .play() loads the sounds. But I want to avoid the delay between pressing a button and the associated feedback sound.
It is better to not play sound than delayed (in my app).
I made this event handler to load sounds (it works) but in the chrome console, it says that download was cancelled, and then restarted I don't know exactly what I am doing wrong.
Is this is the correct way to force load sounds? What are the other ways? If possible without changing the HTML.
let loadSounds = function () {
allSounds.forEach(function (sound) {
sound.preload = "auto";
sound.load();
});
loadSounds = function () {}; // Execute once
};
here is playSound function, but not very important for the questions
const playSound = function (sound) {
// PS
/* only plays ready sound to avoid delays between fetching*/
if (!soundEnabled)) {
return;
}
if (sound.readyState < sound.HAVE_ENOUGH_DATA) {
return;
}
sound.play();
};
Side question: Should there be a preload="full" in the HTML spec?
See also:
Preload mp3 file in queue to avoid any delay in playing the next file in queue
how we can Play Audio with text highlight word by word in angularjs
To cache the audio will need to Base64 encode your MP3 files, and start the Base64 encoded MP3 file with data:audio/mpeg;base64,
Then you can pre-load/cache the file with css using something like:
body::after {
content:url(myfile.mp3);
display:none;
}
I think I would just use the preloading functionality without involving audio tag at all...
Example:
var link = document.createElement('link')
link.rel = 'preload'
link.href = 'sound1.mp3'
link.as = 'audio'
link.onload = function() {
// Done loading the mp3
}
document.head.appendChild(link)
I'm quite sure that I've found a solution for you. As far as I'm concerned, your sounds are additional functionality, and are not required for everybody. In that case I would propose to load the sounds using pure javascript, after user has clicked unmute button.
A simple sketch of solution is:
window.addEventListener('load', function(event) {
var audioloaded = false;
var audioobject = null;
// Load audio on first click
document.getElementById('unmute').addEventListener('click', function(event) {
if (!audioloaded) { // Load audio on first click
audioobject = document.createElement("audio");
audioobject.preload = "auto"; // Load now!!!
var source = document.createElement("source");
source.src = "sound1.mp3"; // Append src
audioobject.appendChild(source);
audioobject.load(); // Just for sure, old browsers fallback
audioloaded = true; // Globally remember that audio is loaded
}
// Other mute / unmute stuff here that you already got... ;)
});
// Play sound on click
document.getElementById('playsound').addEventListener('click', function(event) {
audioobject.play();
});
});
Of course, button should have id="unmute", and for simplicity, body id="body" and play sound button id="playsound. You can modify that of course to suit your needs. After that, when someone will click unmute, audio object will be generated and dynamically loaded.
I didn't try this solution so there may be some little mistakes (I hope not!). But I hope this will get you an idea (sketch) how this can be acomplished using pure javascript.
Don't be afraid that this is pure javascript, without html. This is additional functionality, and javascript is the best way to implement it.
You can use a Blob URL representation of the file
let urls = [
"https://upload.wikimedia.org/wikipedia/commons/b/be/Hidden_Tribe_-_Didgeridoo_1_Live.ogg"
, "https://upload.wikimedia.org/wikipedia/commons/6/6e/Micronesia_National_Anthem.ogg"
];
let audioNodes, mediaBlobs, blobUrls;
const request = url => fetch(url).then(response => response.blob())
.catch(err => {throw err});
const handleResponse = response => {
mediaBlobs = response;
blobUrls = mediaBlobs.map(blob => URL.createObjectURL(blob));
audioNodes = blobUrls.map(blobURL => new Audio(blobURL));
}
const handleMediaSelection = () => {
const select = document.createElement("select");
document.body.appendChild(select);
const label = new Option("Select audio to play");
select.appendChild(label);
select.onchange = () => {
audioNodes.forEach(audio => {
audio.pause();
audio.currentTime = 0;
});
audioNodes[select.value].play();
}
select.onclick = () => {
const media = audioNodes.find(audio => audio.currentTime > 0);
if (media) {
media.pause();
media.currentTime = 0;
select.selectedIndex = 0;
}
}
mediaBlobs.forEach((blob, index) => {
let option = new Option(
new URL(urls[index]).pathname.split("/").pop()
, index
);
option.onclick = () => console.log()
select.appendChild(option);
})
}
const handleError = err => {
console.error(err);
}
Promise.all(urls.map(request))
.then(handleResponse)
.then(handleMediaSelection)
.catch(handleError);

Categories