Web Speech API allows recording human voice and convert it to text or generate an audio file.
This can be used to enable the users to access the website hand-free and give commands with voice.
Sometimes, requires to detect the user voice volume.
To do this I am using volume-meter.js
library.
It returns pitch volume.
Use this value to draw a graphical representation.
Contents
1. Download volume-meter.js
- Download
volume-meter.js
from GitHub and copy it into your project directory. - Also, download the jQuery library.
2. HTML
Create index.html
file.
Created 2 buttons –
- To start voice recognition.
- To stop voice recognition.
Display recording status in the <span id=‘status’>
whether it is started or stopped.
Use <div id=‘voiceVolume’>
to display the user voice pitch in the horizontal bar.
Display said words in the <textarea id='saidwords'>
.
Included volume-meter.js
and the jQuery library.
Completed Code
<style type="text/css"> .recorder{ border: 1px solid black; width: 320px; height: 100px; text-align: center; padding-top: 50px; } #saidwords{ width: 320px; height: 100px; } #volumeBar{ width:200px; height: 10px; border: 1px solid black; position: relative; margin: 0 auto; } #voiceVolume{ width: 0px; height: 10px; background: green; } </style> <div class='recorder'> <input type="button" id="but_start" value='Start Recording' onclick='startSpeech();'> <input type="button" id="but_stop" value='Stop Recording' onclick='stopSpeech();'> <br><br> <span id='status'>Recording not started.</span> <!-- Volume bar --> <div id='volumeBar'><div id='voiceVolume' ></div> </div> </div> <br> Said Words -<br> <textarea id='saidwords'></textarea> <!-- Script --> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <script type='text/javascript' src='volume-meter.js'></script>
3. Script
meter
variable is used to create an instance of the volume meter.
Create an object of webkitSpeechRecognition()
and to detect voice continuously set recognition.continuous = true
.
recognition.onresult
is called when service returns a result. Display said words in the <textarea id='saidwords'>
.
Start Recording –
When Start Recording button gets clicked then call startSpeech()
function from where display “Recording Started.”
Message in the <span id=‘status’>
, clear the <textarea>
, and assign true
to recordingStarted
.
Call recognition.start()
to enable voice detection.
Stop Recording –
When Stop Recording button gets clicked then call stopSpeech()
function from where display “Recording Stopped.”
Message in the <span id=‘status’>
, and assign false
to recordingStarted
.
Call recognition.stop()
to stop voice detection.
Create voice pitch –
To detect stream define navigator.getuserMedia
from where call startUserMedia()
function.
In startUserMedia()
function creates an analyzer and connects the stream source.
Assign createAudioMeter(ctx)
to meter and connect with streamNode.
Call drawLoop()
function to create a pitch volume meter.
Calculate width –
Get the voice pitch volume and set minimum_volume = 130
. You can change the value if you want.
If recording starts then find the percentage and assign to the width
variable.
Update the <div id=‘voiceVolume’ >
width.
Completed Code
var meter = null; var WIDTH = 500; var recordingStarted = false; // initialize SpeechRecognition object let recognition = new webkitSpeechRecognition(); recognition.maxAlternatives = 1; recognition.continuous = true; // Detect the said words recognition.onresult = e => { var current = event.resultIndex; // Get a transcript of what was said. var transcript = event.results[current][0].transcript; // Add the current transcript with existing said values var noteContent = $('#saidwords').val(); noteContent += ' ' + transcript; $('#saidwords').val(noteContent); } // Stop recording function stopSpeech(){ // Change status $('#status').text('Recording Stopped.'); recordingStarted = false; // Stop recognition recognition.stop(); } // Start recording function startSpeech(){ try{ // calling it twice will throw.. $('#status').text('Recording Started.'); $('#saidwords').val(''); recordingStarted = true; // Start recognition recognition.start(); } catch(e){} } navigator.getUserMedia({audio: true}, startUserMedia, function(e) { __log('No live audio input: ' + e); }); function startUserMedia(stream) { const ctx = new AudioContext(); const analyser = ctx.createAnalyser(); const streamNode = ctx.createMediaStreamSource(stream); streamNode.connect(analyser); // Create a new volume meter and connect it. meter = createAudioMeter(ctx); streamNode.connect(meter); drawLoop(); } // Create pitch bar function drawLoop( time ) { var pitchVolume = meter.volume*WIDTH*1.4; var width = 0; // Pitch detection minimum volume var minimum_volume = 130; // Get width if Recording started if(recordingStarted){ if(pitchVolume < minimum_volume){ width = 0; }else if(pitchVolume >= minimum_volume && pitchVolume < (minimum_volume+20) ){ width = 10; }else if(pitchVolume >= (minimum_volume+20) && pitchVolume < (minimum_volume+40)){ width = 20; }else if(pitchVolume >= (minimum_volume+40) && pitchVolume < (minimum_volume+60)){ width = 30; }else if(pitchVolume >= (minimum_volume+60) && pitchVolume < (minimum_volume+80)){ width = 40; }else if(pitchVolume >= (minimum_volume+80) && pitchVolume < (minimum_volume+100)){ width = 50; }else if(pitchVolume >= (minimum_volume+100) && pitchVolume < (minimum_volume+120)){ width = 60; }else if(pitchVolume >= (minimum_volume+120) && pitchVolume < (minimum_volume+140)){ width = 70; }else if(pitchVolume >= (minimum_volume+140) && pitchVolume < (minimum_volume+160)){ width = 80; }else if(pitchVolume >= (minimum_volume+160) && pitchVolume < (minimum_volume+180)){ width = 90; }else if(pitchVolume >= (minimum_volume+180)){ width = 100; } } // Update width document.getElementById('voiceVolume').style.width = width+'%'; rafID = window.requestAnimationFrame( drawLoop ); }
4. Demo
5. Conclusion
I displayed the pitch volume bar horizontally which you also display vertically just need to update the CSS.
You can adjust the pitch detection value according to your requirement.
If you found this tutorial helpful then don't forget to share.