에러 메시지를 유저에게 음성으로 전달하는 기능이 필요했습니다.
카카오에서 제공하는 API를 이용하면 더 자연스러운 음성을 사용할 수 있지만, 유료인 관계로 Web Speech API의 interface를 사용하여 음성 변환 함수를 개발했습니다.
Web Speech API는 SpeechSynthesis (텍스트 -음성변환) 과 SpeechRecognition (비동기 스피치 인식)이 있습니다.
그 중 speechSynthesis, SpeechSynthesisUtterance 두 가지 interface를 이용하여 음성 인식을 개발했습니다.
이 두가지 interface에서 개발에 사용한 메서드와 프로퍼티를 먼저 설명하겠습니다.
SpeechSynthesis
컨트롤러 역할을 하는 interface입니다. 디바이스에 사용가능한 목소리의 정보를 가져오고, 스피치를 시작하고 정지할 수 있습니다.
메서드 | 기능 |
getVoices() | speechSynthesis 인터페이스의 메서드로 현재 사용하고 있는 디바이스의 사용 가능한 목소리들을 가지고 올 수 있습니다. |
speak() | utterance(speech)를 utterrace queue에 쌓아 음성으로 읽을 수 있도록 합니다. |
SpeechSynthesisUtterance
speech 요청을 표현하는 interface입니다. 무엇을 읽을 지 어떻게 읽을지에 대한 정보를 포함하고 있습니다.(e.g. language, pitch and volume.)
프로퍼티 | 설정 |
lang | 사용할 언어. 기본값은 lang 값 또는 user-agent default 값이 됩니다. |
pitch | 스피치 pitch. 기본값 1. 0-2 사이로 설정 가능합니다. |
rate | 스피치 속도. 기본값 1. 0.1에서 10사이로 설정 가능합니다. |
voice | 스피치 목소리. 설정되지 않으면 utterance 언어의 default 언어 세팅의 목소리로 설정됩니다. |
위의 메서드와 프로퍼티를 사용하여 TTS 함수를 아래와 같이 정의했습니다.
export const getSpeech = (text) => {
let voices = [];
//디바이스에 내장된 voice를 가져온다.
const setVoiceList = () => {
voices = window.speechSynthesis.getVoices();
};
setVoiceList();
if (window.speechSynthesis.onvoiceschanged !== undefined) {
//voice list에 변경됐을때, voice를 다시 가져온다.
window.speechSynthesis.onvoiceschanged = setVoiceList;
}
const speech = (txt) => {
const lang = "ko-KR";
const utterThis = new SpeechSynthesisUtterance(txt);
utterThis.lang = lang;
/* 한국어 vocie 찾기
디바이스 별로 한국어는 ko-KR 또는 ko_KR로 voice가 정의되어 있다.
*/
const kor_voice = voices.find(
(elem) => elem.lang === lang || elem.lang === lang.replace("-", "_")
);
//힌국어 voice가 있다면 ? utterance에 목소리를 설정한다 : 리턴하여 목소리가 나오지 않도록 한다.
if (kor_voice) {
utterThis.voice = kor_voice;
} else {
return;
}
//utterance를 재생(speak)한다.
window.speechSynthesis.speak(utterThis);
};
speech(text);
};
배포 후 1주일정도 사용하면서 현장에서 유저가 사용할때 음성 변환하는 데에 0.3 - 0.5초 정도 딜레이가 발생되는 것을 확인했습니다.
에러 메시지를 바로 유저가 인식할 수 있도록 음성으로 안내하는 기능이기 때문에, 딜레이를 해결하기 위해 콘솔에 찍어보니 디바이스에서 목소리를 가지고 오는 getVoices() 메세드에서 딜레이가 발생하는 것을 발견했고, getVoice()를 초기 렌더링시 호출될 수 있도록 useEffect에 넣어줬습니다.
window.speechSynthesis.getVoices()
출처
https://developer.mozilla.org/en-US/docs/Web/API/Web_Speech_API