<!DOCTYPE html> <html> <head> <scriptsrc='http://cdnjs.cloudflare.com/ajax/libs/annyang/2.6.0/annyang.min.js'></script> <script> annyang.start({ autoRestart: false, continuous: true }) var recognition = annyang.getSpeechRecognizer(); var final_transcript = ''; recognition.interimResults = true; recognition.onresult = function(event) { var interim_transcript = ''; final_transcript = ''; for (var i = event.resultIndex; i < event.results.length; ++i) { if (event.results[i].isFinal) { final_transcript += event.results[i][0].transcript; console.log("final_transcript="+final_transcript); //annyang.trigger(final_transcript); //If the sentence is "final" for the Web Speech API, we can try to trigger the sentence } else { interim_transcript += event.results[i][0].transcript; console.log("interim_transcript="+interim_transcript); } } document.getElementById('result').innerHTML = '중간값:='+interim_transcript+'<br/>결과값='+final_transcript; console.log('interim='+interim_transcript+'|final='+final_transcript); }; </script> </head> <bodyclass=""id="grid"> <br/><br/> 한국어 음성 처리 테스트<br/><br/> <divid='result'> 결과가 없습니다. </div> </body> </html>
$ vi text.html
html 파일을 브라우저로 열어보고 테스트를 하면 영어(English)만 가능한 것을 확인할 수 있습니다.
다운받은 annyang.js에서 recognition.lang = 'en-US'; 를 recognition.lang = 'ko';
ko(Korean)으로 변경합니다.
source에서 주석을 제외한 코드 부분은 다음과 같습니다.
//! annyang //! version : 2.6.0 //! author : Tal Ater @TalAter //! license : MIT //! https://www.TalAter.com/annyang/ (function(root, factory) {
....
....
//! annyang //! version : 2.6.0 //! author : Tal Ater @TalAter //! license : MIT //! https://www.TalAter.com/annyang/ (function(root, factory) { 'use strict'; if (typeof define === 'function' && define.amd) { // AMD + global define([], function() { return (root.annyang = factory(root)); }); } elseif (typeof module === 'object' && module.exports) { // CommonJS module.exports = factory(root); } else { // Browser globals root.annyang = factory(root); } }(typeof window !== 'undefined' ? window : this, function(root, undefined) { 'use strict'; var annyang; // Get the SpeechRecognition object, while handling browser prefixes var SpeechRecognition = root.SpeechRecognition || root.webkitSpeechRecognition || root.mozSpeechRecognition || root.msSpeechRecognition || root.oSpeechRecognition; // Check browser support // This is done as early as possible, to make it as fast as possible for unsupported browsers if (!SpeechRecognition) { returnnull; } var commandsList = []; var recognition; var callbacks = { start: [], error: [], end: [], soundstart: [], result: [], resultMatch: [], resultNoMatch: [], errorNetwork: [], errorPermissionBlocked: [], errorPermissionDenied: [] }; var autoRestart; var lastStartedAt = 0; var autoRestartCount = 0; var debugState = false; var debugStyle = 'font-weight: bold; color: #00f;'; var pauseListening = false; var isListening = false; // The command matching code is a modified version of Backbone.Router by Jeremy Ashkenas, under the MIT license. var optionalParam = /\s*\((.*?)\)\s*/g; var optionalRegex = /(\(\?:[^)]+\))\?/g; var namedParam = /(\(\?)?:\w+/g; var splatParam = /\*\w+/g; var escapeRegExp = /[\-{}\[\]+?.,\\\^$|#]/g; var commandToRegExp = function(command) { command = command.replace(escapeRegExp, '\\$&') .replace(optionalParam, '(?:$1)?') .replace(namedParam, function(match, optional) { return optional ? match : '([^\\s]+)'; }) .replace(splatParam, '(.*?)') .replace(optionalRegex, '\\s*$1?\\s*'); returnnew RegExp('^' + command + '$', 'i'); }; // This method receives an array of callbacks to iterate over, and invokes each of them var invokeCallbacks = function(callbacks, ...args) { callbacks.forEach(function(callback) { callback.callback.apply(callback.context, args); }); }; var isInitialized = function() { return recognition !== undefined; }; // method for logging in developer console when debug mode is on var logMessage = function(text, extraParameters) { if (text.indexOf('%c') === -1 && !extraParameters) { console.log(text); } else { console.log(text, extraParameters || debugStyle); } }; var initIfNeeded = function() { if (!isInitialized()) { annyang.init({}, false); } }; var registerCommand = function(command, callback, originalPhrase) { commandsList.push({ command, callback, originalPhrase }); if (debugState) { logMessage('Command successfully loaded: %c'+originalPhrase, debugStyle); } }; var parseResults = function(results) { invokeCallbacks(callbacks.result, results); var commandText; // go over each of the 5 results and alternative results received (we've set maxAlternatives to 5 above) for (let i = 0; i<results.length; i++) { // the text recognized commandText = results[i].trim(); if (debugState) { logMessage('Speech recognized: %c'+commandText, debugStyle); } // try and match recognized text to one of the commands on the list for (let j = 0, l = commandsList.length; j < l; j++) { var currentCommand = commandsList[j]; var result = currentCommand.command.exec(commandText); if (result) { var parameters = result.slice(1); if (debugState) { logMessage('command matched: %c'+currentCommand.originalPhrase, debugStyle); if (parameters.length) { logMessage('with parameters', parameters); } } // execute the matched command currentCommand.callback.apply(this, parameters); invokeCallbacks(callbacks.resultMatch, commandText, currentCommand.originalPhrase, results); return; } } } invokeCallbacks(callbacks.resultNoMatch, results); }; annyang = { init: function(commands, resetCommands = true) { // Abort previous instances of recognition already running if (recognition && recognition.abort) { recognition.abort(); } // initiate SpeechRecognition recognition = new SpeechRecognition(); // Set the max number of alternative transcripts to try and match with a command recognition.maxAlternatives = 5; // In HTTPS, turn off continuous mode for faster results. // In HTTP, turn on continuous mode for much slower results, but no repeating security notices recognition.continuous = root.location.protocol === 'http:'; // Sets the language to the default 'en-US'. This can be changed with annyang.setLanguage() recognition.lang = 'ko'; recognition.onstart = function() { isListening = true; invokeCallbacks(callbacks.start); }; recognition.onsoundstart = function() { invokeCallbacks(callbacks.soundstart); }; recognition.onerror = function(event) { invokeCallbacks(callbacks.error, event); switch (event.error) { case'network': invokeCallbacks(callbacks.errorNetwork, event); break; case'not-allowed': case'service-not-allowed': // if permission to use the mic is denied, turn off auto-restart autoRestart = false; // determine if permission was denied by user or automatically. if (new Date().getTime()-lastStartedAt < 200) { invokeCallbacks(callbacks.errorPermissionBlocked, event); } else { invokeCallbacks(callbacks.errorPermissionDenied, event); } break; } }; recognition.onend = function() { isListening = false; invokeCallbacks(callbacks.end); // annyang will auto restart if it is closed automatically and not by user action. if (autoRestart) { // play nicely with the browser, and never restart annyang automatically more than once per second var timeSinceLastStart = new Date().getTime()-lastStartedAt; autoRestartCount += 1; if (autoRestartCount % 10 === 0) { if (debugState) { logMessage('Speech Recognition is repeatedly stopping and starting. See http://is.gd/annyang_restarts for tips.'); } } if (timeSinceLastStart < 1000) { setTimeout(function() { annyang.start({ paused: pauseListening }); }, 1000-timeSinceLastStart); } else { annyang.start({ paused: pauseListening }); } } }; recognition.onresult = function(event) { if(pauseListening) { if (debugState) { logMessage('Speech heard, but annyang is paused'); } returnfalse; } // Map the results to an array var SpeechRecognitionResult = event.results[event.resultIndex]; var results = []; for (let k = 0; k<SpeechRecognitionResult.length; k++) { results[k] = SpeechRecognitionResult[k].transcript; } parseResults(results); }; // build commands list if (resetCommands) { commandsList = []; } if (commands.length) { this.addCommands(commands); } }, start: function(options) { initIfNeeded(); options = options || {}; if (options.paused !== undefined) { pauseListening = !!options.paused; } else { pauseListening = false; } if (options.autoRestart !== undefined) { autoRestart = !!options.autoRestart; } else { autoRestart = true; } if (options.continuous !== undefined) { recognition.continuous = !!options.continuous; } lastStartedAt = new Date().getTime(); try { recognition.start(); } catch(e) { if (debugState) { logMessage(e.message); } } }, abort */ abort: function() { autoRestart = false; autoRestartCount = 0; if (isInitialized()) { recognition.abort(); } }, pause: function() { pauseListening = true; }, resume: function() { annyang.start(); }, debug: function(newState = true) { debugState = !!newState; }, setLanguage: function(language) { initIfNeeded(); recognition.lang = language; }, addCommands: function(commands) { var cb; initIfNeeded(); for (let phrase in commands) { if (commands.hasOwnProperty(phrase)) { cb = root[commands[phrase]] || commands[phrase]; if (typeof cb === 'function') { // convert command to regex then register the command registerCommand(commandToRegExp(phrase), cb, phrase); } elseif (typeof cb === 'object' && cb.regexp instanceof RegExp) { // register the command registerCommand(new RegExp(cb.regexp.source, 'i'), cb.callback, phrase); } else { if (debugState) { logMessage('Can not register command: %c'+phrase, debugStyle); } continue; } } } }, removeCommands: function(commandsToRemove) { if (commandsToRemove === undefined) { commandsList = []; } else { commandsToRemove = Array.isArray(commandsToRemove) ? commandsToRemove : [commandsToRemove]; commandsList = commandsList.filter(command => { for (let i = 0; i<commandsToRemove.length; i++) { if (commandsToRemove[i] === command.originalPhrase) { returnfalse; } } returntrue; }); } }, addCallback: function(type, callback, context) { var cb = root[callback] || callback; if (typeof cb === 'function' && callbacks[type] !== undefined) { callbacks[type].push({callback: cb, context: context || this}); } }, removeCallback: function(type, callback) { var compareWithCallbackParameter = function(cb) { return cb.callback !== callback; }; // Go over each callback type in callbacks store object for (let callbackType in callbacks) { if (callbacks.hasOwnProperty(callbackType)) { // if this is the type user asked to delete, or he asked to delete all, go ahead. if (type === undefined || type === callbackType) { // If user asked to delete all callbacks in this type or all types if (callback === undefined) { callbacks[callbackType] = []; } else { // Remove all matching callbacks callbacks[callbackType] = callbacks[callbackType].filter(compareWithCallbackParameter); } } } } }, isListening: function() { return isListening && !pauseListening; }, getSpeechRecognizer: function() { return recognition; }, trigger: function(sentences) { if(!annyang.isListening()) { if (debugState) { if (!isListening) { logMessage('Cannot trigger while annyang is aborted'); } else { logMessage('Speech heard, but annyang is paused'); } } return; } if (!Array.isArray(sentences)) { sentences = [sentences]; } parseResults(sentences); } }; return annyang; }));
작성한 javascript 파일로 연동하기 위해 html 부분도 다시 수정을 합니다.
기존의 <script src='http://cdnjs.cloudflare.com/ajax/libs/annyang/2.6.0/annyang.min.js'></script>를 삭제하고 <script src=’annyang.js’></script>로 수정합니다.
<!DOCTYPE html> <html> <head> <scriptsrc='annyang.js'></script> <script> annyang.start({ autoRestart: false, continuous: true }) var recognition = annyang.getSpeechRecognizer(); var final_transcript = ''; recognition.interimResults = true; recognition.onresult = function(event) { var interim_transcript = ''; final_transcript = ''; for (var i = event.resultIndex; i < event.results.length; ++i) { if (event.results[i].isFinal) { final_transcript += event.results[i][0].transcript; console.log("final_transcript="+final_transcript); //annyang.trigger(final_transcript); //If the sentence is "final" for the Web Speech API, we can try to trigger the sentence } else { interim_transcript += event.results[i][0].transcript; console.log("interim_transcript="+interim_transcript); } } document.getElementById('result').innerHTML = '중간값:='+interim_transcript+'<br/>결과값='+final_transcript; console.log('interim='+interim_transcript+'|final='+final_transcript); }; </script> </head> <bodyclass=""id="grid"> <br/><br/> 한국어 음성 처리 테스트<br/><br/> <divid='result'> 결과가 없습니다. </div> </body> </html>
Annyang이 응답 할 명령을 추가하십시오. init ()과 구문이 비슷하지만 기존 명령을 제거하지 않습니다.
예 :
var commands = {'hello :name': helloFunction, 'howdy': helloFunction}; var commands2 = {'hi': helloFunction}; annyang.addCommands(commands); annyang.addCommands(commands2); // annyang will now listen to all three commands
removeCommands ([commandsToRemove])
기존 명령을 제거하십시오. 하나의 문구, 여러 개의 문구 또는 체계적으로 호출됩니다. 모든 명령을 제거하려면 매개 변수를 전달하지 마십시오.
예 :
var commands = {'hello': helloFunction, 'howdy': helloFunction, 'hi': helloFunction}; // Remove all existing commands annyang.removeCommands(); // Add some commands annyang.addCommands(commands); // Don't respond to hello annyang.removeCommands('hello'); // Don't respond to howdy or hi annyang.removeCommands(['howdy', 'hi']);
error - 브라우저의 Speech Recogntion 엔진이 오류를 반환하면 시작됩니다.이 일반 오류 콜백 뒤에는보다 정확한 오류 콜백이 표시됩니다 (둘 다 정의되면 실행됩니다). 첫 번째 인수로 오류 이벤트와 함께 콜백 함수가 호출됩니다.
errorNetwork - 네트워크 오류로 인해 음성 인식이 실패 할 때 발생합니다. 첫 번째 인수로 오류 이벤트와 함께 콜백 함수가 호출됩니다.
errorPermissionBlocked- 브라우저가 음성 인식 사용 권한 요청을 차단하면 시작됩니다. 오류 이벤트를 첫 번째 인수로 사용하여 콜백 함수가 호출됩니다.
errorPermissionDenied- 사용자가 음성 인식 사용 권한 요청을 차단하면 시작됩니다. 오류 이벤트를 첫 번째 인수로 사용하여 콜백 함수가 호출됩니다.
end - 브라우저의 음성 인식 엔진이 중지되면 시작됩니다.
result- 연설이 확인 되 자마자 해고당했습니다. 이 일반 콜백 뒤에는 resultMatch또는 resultNoMatch콜백이옵니다. 이 이벤트에 대한 콜백 함수는 사용자가 첫 번째 인수로 말할 수있는 가능한 구문 배열로 호출됩니다
resultMatch - annyang이 사용자가 말한 것과 등록 된 명령을 일치시킬 수있을 때 시작됩니다.이 이벤트에 대한 콜백 함수는 다음 순서로 세 개의 인수로 호출됩니다. * 사용자가 명령과 일치하는 구를 말합니다. * 일치 한 명령 * 사용자가 말한 가능한 대체 구문의 배열
resultNoMatch- 사용자가 등록한 명령 중 하나와 일치하지 않는다고 말하면 발동됩니다. 이 이벤트에 대한 콜백 함수는 사용자가 첫 번째 인수로 말할 수있는 가능한 구문의 배열로 호출됩니다
예 :
annyang.addCallback('error', function() { $('.myErrorText').text('There was an error!'); }); annyang.addCallback('resultMatch', function(userSaid, commandText, phrases) { console.log(userSaid); // sample output: 'hello' console.log(commandText); // sample output: 'hello (there)' console.log(phrases); // sample output: ['hello', 'halo', 'yellow', 'polo', 'hello kitty'] }); // pass local context to a global function called notConnected annyang.addCallback('errorNetwork', notConnected, this);
removeCallback (유형, 콜백)
이벤트에서 콜백을 제거합니다.
해당 이벤트 유형에서 해당 콜백 명령을 제거하려면 이벤트 이름과 콜백 명령을 전달하십시오.
해당 이벤트 유형에서 모든 콜백 명령을 제거하려면 이벤트 이름 만 전달하십시오.
모든 이벤트 유형에서 해당 콜백 명령을 제거하려면 이벤트 이름과 콜백 명령으로 undefined를 전달하십시오.
모든 이벤트 유형에서 모든 콜백 명령을 제거하는 매개 변수를 전달하지 않습니다.
예 :
annyang.addCallback('start', myFunction1); annyang.addCallback('start', myFunction2); annyang.addCallback('end', myFunction1); annyang.addCallback('end', myFunction2); // Remove all callbacks from all events: annyang.removeCallback(); // Remove all callbacks attached to end event: annyang.removeCallback('end'); // Remove myFunction2 from being called on start: annyang.removeCallback('start', myFunction2); // Remove myFunction1 from being called on all events: annyang.removeCallback(undefined, myFunction1);
isListening ()
음성 인식이 현재 유효한 경우 true를 반환합니다. 음성 인식이 꺼져 있거나 양양이 일시 중지 된 경우 false를 반환합니다.
getSpeechRecognizer ()
annyang이 사용하는 브라우저의 SpeechRecognition 객체의 인스턴스를 반환합니다. 브라우저의 음성 인식 엔진에 직접 액세스하려는 경우에 유용합니다.
반환:
SpeechRecognition 브라우저의 음성 인식기는 현재 annyang에서 사용하고 있습니다.
trigger(string|array)
인식되는 음성을 시뮬레이트합니다. 이것은 음성 인식이 음성을 감지 할 때와 동일한 이벤트 및 동작을 트리거합니다.
단일 문장을 포함하는 문자열 또는 명령 중 하나가 일치 할 때까지 순서대로 검사 할 여러 문장을 포함하는 배열을 사용할 수 있습니다 (음성 인식 대안이 구문 분석되는 방식과 유사)
예 :
annyang.trigger('Time for some thrilling heroics'); annyang.trigger( ['Time for some thrilling heroics', 'Time for some thrilling aerobics'] );