1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

アプリを喋らせたいならWeb Speech APIだ!

1
Posted at

はじめに:突然だが、ブラウザは喋れる

Webアプリに音声機能をつけたいと思ったことはないだろうか。

「入力されたテキストを読み上げてほしい」
「音声でコマンド入力できたらかっこいいな」
「アクセシビリティ対応で読み上げ機能が必要」

こういうとき、真っ先に思い浮かぶのはGoogle Cloud Speech APIやAmazon Polly、IBM Watson Text to Speechあたりだろう。どれも高品質な音声サービスだ。

でも、登録が面倒だし、お金もかかりそう。ちょっと試してみたいだけなのに大げさだなあ...。

そんなあなたに朗報がある。最近のブラウザには、標準で音声合成・音声認識の機能が搭載されている。しかも無料。

それがWeb Speech APIだ。

Web Speech APIとは

Web Speech APIは、W3C(World Wide Web Consortium)が策定したブラウザ標準のAPIである。

MDNのドキュメントによれば:

ウェブ音声 API (Web Speech API) で、音声データをウェブアプリに組み入れることができます。 ウェブ音声 API は、SpeechSynthesis (音声合成、Text-to-Speech)と SpeechRecognition (非同期音声認識、Asynchronous Speech Recognition)の 2 つの部分から成り立っています。

参照:https://developer.mozilla.org/ja/docs/Web/API/Web_Speech_API

つまり、2つの機能がある。

  1. SpeechSynthesis(音声合成): テキストを音声に変換して読み上げる
  2. SpeechRecognition(音声認識): マイクからの音声をテキストに変換する

ブラウザのネイティブAPIなので、JavaScriptライブラリのインポートも不要。サーバーも不要(音声認識の一部機能を除く)。htmlファイルとJavaScriptだけで動く。

まずは喋らせてみよう:音声合成の基本

百聞は一見にしかず。まずは動かしてみよう。

以下のコードをHTMLファイルに書いて、ブラウザで開いてみてほしい。

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Web Speech API テスト</title>
</head>
<body>
  <h1>音声合成テスト</h1>
  <input type="text" id="text" value="こんにちは、世界!" style="width: 300px">
  <button onclick="speak()">読み上げる</button>

  <script>
    function speak() {
      const text = document.getElementById('text').value;
      const uttr = new SpeechSynthesisUtterance(text);
      uttr.lang = 'ja-JP';
      speechSynthesis.speak(uttr);
    }
  </script>
</body>
</html>

ボタンをクリックすると、入力欄のテキストをブラウザが読み上げてくれるはずだ。

たったこれだけ。3行のJavaScriptでブラウザが喋る。

基本の流れはこうなっている。

  1. SpeechSynthesisUtteranceオブジェクトを作成(読み上げる内容を設定)
  2. speechSynthesis.speak()に渡す

めちゃくちゃシンプルだ。

対応ブラウザをチェックしよう

ここで気になるのがブラウザの対応状況。

