Using the browser's speech recognizer as a pronunciation judge
Pronunciation scoring APIs charge per request and want your audio on their servers. We teach spoken English to learners in India, mostly on phones, and we wanted a free test that costs us nothing to run. So we let the browser's speech recognizer play the listener. The idea: minimal pairs Vest and west. Thin and tin. Ship and sheep. Each pair differs by one sound, and that's exactly the sound a lot of learners merge. If you say "vest" and a speech model trained on thousands of speakers writes down "west", a human listener probably hears "west" too. That's the whole test. Which pairs you get depends on your mother tongue, because the merges are predictable: var L1 = { hindi: ["vw", "zj", "tht", "thd", "ii"], tamil: ["pb", "kg", "fp", "zj", "thd"], bengali: ["bv", "ssh", "zj", "fp", "tht"], // 14 languages in all }; A Hindi speaker gets V/W, Z/J, TH/T, TH/D and short I versus long EE. A Tamil speaker gets P/B and K/G, which a Hindi speaker rarely needs. One word, six guesses The trick is maxAlternatives. Most demos read results[0][0] and throw the rest away. We keep all six: function hearOnce(lang, cb) { var rec = new (window.SpeechRecognition || window.webkitSpeechRecognition)(); rec.lang = lang || "en-IN"; rec.continuous = false; rec.interimResults = false; rec.maxAlternatives = 6; rec.onresult = function (e) { var alts = []; for (var i = 0; i < e.results[0].length; i++) alts.push(e.results[0][i].transcript.toLowerCase().trim()); cb(alts); }; rec.start(); } Then the judge looks at where the target word shows up: function judge(s, alts) { // s.w = target word, s.o = the other word in the pair if (!alts.length) return "unclear"; var top = words(alts[0]); if (top.indexOf(s.w) > -1) return "ok"; if (top.indexOf(s.o) > -1) return "merged"; if (has(alts, s.w)) return "close"; if (has(alts, s.o)) return "merged"; return "unclear"; } If "vest" is the top guess, you said it clearly. If "west" wins, you merged the sounds. And if "vest" only turns up as the fourth guess, the model wasn't sure, and that gets labelled Unclear. The alternatives carry the model's doubt. One transcript can't. An unclear result gets one retry, with a note showing what was heard. Choosing whose ears you're testing against rec.lang changes the listener, and for an accent test that's the most useful setting in the whole API. Set it to en-IN and the model has heard a lot of Indian English, so it forgives some merges a learner makes. Set it to en-US and it's stricter. The result screen says so: you tested against an Indian listener, switch to US English for a harder check. For someone preparing for a call with a US client, that's literally the question. Not "is this correct" in the abstract, but "will this listener understand me". The honest limits Your audio does leave the device. Chrome's recognizer sends it to Google for processing. The page says nothing reaches WizMantra, which is true, and we don't claim more than that. Firefox has no SpeechRecognition. There the test flips into ear mode: speechSynthesis plays one word of the pair and you pick which one you heard. If the ear can't split two sounds, the mouth usually can't either. Laptop mics lie. Fan noise and a cheap mic both produce false merges, so the result tells you to repeat any pair marked Merging before you work on it. One speaker, one model. It's a screening test. A tutor still has to listen. In our demos, most Hindi speakers fail V/W first: "vest" comes back as "west" almost every time. Try it The test is free and needs no sign-up: English pronunciation test. Pick your first language, press Start, say each word once. If you've used maxAlternatives for something other than search, I'd like to hear what you did with it. Drafted with help from an AI assistant. The code above is from the live tool and was checked against it.
This is a summary aggregated from Dev.to. Read the complete article on the original site:
Read full article at Dev.to