23. Speech Synthesis

Junghyun Park·2020년 12월 18일
0

Javascript30

목록 보기
8/30
post-thumbnail

프로젝트 소개

  • Text to Speech 기능 구현
  • voice 종류, rate, pitch도 함께 설정 (Html 상의 input value 연동)

배운 것들

  • SpeechSynthesis API

    : text to speech 기능 구현 시 활용 API
    https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesis

  • SpeechSynthesis.getVoices()
    :현재 디바이스에서 지원하는 voice 리스트를 반환

  • SpeechSynthesis.cancel()
    : 모든 utterence queue를 제거하고, 말하고 있는게 있으면 Stop

  • speechSyntheis.addEventListener('voiceschanged', function)
    : SpeechSynthesisVoice object 리스트가 .getVoices() method의 변경에 의해 반환되었을 때 이벤트 발생
    : onvoiceschanged property로도 가능

최종 코드

<script>
      const msg = new SpeechSynthesisUtterance();
      let voices = [];
      const voicesDropdown = document.querySelector('[name="voice"]');
      const options = document.querySelectorAll(
        '[type="range"], [name="text"]'
      );
      const speakButton = document.querySelector('#speak');
      const stopButton = document.querySelector('#stop');

      msg.text = document.querySelector('[name = text]').value;

      console.log(msg);

      function voicePlay() {
        voices = this.getVoices();

        voicesDropdown.innerHTML = voices
          .map((voice) => {
            return `<option name=${voice.name}> ${voice.name} (${voice.lang})</option>`;
          })
          .join('');
      }

      function voiceSet() {
        //this.value voicePlay 합수에서 voice.name과 voice.lang을 조합시켜 만든 값이므로 그대로 할당하면 X
        msg.voice = voices.find((voice) => this.value.includes(voice.name));
        toggle();
      }

      // 동일 함수를 통해, 재생과 정지를 동시에 구현 (Boolean 변수가 스위치 역할)
      function toggle(startOver = true) {
        speechSynthesis.cancel();
        if (startOver) {
          speechSynthesis.speak(msg);
        }
      }

      function setOption() {
        msg[this.name] = this.value;
        toggle();
      }

      speechSynthesis.addEventListener('voiceschanged', voicePlay);
      voicesDropdown.addEventListener('change', voiceSet);
      options.forEach((option) => option.addEventListener('change', setOption));
      speakButton.addEventListener('click', toggle);
      stopButton.addEventListener('click', () => toggle(false));
    </script>

느낀 점/ 기억할 점

  • option에서 선택된 값(this.value)을 바로 msg.voice로 할당하면 아래와 같은 오류 발생 => 그 위에서 this.value 값은 voice name과 lang name의 조합으로 만들어 놨기 때문에 => 따라서, 전체 voice 리스트에서 find method를 통해 포함하는(include) 항목을 선별해서 할당하는 방식으로 변경해야 함 (정답 코드에서도 이 부분을 틀리게 되어있어, 자체 수정함)
  • 이렇게 해결했음
function voiceSet() {
       msg.voice = voices.find((voice) => this.value.includes(voice.name));
      }
  • 미리 속성 name을 알고 있으면, contol 대상 element의 name을 동일하게 해서, 동시에 속성 name과 값을 this로 가져와 간단하게 코드 작성 가능 (아래 예시 참조)
msg[this.name] = this.value;
profile
21c Carpenter

0개의 댓글