Skip to content

๐ŸŽ™๏ธReact ๋งŒ๋“  Text To Speech ์˜ˆ์ œ ํŒŒ์ผ์ž…๋‹ˆ๋‹ค.

Notifications You must be signed in to change notification settings

light9639/React-TTS

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

6 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐ŸŽ™๏ธ React ๋งŒ๋“  Text To Speech ์˜ˆ์ œ ํŒŒ์ผ์ž…๋‹ˆ๋‹ค.

:octocat: https://light9639.github.io/React-TTS/

light9639 github io_React-TTS_

โœจ React ๋งŒ๋“  Text To Speech ์˜ˆ์ œ ํŒŒ์ผ์ž…๋‹ˆ๋‹ค. โœจ

๐ŸŽ‰ React ์ƒ์„ฑ

  • 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 ์„ ํƒํ•˜๋ฉด ์ƒ์„ฑ ์™„๋ฃŒ.

โœ’๏ธ App.tsx, getSpeech.ts ์ˆ˜์ • ๋ฐ ์ž‘์„ฑ

โšก App.tsx

  • 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

โšก getSpeech.ts

  • 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 ์†์˜ ํ…์ŠคํŠธ ๋‚ด์šฉ์„ ์ฝ์–ด์„œ ์Œ์„ฑ ๋ณ€ํ™˜์ด ๋ฉ๋‹ˆ๋‹ค.

๐Ÿ“Ž ์ถœ์ฒ˜

About

๐ŸŽ™๏ธReact ๋งŒ๋“  Text To Speech ์˜ˆ์ œ ํŒŒ์ผ์ž…๋‹ˆ๋‹ค.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published