音声合成(SpeechSynthesis)については、ほとんどの主要ブラウザが対応している。Chrome、Edge、Safari、Firefoxと、Internet Explorer以外はだいたいOK。Can I use(https://caniuse.com/speech-synthesis)で確認できる。

一方、音声認識(SpeechRecognition)は少し状況が違う。長らくChromeでしか動かなかったが、2024年に入ってSafariとEdgeも対応するようになった。Firefoxはまだ非対応だが、カバー率はだいぶ上がってきた。

コードでブラウザ対応を確認するなら、こんな感じ。

// 音声合成の対応チェック
if ('speechSynthesis' in window) {
  console.log('このブラウザは音声合成に対応しています');
} else {
  console.log('このブラウザは音声合成に対応していません');
}

// 音声認識の対応チェック
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
if (SpeechRecognition) {
  console.log('このブラウザは音声認識に対応しています');
} else {
  console.log('このブラウザは音声認識に対応していません');
}

Chromeなど一部ブラウザではwebkitSpeechRecognitionというプレフィックス付きの名前になっているので、両方チェックしている。

音声合成をもう少し詳しく

基本は分かったので、もう少し踏み込んでみよう。

SpeechSynthesisUtteranceには、いろいろなプロパティがある。

const uttr = new SpeechSynthesisUtterance('読み上げるテキスト');

// 言語設定(日本語)
uttr.lang = 'ja-JP';

// 音声の高さ(0〜2、デフォルト1)
uttr.pitch = 1.2;

// 読み上げ速度(0.1〜10、デフォルト1)
uttr.rate = 1.0;

// 音量(0〜1、デフォルト1)
uttr.volume = 0.8;

// 使用する音声を指定(後述)
// uttr.voice = selectedVoice;

pitchを上げると高い声に、下げると低い声になる。rateで読み上げ速度を調整できるので、英語学習アプリなんかで「ゆっくり再生」機能を実装するときに便利だ。

利用可能な音声を取得する

ブラウザには複数の音声が搭載されていることがある。日本語の声、英語の声、男性の声、女性の声...。

利用可能な音声一覧はspeechSynthesis.getVoices()で取得できる。

// 音声一覧を取得
const voices = speechSynthesis.getVoices();
voices.forEach((voice, index) => {
  console.log(`${index}: ${voice.name} (${voice.lang})`);
});

// 特定の音声を使用
const uttr = new SpeechSynthesisUtterance('Hello World');
uttr.voice = voices.find(v => v.name.includes('Google'));
speechSynthesis.speak(uttr);

ただし注意点がある。getVoices()は非同期的に音声リストを読み込むことがあり、ページ読み込み直後だと空配列が返ってくることがある。

安全に取得するにはこうする。

function populateVoices() {
  const voices = speechSynthesis.getVoices();
  if (voices.length > 0) {
    // 音声リストを使った処理
    console.log('音声数:', voices.length);
  }
}

// 音声リストが読み込まれたときのイベント
speechSynthesis.onvoiceschanged = populateVoices;
// 初回呼び出し
populateVoices();

読み上げの制御

読み上げ中に一時停止したり、再開したり、キャンセルしたりもできる。

// 一時停止
speechSynthesis.pause();

// 再開
speechSynthesis.resume();

// キャンセル(読み上げを中止)
speechSynthesis.cancel();

// 読み上げ中かどうか
if (speechSynthesis.speaking) {
  console.log('読み上げ中です');
}

音声認識にも挑戦

音声合成ができたので、今度は音声認識にも挑戦してみよう。

// ブラウザ互換性のための書き方
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
const recognition = new SpeechRecognition();

// 日本語認識
recognition.lang = 'ja-JP';

// 継続的に認識するか(falseだと一度認識したら止まる)
recognition.continuous = false;

// 認識途中の結果も取得するか
recognition.interimResults = false;

// 認識開始
recognition.start();

// 結果を受け取る
recognition.onresult = (event) => {
  const transcript = event.results[0][0].transcript;
  console.log('認識結果:', transcript);
};

// エラーハンドリング
recognition.onerror = (event) => {
  console.error('認識エラー:', event.error);
};

// 認識終了時
recognition.onend = () => {
  console.log('認識終了');
};

このコードを実行すると、ブラウザからマイクのアクセス許可を求められる。許可すると、話した内容がテキストに変換される。

注意点:Chromeなどの一部ブラウザでは、音声認識にサーバーベースの認識エンジンを使用している。つまり、音声データがGoogleのサーバーに送信されている。オフラインでは動作しない。プライバシーが気になる用途では注意が必要だ。

実践的なサンプル:入力フォームに音声入力機能を追加

実際に使えるサンプルを作ってみよう。入力フォームにマイクボタンをつけて、音声入力できるようにする。

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>音声入力フォーム</title>
  <style>
    .input-container {
      display: flex;
      gap: 8px;
      margin: 20px;
    }
    input[type="text"] {
      flex: 1;
      padding: 8px;
      font-size: 16px;
    }
    .mic-btn {
      padding: 8px 16px;
      background: #4285f4;
      color: white;
      border: none;
      border-radius: 4px;
      cursor: pointer;
    }
    .mic-btn.listening {
      background: #ea4335;
    }
    .status {
      margin: 20px;
      color: #666;
    }
  </style>
</head>
<body>
  <h1>音声入力フォーム</h1>
  
  <div class="input-container">
    <input type="text" id="textInput" placeholder="ここに入力されます">
    <button class="mic-btn" id="micBtn">マイク</button>
  </div>
  <div class="status" id="status">マイクボタンを押して話してください</div>

  <script>
    const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
    
    if (!SpeechRecognition) {
      document.getElementById('status').textContent = 'このブラウザは音声認識に対応していません';
      document.getElementById('micBtn').disabled = true;
    } else {
      const recognition = new SpeechRecognition();
      recognition.lang = 'ja-JP';
      recognition.interimResults = true;
      
      const micBtn = document.getElementById('micBtn');
      const textInput = document.getElementById('textInput');
      const status = document.getElementById('status');
      
      let isListening = false;
      
      micBtn.addEventListener('click', () => {
        if (isListening) {
          recognition.stop();
        } else {
          recognition.start();
        }
      });
      
      recognition.onstart = () => {
        isListening = true;
        micBtn.textContent = '停止';
        micBtn.classList.add('listening');
        status.textContent = '聞いています...';
      };
      
      recognition.onend = () => {
        isListening = false;
        micBtn.textContent = 'マイク';
        micBtn.classList.remove('listening');
        status.textContent = 'マイクボタンを押して話してください';
      };
      
      recognition.onresult = (event) => {
        const transcript = event.results[0][0].transcript;
        textInput.value = transcript;
        
        // 確定した結果かどうか
        if (event.results[0].isFinal) {
          status.textContent = '認識完了!';
        }
      };
      
      recognition.onerror = (event) => {
        status.textContent = 'エラー: ' + event.error;
        isListening = false;
        micBtn.textContent = 'マイク';
        micBtn.classList.remove('listening');
      };
    }
  </script>
</body>
</html>

これで、マイクボタンを押して話すと、音声がテキストに変換されて入力欄に入る。interimResults = trueにしているので、話している途中でもリアルタイムに結果が表示される。

ハマりがちなポイント

Web Speech APIを使っていると、いくつかハマりがちなポイントがある。

1. ユーザー操作なしでは音声が再生されない

Chromeなど最近のブラウザでは、ユーザーのインタラクションなしに音声を再生することが制限されている。ページを開いた瞬間に自動で喋らせようとしても、無音になる。

必ずボタンクリックなどのユーザー操作をトリガーにすること。

2. 漢字の読みが違う

音声合成は万能ではない。特に日本語の漢字の読みは怪しいことがある。

「日本橋」を「にほんばし」と読んでほしいのに「にっぽんばし」になったり。人名や地名は特に危ない。

対処法としては、ひらがなで渡すか、読み仮名辞書を用意して変換するしかない。

3. 顔文字や記号が読めない

「(^^)」とか「www」とか、そのまま渡すと変な読み方になる。

顔文字は「かっこ おめが」とか読み上げちゃうし、「www」は「ダブルダブルダブル」になる。事前にフィルタリングするなどの工夫が必要だ。

4. getVoices()が空配列を返す

前述の通り、ページ読み込み直後だとgetVoices()が空を返すことがある。onvoiceschangedイベントを使って対処しよう。

Web Speech APIの活用例

実際にどんな用途で使われているか、いくつか例を挙げてみよう。

アクセシビリティ対応
視覚障害のあるユーザー向けに、ページの内容を読み上げる機能。

言語学習アプリ
外国語の発音を聞いたり、自分の発音を認識してチェックしたり。読み上げ速度を調整できるのが便利。

音声コマンド
ハンズフリーでWebアプリを操作。「次のスライド」と言ったら次のスライドに移動する、とか。

音声メッセージング
テキストを打つ代わりに、音声で入力してメッセージを送る。

議事録の自動作成
会議中の音声を認識してリアルタイムで文字起こし。(精度との戦いはあるが)

もっと高品質な音声が欲しい場合

Web Speech APIは手軽で便利だが、音声の品質は正直そこまで高くない。ロボットっぽいというか、自然さに欠ける。

本番環境で高品質な音声が必要な場合は、外部サービスの利用も検討しよう。

  • Google Cloud Text-to-Speech: 自然な音声、多言語対応
  • Amazon Polly: AWSの音声合成サービス
  • Microsoft Azure Text to Speech: 感情表現も可能
  • VOICEVOX: 無料で使えるテキスト読み上げソフト(商用利用もOKなキャラクターあり)

ただ、ちょっとした読み上げ機能やプロトタイプ、社内ツールなどであれば、Web Speech APIで十分なことも多い。無料で手軽に試せるのが最大の強みだ。

まとめ

Web Speech APIは、ブラウザ標準で使える音声合成・音声認識のAPIだ。

  • 無料、登録不要、ライブラリ不要
  • SpeechSynthesis(テキスト→音声)とSpeechRecognition(音声→テキスト)の2機能
  • 音声合成はほぼ全ブラウザで動作、音声認識も対応ブラウザが増加中
  • 数行のJavaScriptでブラウザが喋る

外部APIほどの品質は期待できないが、手軽さは圧倒的。「ちょっと音声機能を試してみたい」というときに、真っ先に検討すべき選択肢だと思う。

ぜひ一度、自分のブラウザに喋らせてみてほしい。意外と楽しいよ。

参考リンク

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?