<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta content="initial-scale=1, minimum-scale=1, width=device-width" name="viewport"> <title>Speech recognition demo</title> <style> #info { font-size: 20px; } #headline { text-decoration: none } #results { font-size: 14px; font-weight: bold; border: 1px solid #ddd; padding: 15px; text-align: left; min-height: 150px; } #start_button { border: 2; background-color:transparent; padding: 2; font-weight: bold; } .final { color: black; padding-right: 3px; } .marquee { margin: 20px auto; } #buttons { margin: 10px 0; position: relative; top: -50px; } #copy { margin-top: 20px; } #copy > div { display: none; margin: 0 70px; } </style> <script> "use strict"; /* * Simple program to demo speech recognition * * Based on https://www.google.com/intl/en/chrome/demos/speech.html * * Must run on a remote server, and access via https not http. */ /* * Choose your language */ const langs = [['Afrikaans', ['af-ZA']], ['አማርኛ', ['am-ET']], ['Azərbaycanca', ['az-AZ']], ['বাংলা', ['bn-BD', 'বাংলাদেশ'], ['bn-IN', 'ভারত']], ['Bahasa Indonesia',['id-ID']], ['Bahasa Melayu', ['ms-MY']], ['Català', ['ca-ES']], ['Čeština', ['cs-CZ']], ['Dansk', ['da-DK']], ['Deutsch', ['de-DE']], ['English', ['en-AU', 'Australia'], ['en-CA', 'Canada'], ['en-IN', 'India'], ['en-KE', 'Kenya'], ['en-TZ', 'Tanzania'], ['en-GH', 'Ghana'], ['en-NZ', 'New Zealand'], ['en-NG', 'Nigeria'], ['en-ZA', 'South Africa'], ['en-PH', 'Philippines'], ['en-GB', 'United Kingdom'], ['en-US', 'United States']], ['Español', ['es-AR', 'Argentina'], ['es-BO', 'Bolivia'], ['es-CL', 'Chile'], ['es-CO', 'Colombia'], ['es-CR', 'Costa Rica'], ['es-EC', 'Ecuador'], ['es-SV', 'El Salvador'], ['es-ES', 'España'], ['es-US', 'Estados Unidos'], ['es-GT', 'Guatemala'], ['es-HN', 'Honduras'], ['es-MX', 'México'], ['es-NI', 'Nicaragua'], ['es-PA', 'Panamá'], ['es-PY', 'Paraguay'], ['es-PE', 'Perú'], ['es-PR', 'Puerto Rico'], ['es-DO', 'República Dominicana'], ['es-UY', 'Uruguay'], ['es-VE', 'Venezuela']], ['Euskara', ['eu-ES']], ['Filipino', ['fil-PH']], ['Français', ['fr-FR']], ['Basa Jawa', ['jv-ID']], ['Galego', ['gl-ES']], ['ગુજરાતી', ['gu-IN']], ['Hrvatski', ['hr-HR']], ['IsiZulu', ['zu-ZA']], ['Íslenska', ['is-IS']], ['Italiano', ['it-IT', 'Italia'], ['it-CH', 'Svizzera']], ['ಕನ್ನಡ', ['kn-IN']], ['ភាសាខ្មែរ', ['km-KH']], ['Latviešu', ['lv-LV']], ['Lietuvių', ['lt-LT']], ['മലയാളം', ['ml-IN']], ['मराठी', ['mr-IN']], ['Magyar', ['hu-HU']], ['ລາວ', ['lo-LA']], ['Nederlands', ['nl-NL']], ['नेपाली भाषा', ['ne-NP']], ['Norsk bokmål', ['nb-NO']], ['Polski', ['pl-PL']], ['Português', ['pt-BR', 'Brasil'], ['pt-PT', 'Portugal']], ['Română', ['ro-RO']], ['සිංහල', ['si-LK']], ['Slovenščina', ['sl-SI']], ['Basa Sunda', ['su-ID']], ['Slovenčina', ['sk-SK']], ['Suomi', ['fi-FI']], ['Svenska', ['sv-SE']], ['Kiswahili', ['sw-TZ', 'Tanzania'], ['sw-KE', 'Kenya']], ['ქართული', ['ka-GE']], ['Հայերեն', ['hy-AM']], ['தமிழ்', ['ta-IN', 'இந்தியா'], ['ta-SG', 'சிங்கப்பூர்'], ['ta-LK', 'இலங்கை'], ['ta-MY', 'மலேசியா']], ['తెలుగు', ['te-IN']], ['Tiếng Việt', ['vi-VN']], ['Türkçe', ['tr-TR']], ['اُردُو', ['ur-PK', 'پاکستان'], ['ur-IN', 'بھارت']], ['Ελληνικά', ['el-GR']], ['български', ['bg-BG']], ['Pусский', ['ru-RU']], ['Српски', ['sr-RS']], ['Українська', ['uk-UA']], ['한국어', ['ko-KR']], ['中文', ['cmn-Hans-CN', '普通话 (中国大陆)'], ['cmn-Hans-HK', '普通话 (香港)'], ['cmn-Hant-TW', '中文 (台灣)'], ['yue-Hant-HK', '粵語 (香港)']], ['日本語', ['ja-JP']], ['हिन्दी', ['hi-IN']], ['ภาษาไทย', ['th-TH']]]; // Globals var recognizing = false; var ignore_onend; var start_timestamp; var recognition; window.onload = function () { for (let i = 0; i < langs.length; i++) { select_language.options[i] = new Option(langs[i][0], i); } select_language.selectedIndex = 10; updateCountry(); select_dialect.selectedIndex = 11; showInfo('info_start'); /* * Set up recognizer */ if (!('webkitSpeechRecognition' in window)) { //*1 Set up recognizer upgrade(); } else { start_button.style.display = 'inline-block'; recognition = new webkitSpeechRecognition(); //*1 recognition.continuous = true; //*1 recognition.interimResults = false; //*1 let final_transcript = ''; //*1 /* * Callbacks from recognizer */ // When it starts or restarts recognition.onstart = function() { //*2 Recognizer callbacks recognizing = true; //*2 showInfo('info_speak_now'); //*2 }; // Things that can go wrong recognition.onerror = function(event) { //*2 if (event.error == 'no-speech') { //*2 showInfo('info_no_speech'); //*2 ignore_onend = true; //*2 } if (event.error == 'audio-capture') { showInfo('info_no_microphone'); ignore_onend = true; } if (event.error == 'not-allowed') { if (event.timeStamp - start_timestamp < 100) { showInfo('info_blocked'); } else { showInfo('info_denied'); } ignore_onend = true; } }; // Intermediate or final result of recognition recognition.onresult = function(event) { //*3 We take final result if (typeof(event.results) == 'undefined') { recognition.onend = null; recognition.stop(); upgrade(); return; } // event.results is an array of the recognized strings for (let i = event.resultIndex; i < event.results.length; ++i) { //*3 if (event.results[i].isFinal) { //*3 doit (event.results[i][0].transcript) //*4 Call our demo app final_transcript += event.results[i][0].transcript + "\n"; final_span.innerHTML = linebreak(final_transcript); } } } } } // User message about browser function upgrade() { start_button.style.visibility = 'hidden'; showInfo('info_upgrade'); } // Convert line breaks to HTML const two_line = /\n\n/g; const one_line = /\n/g; function linebreak(s) { return s.replace(two_line, '<p></p>').replace(one_line, '<br>'); } function startButton(event) { // Stop if (recognizing) { recognition.stop(); showInfo('info_start'); recognizing = false } // Start else { recognition.lang = select_dialect.value; recognition.start(); ignore_onend = false; showInfo('info_allow'); start_timestamp = event.timeStamp; } } function updateCountry() { for (let i = select_dialect.options.length - 1; i >= 0; i--) { select_dialect.remove(i); } let list = langs[select_language.selectedIndex]; for (let i = 1; i < list.length; i++) { select_dialect.options.add(new Option(list[i][1], list[i][0])); } select_dialect.style.visibility = list[1].length == 1 ? 'hidden' : 'visible'; } // Display selected message, hide others function showInfo(s) { if (s) { for (let child = info.firstChild; child; child = child.nextSibling) { if (child.style) { child.style.display = child.id == s ? 'inline' : 'none'; } } info.style.visibility = 'visible'; } else { info.style.visibility = 'hidden'; } } /* *************************************************************************** * Voice drawing program, just an example of usage of above code *************************************************************************** */ // "Roy G Biv" colors only const colors = ["red", "orange", "yellow", "green", "blue", "indigo", "violet"] //*6 Show functional programming style, optional // Limited set of shapes const shapes = ["square", "rectangle", "circle", "ellipse", "triangle"] //*6 function doit (string) { //*5 Demo app: voice drawing /* * Example of something you could do with the recognized text */ string = string.toLowerCase() // Search for a color, else we choose black let color = colors.filter ( //*6 function (c) { //*6 return string.match (new RegExp ("\\b" + c + "\\b")) //*6 }) [0] //*6 // Search for a shape, else we don't draw let shape = shapes.filter ( //*6 function (s) { //*6 return string.match (new RegExp ("\\b" + s + "\\b")) //*6 }) [0] //*6 // If found a shape, draw it if (shape) { //*5 let gc = myCanvas.getContext ("2d") gc.fillStyle = color? color: "black" //*5 // Generate some random coordinates let x = 50 + Math.floor (400 * Math.random ()) let y = 50 + Math.floor (400 * Math.random ()) let w = 20 + Math.floor (100 * Math.random ()) let h = 20 + Math.floor (100 * Math.random ()) if (shape=="square") { //*5 gc.fillRect (x, y, w, w) //*5 } else if (shape=="rectangle") { //*5 gc.fillRect (x, y, w, h) //*5 } else if (shape=="circle") { //*5 gc.beginPath(); //*5 gc.arc (x, y, w/2, 0, Math.PI * 2); //*5 gc.fill(); //*5 } else if (shape=="ellipse") { //*5 gc.beginPath(); gc.ellipse (x, y, w/2, h/2, 0, 0, Math.PI * 2); gc.fill(); } else if (shape=="triangle") { //*5 gc.beginPath(); gc.moveTo (x + w/2, y); gc.lineTo (x, y+h); gc.lineTo (x+w, y+h); gc.lineTo (x + w/2, y); gc.fill(); } } // For testing, display the understood message (2 words) console.log ("Color = " + color + ", Shape = " + shape) } </script> </head> <body> <div class="browser-landing" id="main"> <div class="compact marquee-stacked" id="marquee"> <div class="marquee-copy"> <h1> <a href="https://w3c.github.io/speech-api/">Web Speech API</a> Demonstration </h1> </div> </div> <div class="compact marquee"> <div id="info"> <p id="info_start"> Click on the Start/stop button and begin speaking. </p> <p id="info_speak_now" style="display:none"> Speak now. </p> <p id="info_no_speech" style="display:none"> No speech was detected. You may need to adjust your <a href= "//support.google.com/chrome/bin/answer.py?hl=en&answer=1407892">microphone settings</a>. </p> <p id="info_no_microphone" style="display:none"> No microphone was found. Ensure that a microphone is installed and that <a href="//support.google.com/chrome/bin/answer.py?hl=en&answer=1407892"> microphone settings</a> are configured correctly. </p> <p id="info_allow" style="display:none"> Click the "Allow" button above to enable your microphone. </p> <p id="info_denied" style="display:none"> Permission to use microphone was denied. </p> <p id="info_blocked" style="display:none"> Permission to use microphone is blocked. To change, go to chrome://settings/contentExceptions#media-stream </p> <p id="info_upgrade" style="display:none"> Web Speech API is not supported by this browser. Use <a href= "//www.google.com/chrome">Chrome</a> version 25 or later. </p> </div> <div id="div_start"> <button id="start_button" onclick="startButton(event)">Start/stop</button> </div> <div id="results"> <span class="final" id="final_span"></span> </div> <div class="compact marquee" id="div_language"> <select id="select_language" onchange="updateCountry()"> </select> <select id="select_dialect"> </select> </div> </div> </div> <canvas id="myCanvas" width="500" height="500" style="border: solid"></canvas> </body> </html>