はじめに:突然だが、ブラウザは喋れる
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つの機能がある。
- SpeechSynthesis(音声合成): テキストを音声に変換して読み上げる
- 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でブラウザが喋る。
基本の流れはこうなっている。
-
SpeechSynthesisUtteranceオブジェクトを作成(読み上げる内容を設定) -
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ほどの品質は期待できないが、手軽さは圧倒的。「ちょっと音声機能を試してみたい」というときに、真っ先に検討すべき選択肢だと思う。
ぜひ一度、自分のブラウザに喋らせてみてほしい。意外と楽しいよ。
参考リンク
- MDN Web Docs - ウェブ音声 API: https://developer.mozilla.org/ja/docs/Web/API/Web_Speech_API
- MDN - ウェブ音声 API の使用: https://developer.mozilla.org/ja/docs/Web/API/Web_Speech_API/Using_the_Web_Speech_API
- W3C Specification: https://w3c.github.io/speech-api/speechapi.html
- Can I use - Speech Synthesis: https://caniuse.com/speech-synthesis
- Can I use - Speech Recognition: https://caniuse.com/speech-recognition