--{{0}}--
The SpeechRecognition API lets you convert spoken words into text right in the browser—no server calls needed. Modern Chromium-based browsers (Chrome, Edge, Opera) support it; Firefox and Safari currently do not.
Try it on LiaScript:
See the project on Github:
https://github.com/liaTemplates/Speech-Recognition-Quiz
--{{1}}--
Like with other LiaScript templates, there are three ways to integrate this feature into your project, but the easiest way is to copy the import statement into the header of your LiaScript course.
{{1}}
-
Load the latest macros via (this might cause breaking changes)
import: https://raw.githubusercontent.com/LiaTemplates/Speech-Recognition-Quiz/refs/heads/main/README.mdor the current version 0.0.1 via:
import: https://raw.githubusercontent.com/LiaTemplates/Speech-Recognition-Quiz/refs/tags/0.0.1/README.md -
Copy the definitions into your Project
-
Clone this repository on GitHub
This macro runs once at load time and reports whether the API is available in your learner’s browser.
@SpeechRecognition.support
@SpeechRecognition.support
SpeechRecognition uses BCP-47 language tags. Common examples:
- en-US: American English
- en-GB: British English
- de-DE: German (Germany)
- fr-FR: French (France)
- es-ES: Spanish (Spain)
- zh-CN: Mandarin Chinese (Simplified)
- ja-JP: Japanese
- ar-SA: Arabic (Saudi Arabia)
You can look up others at IANA Language Subtag Registry.
The [[!]] syntax is used to create generic quizzes in LiaScript.
As with all quizzes in LiaScript, you can add hints and a solution and more settings to it, if you want to.
The two parameters that you need to provide are the language code and the phrase you want the learner to say.
- lang: BCP-47 code
- phrase: expected text (punctuation is ignored)
[[!]]
@SpeechRecognition(en-US,Hello world)Result:
[[!]] @SpeechRecognition(en-US,Hello world)
{{1}}
In order to remove the default solution button, you can add the data-solution-button="off" attribute to the quiz.
This will hide the solution button and only show the quiz itself.
<!-- data-solution-button="off" -->
[[!]]
@SpeechRecognition(en-US,Hello world)Result:
[[!]] @SpeechRecognition(en-US,Hello world)
--{{2}}--
For more information on quizzes and their settings, please refer to the LiaScript documentation:
--{{0}}--
This macro works the same way as the one above, but it returns the actual transcript on mismatch. This is useful for providing feedback to learners.
<!-- data-solution-button="off" -->
[[!]]
@SpeechRecognition.withFeedback(fr-FR,Bonjour le monde)Result:
[[!]] @SpeechRecognition.withFeedback(fr-FR,Bonjour le monde)
Say "Good morning" in American English.
[[!]]
@SpeechRecognition(en-US,Good morning)
What about "Good morning" in German?
[[!]]
@SpeechRecognition(de-DE,Guten Morgen)
French (with feedback): Please say "Je m'appelle Claude".
[[!]]
@SpeechRecognition.withFeedback(fr-FR,Je m'appelle Claude)
How are you in Spanish?
[[!]]
@SpeechRecognition(es-ES,Cómo estás?)
Mandarin Chinese, please say "你好世界" (Nǐ hǎo shìjiè).
[[!]]
@SpeechRecognition.withFeedback(zh-CN,你好世界)
--{{0}}--
If you want to minimize loading effort in your LiaScript project, you can also copy this code and paste it into your main comment header, but this is the entire implementation.
@SpeechRecognition.support
<script modify="false" run-once>
// Vendor prefix
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
if (!SpeechRecognition) {
"LIASCRIPT: > 'Speech Recognition' not supported in this browser. Try Chrome, Opera, or Edge.";
} else {
"LIASCRIPT: > Your browser does support 'Speech Recognition' ..."
}
</script>
@end
@SpeechRecognition
<script>
// Vendor prefix
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
if (!SpeechRecognition) {
alert('SpeechRecognition not supported. Try Chrome, Opera, or Edge.');
} else {
const recognition = new SpeechRecognition();
recognition.lang = '@0';
recognition.interimResults = false;
recognition.continuous = false;
const solution = "@1".toLowerCase()
.replace(/(\.|\?|\!|\,|\-|\;)/g," ")
.replace(/[ ]+/g," ")
.trim();
recognition.onresult = ev => {
let t = ev.results[0][0].transcript?.toLowerCase().trim() || '';
if (t === solution) {
send.lia("true");
} else {
send.lia("Please try again …",[],false);
}
};
recognition.onerror = ev => send.lia("Error: "+ev.error,[],false);
recognition.onend = () => console.log('Speech recognition ended.');
recognition.start();
}
"LIA: wait"
</script>
@end
@SpeechRecognition.withFeedback
<script>
// Vendor prefix
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
if (!SpeechRecognition) {
alert('SpeechRecognition not supported. Try Chrome, Opera, or Edge.');
} else {
const recognition = new SpeechRecognition();
recognition.lang = '@0';
recognition.interimResults = false;
recognition.continuous = false;
const solution = "@1".toLowerCase()
.replace(/(\.|\?|\!|\,|\-|\;)/g," ")
.replace(/[ ]+/g," ")
.trim();
recognition.onresult = ev => {
let t = ev.results[0][0].transcript?.toLowerCase().trim() || '';
if (t === solution) {
send.lia("true");
} else {
send.lia(t,[],false);
}
};
recognition.onerror = ev => send.lia("Error: "+ev.error,[],false);
recognition.onend = () => console.log('Speech recognition ended.');
recognition.start();
}
"LIA: wait"
</script>
@end