LoginSignup
2
3

JavaScriptによりブラウザで読み上げする (WEB SPEECH API)

Posted at

1. やりたいこと

ウェブページで文章を読み上げたい

2. 実現方法

JavaScriptからWEB SPEECH APIを使うと大抵のブラウザで読み上げが可能です
https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesis

3. ブラウザが対応しているか確認する

ブラウザごとの対応状況は以下から確認できます
https://caniuse.com/speech-synthesis

実行中のJavaScriptからだと以下のように確認できるようです

index.html
<script>
  if ('speechSynthesis' in window) {
    alert("このブラウザは音声合成に対応しています")
  } else {
    alert("このブラウザは音声合成に対応していません")
  }
</script>

4. 読み上げる

JavaScriptで以下を実行すると読み上げてくれます

javascript
const uttr = new SpeechSynthesisUtterance("Hello World!")
speechSynthesis.speak(uttr)

Chromeだとユーザーが操作していないページでは音がならなくなっていますので、ボタン操作に伴い読み上げるようにしてみます

index.html
<html>
  <head>
    <title>2 読み上げテスト</title>
    <link rel="icon" href="data:,">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=Edge">
    <meta name="viewport" content="width=device-width">
  </head>

  <body>
    <input type="button" value="Hello World!" onclick="say('Hello World!')">
  </body>
</html>

<script>
  const say = (text) => {
    const uttr = new SpeechSynthesisUtterance("Hello World!")
    speechSynthesis.speak(uttr)
  }
</script>

5. 読み上げの一時停止、再開、終了

読み上げ中に一時停止したり再開したり、再生を終了したりできます

index.html
<html>
  <head>
    <title>3 止めたり再開したり</title>
    <link rel="icon" href="data:,">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=Edge">
    <meta name="viewport" content="width=device-width">
  </head>

  <body>
    <input type="button" value="再生" onclick="start()">
    <input type="button" value="停止" onclick="stop()">
    <input type="button" value="一時停止" onclick="pause()">
    <input type="button" value="再開" onclick="resume()">
  </body>
</html>

<script>
  const text = "グスコーブドリは、イーハトーヴの大きな森のなかに生まれました\
                おとうさんは、グスコーナドリという名高い木こりで\
                どんな大きな木でも、まるで赤ん坊を寝かしつけるようにわけなく切ってしまう人でした"

  const start = () => {
    const uttr = new SpeechSynthesisUtterance(text)
    speechSynthesis.speak(uttr)
  }
  const stop = () => {
    speechSynthesis.cancel()
  }
  const pause = () => {
    speechSynthesis.pause()
  }
  const resume = () => {
    speechSynthesis.resume()
  }
</script>

6. 声の選択

読み上げる声の種類を選べます

6-1. 選択肢の確認

利用可能な声の一覧を以下のコマンドで取得できます

javascript
voices = speechSynthesis.getVoices()

Chromeでは使用可能な声を逐次取得していく為に、普通に取得しようとすると1回目は空配列が返ってきてしまいますが、少し間をおいて再取得すればちゃんと取れます

声が取得可能になる度にspeechSynthesis.onvoiceschangedに入れた関数が実行されます。これを仕込んでおけばスマートな書き方が出来そうです

javascript
let voices = []
speechSynthesis.onvoiceschanged = e => {
  voices = speechSynthesis.getVoices()
}

声のサンプルはここで試聴することもできます
https://codepen.io/rodhamjun/full/jQJEWQ/

OSとブラウザによって使える声が違うので、公開するサービスに使うときはユーザー環境ごとに使える声が異なる前提で作成する必要があります

6-2. 声を選んで読み上げる

SpeechSynthesisUtteranceインスタンスのvoiceプロパティに取得した声情報のどれかを渡してやれば、その声で話すようになります

javascript
const uttr = new SpeechSynthesisUtterance()
uttr.voice = voices[0]
speechSynthesis.speak(uttr)

7. 読み上げる速さや声の高さを変更する

読み上げる文章、言語、速さ、声の高さ、音量を変更できます
以下ではボタンを押すと取得した声のうち言語が日本語であるものを順番に使って読み上げを実行するようにしています

index.html
<script>
  const uttr = new SpeechSynthesisUtterance() 
  let k = 0
  let voices = null

  const getVoices = () => {
    return  speechSynthesis.getVoices().filter((v) => v.lang === 'ja-JP')
  }
  voices = getVoices()

  const start = () => {
    voices = getVoices()

    // 発言を作成
    const uttr = new SpeechSynthesisUtterance()

    // 声を選択   
    uttr.voice = voices[k]
    console.log(k, uttr.voice.name)

    // 文章を設定
    uttr.text = "声や話す速度を指定して話すことができます"

    // 言語 (日本語:ja-JP, アメリカ英語:en-US, イギリス英語:en-GB, 中国語:zh-CN, 韓国語:ko-KR)
    uttr.lang = "ja-JP"

    // 速度 0.1-10
    uttr.rate = 2.0

    // 高さ 0-2
    uttr.pitch = 0.7

    // 音量 0-1
    uttr.volume = 0.75

    // 再生
    speechSynthesis.speak(uttr)    

    if (k < (voices.length - 1)) {
      k += 1
    } else {
      k = 0
    }
  }
</script>

Windows版Chromeでは日本語読み上げの選択肢が以下の5つになるようです

実行してもらえば分かりますがMicrosoftの作ってくれた声の方が圧倒的に品質が高いです。Googleのは英語読み上げが抜群に素晴らしいのに日本語の方はかなりダメです

ステータスの確認

停止中かどうかなどが見られるようです

speechSynthesis.paused    // 一時停止中だとtrue
speechSynthesis.pending   // 発言キューにまだ再生していない文章が残っていればtrue
speechSynthesis.speaking  // 再生中だとtrue

まとめ

手軽に読み上げが実装できてすごいです
レッツトライ

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3