Web Speech API를 이용해 텍스트를 입력해보자
들어가며
최근 자사 웹 플랫폼을 한창 만들고 있습니다.. 새로운 요구사항이 들어왔는데, 바로 음성인식으로 텍스트 데이터를 입력할 수 있으면 좋겠다는 내용이었습니다. 자사 플랫폼 중에서 전문가의 리뷰를 받는 부분이 있는데, 이 때 전문가 분들이 타이핑을 하기 어려워하는 분들이 많다는 이유였습니다. 한 번도 해보진 않았지만, 일단 해보겠다고 하고 난 뒤 구현에 성공했습니다. 여기서는 그 과정에서 대해서 말해보려고 합니다.
디자인
처음 생각한 디자인은 Mac 의 받아쓰기 기능과 같습니다. 이 기능을 그대로 활용하면 좋겠지만, 아쉽게도 전문가 분들이 대부분 윈도우를 사용하시고 윈도우 11 부터 한국어를 지원하기 때문에 사용하기가 어렵습니다. 어쨋든 기능 디자인은 아래처럼 간단합니다.
- 마우스로 데이터를 입력할 부분을 클릭 해 커서를 활성화시킨다.
- 다음으로 받아쓰기 기능을 키고 말을 한다.
- 원할 때 받아쓰기 기능을 끈다.
구현
1. 음성 인식 기능
Web API에는 편리하게도 SpeechRecognition 기능이 존재합니다. 바로 음성 입력을 번역해주는 기능이죠. 다행히 한국어도 지원하기에 아래와 같이 해석된 문장을 입력받아 콜백을 적용할 수 있습니다. 브라우저 중에서는 이 기능을 지원하지 않는 경우도 있기에 아래와 같이 조건문을 설정했습니다. onresult 가 바로 콜백을 적용하는 문장입니다. 여기서 텍스트 영역이 선택된 경우 음성 인식 문장을 추가해주는 기능을 구현했습니다.
export const recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition)
if(recognition){
recognition.continuous = true;
recognition.interimResults = false;
recognition.lang = 'ko-KR'
recognition.onresult = (event) => {
const focusedComponent = getFocusedComponent()
const isTextAreaFocused = isTextArea(focusedComponent)
let interimTranscript = "";
for (let i = event.resultIndex; i < event.results.length; i++) {
const transcript = event.results[i][0].transcript;
console.log(transcript)
if (event.results[i].isFinal) {
interimTranscript=transcript
} else {
interimTranscript += transcript;
}
}
if(isTextAreaFocused){
focusedComponent.innerHTML += interimTranscript
}
}
}
else{
console.log("SpeechRecognition is not supported")
}
const getFocusedComponent = ():HTMLElement => {
return document.activeElement as HTMLElement
}
const isTextArea = (element:HTMLElement):boolean => {
return element.tagName === 'TEXTAREA'
}
2. 음성인식을 ON/OFF를 설정할 수 있는 버튼
음성 인식 지원 유무를 다시 검사하고 만약 지원하지 않다면 비어있는 컴포넌트를 반환하도록 합니다. recognition.start() 와 recognition.stop() 을 이용해 음성인식 유무를 활성화 할 수 있습니다.
import React from 'react'
import {Button} from "@mui/material";
import MicIcon from '@mui/icons-material/Mic';
import MicOffIcon from '@mui/icons-material/MicOff';
import {recognition} from "./SpeechRecognition";
const isSpeechRecognitionSupported = ():boolean => {
return 'webkitSpeechRecognition' in window || 'SpeechRecognition' in window;
}
const setSpeechRecognition= (isActivate : boolean) => {
if(!recognition){
throw new Error("SpeechRecognition is not supported")
}
if(isActivate){
recognition.start()
} else{
recognition.stop()
}
}
/**
* 받아쓰기 기능을 활성화, 비활성화 할 수 있는 버튼입니다.
* 브라우저가 음성인식을 사용하지 않는 경우 사용할 수 없습니다.
* autoVisible 속성을 true로 설정하면 음성인식이 지원되지 않는 경우 버튼이 보이지 않습니다.
* @param props
* @constructor
*/
const DictationActivateButton=({autoVisible = true})=>{
const [isActivated, setIsActivated] = React.useState(false);
const isSupported=isSpeechRecognitionSupported()
if(!isSupported && autoVisible){
return <></>
}
const onClick=()=> {
if(isSupported){
setSpeechRecognition(!isActivated)
setIsActivated(!isActivated)
}
else{
alert("음성인식을 지원하지 않는 브라우저입니다.")
}
}
return (
<Button onClick={onClick}>
{isActivated ? <MicIcon/> : <MicOffIcon/>}
</Button>
)
}
export default DictationActivateButton
결과
텍스트 영역을 클릭하고 말을 하면 잘 인식하는 모습을 볼 수 있습니다!