들어가며

최근 자사 웹 플랫폼을 한창 만들고 있습니다.. 새로운 요구사항이 들어왔는데, 바로 음성인식으로 텍스트 데이터를 입력할 수 있으면 좋겠다는 내용이었습니다. 자사 플랫폼 중에서 전문가의 리뷰를 받는 부분이 있는데, 이 때 전문가 분들이 타이핑을 하기 어려워하는 분들이 많다는 이유였습니다. 한 번도 해보진 않았지만, 일단 해보겠다고 하고 난 뒤 구현에 성공했습니다. 여기서는 그 과정에서 대해서 말해보려고 합니다.

디자인

처음 생각한 디자인은 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

결과

텍스트 영역을 클릭하고 말을 하면 잘 인식하는 모습을 볼 수 있습니다!

+ Recent posts