
Web Speech APIの仕組みとブラウザ音声合成の歴史 ― DECtalkからニューラルTTSまで
ブラウザの読み上げは、文章を発話オブジェクトにして音声エンジンへ渡す仕組みです。Web Speech API自体が声を生成するモデルではありません。Voder、DECtalk、ニューラルTTSの歩みと、実際のWeb開発で必要になる音声選択・プライバシー・再生管理を区別して見ていきます。
音声合成の歴史 ― Voder、DECtalk、CallText
1939年のニューヨーク万博では、ベル研究所のHomer DudleyによるVoderが披露されました。鍵盤とペダルを人が操作して音声を作る装置で、文章を自動で読む現在のTTSとは異なります。
1980年代にはDennis Klattらの研究を背景にDECtalkが登場しました。Perfect PaulはKlattの声に基づく音声です。ただし、スティーブン・ホーキング博士が使用した装置は、DECtalkではなくSpeech PlusのCallText 5010でした。MITalkに関わる技術的な系譜が重なることと、同じ製品であることは区別が必要です。
音声を作る方式にも違いがあります。以下は代表例であり、すべての方式を二分したものではありません。
表が収まらない場合は、左右にスクロールできます。
| 方式 | 基本的な考え方 |
|---|---|
| フォルマント合成 | 声道の共鳴を表す特性などをモデル化し、音声を生成する。DECtalkはこの系統。 |
| 連結合成 | 録音した音声の断片を選択してつなぐ。接続や抑揚の調整が必要。 |
歴史の出典: Computer History Museum、方式比較: 同館とGoogle DeepMind。正式な文献リンクは末尾にまとめています。
OSの音声機能とAPIは別の層
デスクトップ環境では、OSの音声機能をアプリから利用するためのAPIが提供されてきました。MicrosoftのSAPI(Speech API)はその例です。SAPI自体を「連結合成エンジン」と呼ぶのは不正確で、APIと、その背後で文章を音声に変えるエンジンを分けて考えます。
Web Speech APIもブラウザから音声合成機能を呼び出す窓口です。OSにインストールされた音声がすべてブラウザへ公開されるとは限りません。音声の有無・種類・処理場所は、ブラウザ、OS、設定、サービスによって変わります。利用可能な音声は、その環境のgetVoices()で確認します。
Web Speech APIの位置付けと対応状況
Web Speech APIは、音声を文字にする音声認識と、文字を音声にする音声合成を扱います。この記事は後者を対象とします。認識側の対応状況やマイクの権限条件を、そのまま合成側に当てはめないでください。
2026年11月12日に確認した仕様はDraft Community Group Reportです。W3C勧告ではなく、「2012年に最終仕様が完成した」とする説明は適切ではありません。
Can I useの音声合成対応表では、Chrome 33、Safari 7、Firefox 49、Edge 14以降が対応の目安です。これはAPI対応の履歴であり、特定の音声・言語・音質や全機能の同一動作を保証しません。現在の利用可否はAPIの存在と音声一覧を確認し、対象端末で試します。
APIの仕組み ― 発話を作り、音声を選ぶ
次の例は、HTMLに置いた<button id="speak" type="button">読み上げ</button>の後にscriptとして配置します。クリックから短い文章を再生し、ローカル日本語音声がなければ再生しません。ページの音声キューをこの例だけが管理する前提です。通常、speak()は発話をキューへ追加します。この例はcancel()で以前の発話を停止・削除するため、音声が利用できる状態で再クリックすると新しい発話を開始します。resume()で取消済みの発話を復元するわけではありません。一覧が最初は空なら、音声の取得後にもう一度クリックしてください。後述の一覧監視例は再生を再試行しません。
if ("speechSynthesis" in window && "SpeechSynthesisUtterance" in window) {
const synth = window.speechSynthesis;
document.getElementById("speak").addEventListener("click", () => {
const voice = synth.getVoices().find(v =>
v.localService && /^ja(?:-|$)/i.test(v.lang));
if (!voice) {
console.log("ローカル日本語音声がまだ利用できません");
return;
}
const utterance = new SpeechSynthesisUtterance("こんにちは");
utterance.voice = voice;
utterance.lang = voice.lang;
utterance.rate = 1;
utterance.pitch = 1;
utterance.volume = 1;
utterance.onend = () => console.log("発話終了の通知");
utterance.onerror = event => console.error("読み上げエラー", event.error);
synth.cancel();
synth.resume();
synth.speak(utterance);
});
} else {
console.log("この環境では音声合成APIを利用できません");
}
speak()には発話オブジェクトを渡します。呼び出しだけで再生成功とは判断せず、エラーを扱います。rateのAPI上の範囲は0.1〜10、pitchは0〜2、volumeは0〜1ですが、エンジンの対応範囲や効果には差があります。この短い例には長文分割・タイムアウト・画面の状態表示は含めていません。
音声一覧は後から変わる
一覧が初めは空の場合もあるため、最初の取得とvoiceschangedの両方を扱います。次の独立した例は一覧を記録するだけで、自動再生はしません。戻り値を画面破棄時に呼び出して監視を解除します。空のままなら、OSの音声設定やブラウザの提供条件も確認してください。
function watchLocalVoices(onChange) {
if (!("speechSynthesis" in window)) return () => {};
const synth = window.speechSynthesis;
const update = () => onChange(synth.getVoices().filter(v =>
v.localService && /^ja(?:-|$)/i.test(v.lang)));
synth.addEventListener("voiceschanged", update);
update();
return () => synth.removeEventListener("voiceschanged", update);
}
const stopWatching = watchLocalVoices(voices => console.log(voices));
// 画面・コンポーネントの破棄時に stopWatching() を呼ぶ。
発話にはstart、end、error、pause、resumeなどのイベントがあります。boundaryは単語や文の境界通知ですが、すべてのエンジンが同じ粒度で通知するとは限りません。終了通知も、利用者に音が聞こえたことや正しい発音の証明ではありません。
ブラウザによる音声の違いとプライバシー
音声の種類・品質はブラウザ、OS、端末設定、音声サービスによって異なります。ブラウザ名から特定音声の提供や品質を保証することはできません。getVoices()の一覧にある音声を確認してください。音声名は一意とは限らず、一覧更新時に配列の同じ位置が同じ音声を指すとも限りません。
localServiceはブラウザが報告する処理区分です。trueは端末内、falseは外部の音声サービスを意味します。外部サービスでは文章が音声提供者へ送信される場合があります。この区分は、拡張機能や端末を含む全通信の非送信保証ではありません。
NanTooのテキスト読み上げツールは初期設定をローカル音声のみにしています。クラウド音声はフィルターを解除して明示選択します。選択した音声が消えた場合に別の音声へ自動変更しません。入力文章をNanTooのサーバーへ送信・保存する処理はありませんが、機密情報の扱いには端末と音声提供者の条件も確認してください。
ニューラルTTS ― WaveNetとTacotron 2
2016年に発表されたWaveNetは、生の音声波形をサンプルごとに生成する自己回帰型のニューラルネットワークです。先に生成したサンプルを条件として次の値を生成するため、初期方式には計算コストの課題がありました。報告された聴取評価の改善は、その実験条件で比較したシステムに対する結果であり、すべての音声合成に対する優越を証明するものではありません。
Googleが2017年12月に紹介したTacotron 2は、文字列からメルスペクトログラムを推定し、WaveNet系のボコーダで音声波形に変換する構成です。メルスペクトログラムは、周波数の分布が時間とともにどう変わるかを、人の聴覚を考慮した尺度で表します。文字を入力するこの例を「必ず音素列から生成する方式」と説明してはいけません。
Microsoftは2018年9月にニューラルTTSサービスのプレビューを発表しました。ただし、クラウドサービスの研究・製品発表は、その声が特定ブラウザのgetVoices()に現れることを意味しません。ニューラルTTSにも複数の構成があり、全方式を固定的な3段階に限定することはできません。
長文読み上げと再生状態の管理
長文の途中停止は過去にChromiumで報告されていますが、現在の全環境に共通の15秒制限があるとは限りません。定期的なpause()/resume()だけで安定動作を保証することもできません。
cancel()は発話キューを消しますが、一時停止状態を解除しません。新しい再生時はresume()で解除します。停止した発話の遅いイベントを新しい再生に混ぜないよう、再生と各発話に所有者を設け、終了イベントが現在の発話に属するか確認します。エラーと完了は区別し、無応答を無期限に待たない設計が必要です。
NanTooは最大5,000 UTF-16単位の文章を、結合文字を分断せず200単位以下の区間に分けます。過長入力は超過検出用の先頭5,001単位までを保持し、再生しません。区間前後の空白は省き、単一の結合文字が200単位を超える入力は拒否します。1区間90秒、全体20分を上限として中断し、一時停止時間も上限に含めます。バックグラウンド・画面ロック・端末スリープでは検知や停止が遅れる場合があります。文章・音声・フィルター・設定の変更時は停止します。
この分割処理は音声エンジンの不具合や発音の誤りを解消する保証ではありません。区間の継ぎ目に不自然な間が入る場合があります。完了表示も音声エンジンからの通知であり、音量や実際の発音を検証した結果ではありません。
SSML ― 読み上げ方を指定するマークアップ
SSML(Speech Synthesis Markup Language)は読み上げ方を指定するためのXMLベースの言語です。SSML 1.1は2010年9月7日のW3C勧告です。次は名前空間を含むSSML文書の例で、ブラウザ間で同じ読み上げになることを保証するものではありません。
<speak xmlns="http://www.w3.org/2001/10/synthesis"
version="1.1" xml:lang="ja-JP">
こんにちは。
<break time="500ms"/>
<prosody rate="slow" pitch="+10%">ゆっくり高めに読みます。</prosody>
</speak>
breakは間、prosodyは速度やピッチなどを指定します。音素の表記方式やsay-asの解釈まで、すべてのエンジンで共通とは限りません。
Web Speech APIの仕様は発話テキストにプレーンテキストまたは整形式SSMLを認めていますが、SSMLの解釈や対応範囲は実装に依存します。「クラウドAPIだけがSSMLを扱える」とは限りません。NanTooではSSML/XMLや山括弧で囲んだ表現を受け付けず、文章とrate・pitch・volumeの設定による再生に限定しています。
利用前に押さえる限界
- 音声と音質: ブラウザ・OS・設定・音声提供者に依存します。
- 音声データの取得: SpeechSynthesisには合成結果をBlobや音声ストリームとして返す標準メソッドがありません。WebCodecsを加えるだけで出力を取り出せるわけではありません。
- SSMLとイベント: 実装ごとの確認が必要です。
- 長文: 分割やタイムアウトは対策であり、全環境での完走保証ではありません。
- 独自音声: ページから任意のモデルをSpeechSynthesisの音声一覧へ登録するAPIはありません。
独自のTTSモデルをWebAssemblyやWebGPUで動かす設計は、ブラウザが提供するSpeechSynthesisとは別です。文章の読み上げが目的なら、まず利用可能な声・処理場所・再生状態を確認します。録音ファイルの生成や特定モデルの利用が必要なら、それに対応した別の合成手段を検討します。
参考文献・ソース
- webaudio.github.io: Web Speech API ↗
- MDN Web Docs: ウェブ音声 API - Web API ↗
- caniuse.com: Speech Synthesis API | Can I use... Support tables for HTML5, CSS3, etc ↗
- computerhistory.org: Bringing A New Voice to Genius—MITalk, the CallText 5010, and Stephen Hawking’s Wheelchair - CHM ↗
- Google Research: Tacotron 2: Generating Human-like Speech from Text ↗
- Microsoft Azure Blog: Microsoft’s new neural text-to-speech service helps machines speak like people ↗
- Chromium: Speech Synthesis stops abruptly after about 15 seconds ↗
- Google DeepMind: WaveNet: A generative model for raw audio ↗
- Microsoft Learn: Text-to-Speech Tutorial (SAPI 5.3) ↗
- MDN Web Docs: SpeechSynthesis: getVoices() method - Web APIs ↗
- MDN Web Docs: SpeechSynthesis: cancel() method - Web APIs ↗
- W3C: Speech Synthesis Markup Language (SSML) Version 1.1 ↗
- WHATWG: HTML Standard ↗
- MDN Web Docs: SpeechSynthesisUtterance - Web APIs ↗
- MDN Web Docs: SpeechSynthesisVoice: localService property - Web APIs ↗
- MDN Web Docs: SpeechSynthesisUtterance: boundary event - Web APIs ↗
記事作成に関する注記
本記事は AI(大規模言語モデル)を編集補助として活用して作成しています。 公開前に編集者が内容を確認していますが、事実誤認・仕様の解釈ミス・最新情報との齟齬が含まれる可能性があります。 重要な判断を行う際は、本文中の一次ソースや公式ドキュメントを必ずご自身でご確認ください。 誤りにお気づきの場合は、お問い合わせフォームよりご連絡いただけると助かります。




