web-tts という自作ライブラリを使って、Web ページに部分的な読み上げ機能を付ける方法を説明します。
web-tts
web-tts は、はてなブログで対訳の読み上げを行うために開発したライブラリです。
はてなブログに特化したものではないため、JavaScript が使える環境であれば使用できます。
対訳に特化したライブラリですが、コードを書けばページの一部分を指定して読み上げることができます。今回はその使い方を説明します。
準備
CSS と JavaScript を CDN 経由で読み込みます。(参考)
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/7shi/web-tts@0.11/speech.min.css">
<script src="https://cdn.jsdelivr.net/gh/7shi/web-tts@0.11/speech.min.js"></script>
音声の選択肢を出すための受け皿となる table を用意します。
<table id="voice_table"></table>
言語を指定して table を初期化します。
<script>
webTTS.initVoices({
en: { name: "英語", country: "US", test: "hello" },
}, voice_table);
</script>
-
en
と"US"
でen-US
(アメリカ英語)を指定します。(後述) -
test
でテスト用のフレーズを指定します。 -
name
はボタンのテキストを指定しているだけで、書き換えても言語選択には影響しません。
table にテスト用ボタンと選択肢が生成されます。
See the Pen web-tts (1) 音声選択 by 七誌 (@7shi) on CodePen.
音声一覧
en-US
のように指定できる言語や地域の一覧を取得します。
See the Pen ブラウザで使える音声の調査 by 七誌 (@7shi) on CodePen.
利用可能な音声は環境依存で、OS やブラウザによって異なります。Edge は OS に依存しない高品質なオンライン音声を豊富に揃えているためお勧めです。
読み上げ
web-tts は読み上げ用のボタンとテキストをセットにして、それぞれ span として用意します。
<p>
<span id="button1"></span><span id="text1">This is a pen.</span>
</p>
JavaScript でボタンを初期化して、テキストと関連付けます。
button1.playStop = ["▶", "■"];
button1.style.width = "1.5em";
webTTS.setSpeak(button1, "en", text1);
ボタンを押せばテキストが読み上げられるようになります。
See the Pen web-tts (2) 読み上げ by 七誌 (@7shi) on CodePen.
読み上げ位置を黄色で示す機能を実装していますが、位置を示すイベントが音声に実装されているかに依存します。Edge のオンライン音声では利用可能ですが、Chrome のオンライン音声では利用不可です。
複数のテキスト
speakTarget
が配列になっているのは、1 つのボタンに複数のテキストを関連付けられるようにするためです。センテンスごとに span を分けることを想定しています。
例を示します。
<p>
<span id="button1"></span>
<span id="text1_1">This is a pen.</span>
<span id="text1_2">That is a pencil.</span>
</p>
button1.playStop = ["▶", "■"];
button1.style.width = "1.5em";
webTTS.setSpeak(button1, "en", text1_1, text1_2);
See the Pen web-tts (3) 複数のテキスト by 七誌 (@7shi) on CodePen.
setSpeak
ボタンの外見をセットするための関数を定義します。
function setSpeak(button, lang, ...targets) {
button.playStop = ["▶", "■"];
button.style.width = "1.5em";
webTTS.setSpeak(button, lang, ...targets);
}
以後のサンプルではこの関数を使用します。
連続読み上げ
speakTarget にボタンを指定すれば、複数のボタンに関連付けられたテキストを連続して読み上げることができます。
<p>連続 <span id="button0"></span></p>
<p>
<span id="button1"></span><span id="text1">This is a pen.</span><br>
<span id="button2"></span><span id="text2">That is a pencil.</span>
</p>
setSpeak(button1, "en", text1);
setSpeak(button2, "en", text2);
setSpeak(button0, "", button1, button2);
See the Pen web-tts (4) 連続読み上げ by 七誌 (@7shi) on CodePen.
次を指定
別の方法として、次に再生するボタンを nextSpeak
で指定します。
<p>
<span id="button1"></span><span id="text1">This is a pen.</span><br>
<span id="button2"></span><span id="text2">That is a pencil.</span>
</p>
setSpeak(button1, "en", text1);
setSpeak(button2, "en", text2);
button1.nextSpeak = button2;
See the Pen web-tts (5) 次を指定 by 七誌 (@7shi) on CodePen.
複数言語
initVoices
に言語を追加してテキストの span の language
に指定すれば、複数の言語を読み上げることができます。
<script>
webTTS.initVoices({
en: { name: "英語", country: "US", test: "hello" },
fr: { name: "フランス語", country: "FR", test: "bonjour" },
}, voice_table);
</script>
<p>連続 <span id="button0"></span></p>
<p>
<span id="button1"></span><span id="text1">This is a pen.</span><br>
<span id="button2"></span><span id="text2">C'est un stylo.</span>
</p>
setSpeak(button1, "en", text1);
setSpeak(button2, "fr", text2);
setSpeak(button0, "", button1, button2);
See the Pen web-tts (6) 複数言語 by 七誌 (@7shi) on CodePen.
対訳
web-tts には複数言語のテキストを対訳形式に変換する機能があります。ボタンとテキストの関連付けは自動化されます。
<pre>
か <code>
の片方だけでも機能します。<pre>
は、デバッグ用に hidden
を外したときに改行を維持することが目的です。<code>
は、はてなブログでのはてなキーワード対策として付けているため、それ以外の環境では必須ではありません。
<pre hidden><code id="source1">
This is a pen.
C'est un stylo.
That is a pencil.
C'est un crayon.
</code></pre>
<p>
<table id="button1"></table>
<table id="text1"></table>
</p>
const source1Table = webTTS.convertSource(source1);
webTTS.initTable(source1Table, button1, text1, "en", "fr");
See the Pen web-tts (7) 対訳 by 七誌 (@7shi) on CodePen.
この方式については以下の記事を参照してください。はてなブログを想定していますが、他でも応用できる内容です。
会話
同一言語で異なる音声を指定すれば、会話のように読み上げることも可能です。
同一言語で異なる音声が利用可能かは環境依存です。Edge と Chrome と Windows ローカルの音声をコンマで区切って指定する例を示します。それ以外の環境では同一音声になります。(フォント指定の状況に似ています)
<script>
webTTS.initVoices({
en1: { name: "英語1", lang: "en", test: "hello", prefer: "Eric Online,Male,David" },
en2: { name: "英語2", lang: "en", test: "hello", prefer: "Aria Online,Female,Zira" },
}, voice_table);
</script>
<p>連続 <span id="button0"></span></p>
<p>
<span id="button1"></span><span id="text1">What is this?</span><br>
<span id="button2"></span><span id="text2">This is a pen.</span>
</p>
setSpeak(button1, "en1", text1);
setSpeak(button2, "en2", text2);
setSpeak(button0, "", button1, button2);
See the Pen web-tts (8) 会話 by 七誌 (@7shi) on CodePen.
ピッチ
ピッチを指定して声を変える方法もあります。
Edge のオンライン音声のようにピッチの変更をサポートしない音声もあります。
<script>
webTTS.initVoices({
en1: { name: "英語1", lang: "en", country: "US", pitch: 1, test: "hello" },
en2: { name: "英語2", lang: "en", country: "US", pitch: 2, test: "hello" },
}, voice_table);
</script>
ピッチに指定できるのは 0 から 2 までの浮動小数点数で、デフォルトは 1 です。
環境依存
ここまで見たように、Web Speech API は手軽ではありますが、使用できる音声が環境に依存します。
商用サイトでは Amazon Polly や Azure Speech Service などの商用クラウドサービスを使うことになるでしょう。
Edge で利用可能なオンライン音声は Azure Speech Service で提供される音声のサブセットのようです。
関連記事
Web Speech API を直接扱うための記事です。web-tts はこれらの内容をまとめたものです。