https://light9639.github.io/React-TTS/
โจ React ๋ง๋ Text To Speech ์์ ํ์ผ์ ๋๋ค. โจ
- React ์์ฑ
npm create-react-app my-app
# or
yarn create react-app my-app
- vite๋ฅผ ์ด์ฉํ์ฌ ํ๋ก์ ํธ๋ฅผ ์์ฑํ๋ ค๋ฉด
npm create vite@latest
# or
yarn create vite
- ํฐ๋ฏธ๋์์ ์คํ ํ ํ๋ก์ ํธ ์ด๋ฆ ๋ง๋ ํ React ์ ํ, Typescirpt ์ ํํ๋ฉด ์์ฑ ์๋ฃ.
useEffect
์์window.speechSynthesis.getVoices();
๋ฅผ ํตํด ์์ฑ ๋ณํ์ ํ ์ ์๋ค.
import { useEffect, useState } from 'react'
import reactLogo from './assets/react.svg'
import './App.css';
import { getSpeech } from "./utils/getSpeech";
function App() {
const [value, setValue] = useState("์๋
ํ์ธ์");
//์์ฑ ๋ณํ ๋ชฉ์๋ฆฌ preload
useEffect(() => {
window.speechSynthesis.getVoices();
}, []);
const handleInput = (e: { target: { value: any; }; }) => {
const { value } = e.target;
setValue(value);
};
const handleButton = () => {
getSpeech(value);
};
return (
<div className="App">
<div>
<a href="https://vitejs.dev" target="_blank">
<img src="/vite.svg" className="logo" alt="Vite logo" />
</a>
<a href="https://reactjs.org" target="_blank">
<img src={reactLogo} className="logo react" alt="React logo" />
</a>
</div>
<h1>TTS(ํ๊ตญ์ด)</h1>
<p>ํ
์คํธ๋ฅผ ์
๋ ฅํ๊ณ ์์ฑ ๋ณํ ๋ฒํผ์ ํด๋ฆญํ์ธ์.</p>
<div className="box">
<input onChange={handleInput} value={value} />
<button onClick={handleButton}>์์ฑ ๋ณํ</button>
</div>
</div>
)
}
export default App
window.speechSynthesis.getVoices();
ํจ์๋ฅผ ์ด์ฉํ์ฌ ๋๋ฐ์ด์ค์ ๋ด์ฅ๋ ์์ฑ์ ๊ฐ์ ธ์ฌ ์ ์๋ค.if ์กฐ๊ฑด์
์ ์ด์ฉํ์ฌ ํ๊ตญ์ด ์์ฑ์ด ์๋์ง๋ฅผ ํ์ธํ์ฌ, ํ๊ตญ์ด๊ฐ ์๋ค๋ฉด ์์ฑ์ด ๋์ค๊ฒ๋ ์ค์ ํ๋ค.
export const getSpeech = (text: any) => {
let voices: any[] = [];
//๋๋ฐ์ด์ค์ ๋ด์ฅ๋ voice๋ฅผ ๊ฐ์ ธ์จ๋ค.
const setVoiceList = () => {
voices = window.speechSynthesis.getVoices();
};
setVoiceList();
if (window.speechSynthesis.onvoiceschanged !== undefined) {
//voice list์ ๋ณ๊ฒฝ๋์๋, voice๋ฅผ ๋ค์ ๊ฐ์ ธ์จ๋ค.
window.speechSynthesis.onvoiceschanged = setVoiceList;
}
const speech = (txt: string | undefined) => {
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);
};
- ์์ฑ ๋ณํ ๋ฒํผ์ ํด๋ฆญํ๋ฉด ์นํ์ด์ง์์ input ์์ ํ ์คํธ ๋ด์ฉ์ ์ฝ์ด์ ์์ฑ ๋ณํ์ด ๋ฉ๋๋ค.