Amazon Web Services ブログ

Amazon Polly を使用した日本語テキスト読み上げの最適化

Amazon Polly は、高度な深層学習テクノロジーを使用して、29 の言語および 61 の音声で、人間のように聞こえる音声を合成するテキスト読み上げ( TTS )を提供するクラウドサービスです。Amazon Polly サービスは、自動コンタクトセンター、言語学習プラットフォーム、翻訳アプリ、および記事の読み上げなど、幅広い用途に対応する音声合成を使用するデジタル製品の開発において企業をサポートしています。

Amazon Polly は現在、2 つの日本語音声を提供しています。日本語は書記体系が複雑であるため、TTS システムに多くの課題をもたらします。

この投稿では、日本語が TTS に与える課題の概要、Amazon Polly がそれらの課題に対処する方法、および正しい発音を合成してカスタマーエクスペリエンスを最適化するために開発者が利用できる手法について説明します。

日本語はTTS にとって課題が多い言語

日本語の書記体系は、主に 3 つの書記法(漢字、平仮名、片仮名)で構成されており、多くの場合、これらの書記法は互換できます。たとえば、ロウソクを表す単語は、漢字(蝋燭)、平仮名(ろうそく)、または片仮名(ロウソク)で書くことができます。

漢字の読み方には音読みと訓読みがあり、さらに熟語の読みは、当て字の場合など、構成文字の読みから予想されるものとは異なる場合があります。これは、人名の場合に特に顕著であり、文字列からその名前の発音を常に予測できるとは限りません。

TTS システムの最初のステップの 1 つは、文を単語に分割することです。英語の場合、単語はスペースで分かれているためこの作業は簡単ですが、日本語の場合は一筋縄にはいきません。日本語は、間にスペースを入れずに単語をつなぎ合わせるため、単語と単語の境界を予測するモデルが必要になります。英語で、Applesonatable などの文字列を個々の単語に分解する場面を想像してください。言語的な知識を用いると、“Apple son at able” ではなく “Apples on a table” であることがわかります。これを自動的に行うにはモデルを学習する必要があります。

さらに、日本語の単語の発音は周囲の文脈に大きく依存します。同じ漢字の連なりの単語であっても、発音が異なり、文脈に応じて異なる意味を有することがあります (同形異義語)。これらはTTS にとって最大の課題です。例えば「東京都」を「とうきょうと」と読むと「現在の日本の首都」を指しますが、「ひがしきょうと」と読むと「京都の東部」を指します。また、「行った」を「いった」と読むと、「ある場所に出かけたこと」を意味しますが、「おこなった」と読むと、「何かを実行したこと」を意味します。

「東京都に行った」は、「東京///行った」と分割でき、この場合は「とうきょうとにいった」と読みますが、「東/京都//行った」の場合は「ひがしきょうとにいった」と読みます。これらの両方の場合において、「行った」は「いった」と読みますが、「東京都に行った事業の報告をする」という文脈では、2 番目の意味(「何かを実行したこと」)となり、「いった」ではなく「おこなった」と読みます。

さらに、日本語は高低アクセント言語であるため、アクセントの違いによって単語の意味に違いが生じる可能性があります。例として、(頭高型アクセント)と(平板型アクセント)があります(いずれも標準語・共通語のアクセント)。平仮名で書くと両方とも「あめ」ですが、アクセントの表記はありません。

これらの困難に対処するために、Amazon Polly は日本語のTTS システムでいくつかの機械学習(ML)モデルを採用しています。ML モデルは、周囲の単語およびその構文(文法)および形態(単語構造)情報に関する情報を使用して、単語の発音または高低アクセントおよび抑揚を予測します。これらのモデルは、言語のパターンを一般化するのに役立ち、合成されたことのない文の発音および抑揚を予測できます。

私たちは Amazon Polly のモデルの改善に継続的に取り組んでいますが、それでもサービスが正しい発音を予測できない場合があります。人間は、書かれた文脈が不十分でも、より広い文化的または状況的知識から文脈情報を推測し、筆記された文を理解できます。これらの情報の一部は現在の TTS モデルでは利用できず、または利用可能な情報はあってもモデルがそれを使って正確な予測を行うことができないこともあります。母国語話者でさえ、背景知識がないために正しい発音を予測するのに苦労する場合があります。これは、人名や地名で特によくあることで、たとえば、「愛」という名前は、「あい」、「めぐみ」、「まなみ」、「まな」など、少なくとも 28 通りの読み方があります。

これらの問題を回避するために、日本語テキストの発音をコントロールする方法がいくつかあります。

単語の区切りを指定して発音をコントロールする

単語の区切りを指定するだけで、目的の発音を示すことができる場合があります。たとえば、「東京都」(日本の首都)は、通常「とうきょうと」と読みます。この場合、この語は「東京」と「都」の 2 つの単語で構成されていると解釈できます。しかし、同じく「東京都」と書いて「ひがしきょうと」と読み、「京都の東部」を指すこともできます。この語は、「東」と「京都」の 2 つの単語で構成されていると解釈できます。単語境界タグ<w>...</w>を適用することにより、次のように目的の発音を取得できます。

 <w>東</w><w>京都</w>
 東<w>京都</w>
 <w>東</w>京都
Listen now

Voiced by Amazon Polly

単語境界タグを適用することにより、「東京都」のデフォルトの発音が上書きされ、「とうきょうと」ではなく「ひがしきょうと」と発音されます。このタグは、個々の単語を囲むことによって TTS の発音をコントロールするために使用できる SSML (音声合成マークアップ言語)の形式です。

振り仮名で発音をコントロールする

単語の区切りを指定する方法は便利ですが、合成したい語が複数の単語で構成されている場合にのみ有効です。しかし単一の単語(または単一の文字)が複数の発音を有することも多々あります。たとえば、東京の地名である日本橋は「にほんばし」と発音されますが、大阪の同じ地名を指す場合は「にっぽんばし」と発音されます。文脈がなければ、正しい発音がわかりません。

このような場合に発音を指定する最も簡単な方法は、括弧内に振り仮名表記をすることです。

日本橋(にほんばし)
Listen now

Voiced by Amazon Polly

日本橋(にっぽんばし)
Listen now

Voiced by Amazon Polly

ただし、振り仮名が表示されてしまうため、用途によっては望ましくない場合もあります。また、振り仮名が Amazon Polly が認識する発音の1 つと一致しない場合は、うまく機能しません。たとえば「海(やま)」のように、「海」という漢字に対して「やま」という振り仮名を当てても振り仮名としては認識されません。これは、たとえば「七音(どれみ)」のように、標準的ではない文字の読み方をする人名の場合に当てはまります。

この問題を克服するために、Amazon Polly には日本語用の特別な SSML タイプ属性があり、振り仮名を用いて発音を指定できます。

次の例に示すようにルビ(ruby)という音素(phoneme)タイプのタグを使用して、デフォルトの発音が「にほんばし」である「日本橋」という表記に、「にっぽんばし」という振り仮名を適用できます。

<phoneme type="ruby" ph="にっぽんばし">日本橋</phoneme> 
Listen now

Voiced by Amazon Polly

この構文を使用すると、任意の振り仮名(発音)を任意の文字列に適用できるのです。このルビタグは、単語の区切りに関係なく使えます。たとえば、次の例のように、送り仮名を除いた漢字部分のみにタグを付けることもできます。

<phoneme type="ruby" ph="い">行</phoneme>った 
Listen now

Voiced by Amazon Polly

<phoneme type="ruby" ph="おこな">行</phoneme>った 
Listen now

Voiced by Amazon Polly

振り仮名が Amazon Polly が認識する発音の 1 つと一致しない場合、モデルを使ってアクセントを予測しますが、この予測されたアクセントは正しくない場合があります。たとえば、ルビタグを使って「山」という文字に「うみ」という読みを強制することはできますが、「うみ」は「山」という文字の認識された発音の 1 つではないため、想定外のアクセントとなる場合があります。

ph 属性で指定する振り仮名には、平仮名または片仮名を使うことができます。ただし、振り仮名が有効な形式でない場合、指定された発音は効果がなく、タグで囲まれた文字列に対して予測されたデフォルトの発音になります。たとえば、数字や記号など、仮名以外の文字を振り仮名に含めることはできません。また、二重の長音符(長音記号)などの一般的ではない振り仮名の使用も無効とみなされます。

次の例では、振り仮名の形式が正しくないため、ルビタグは有効になりません。

 <phoneme type="ruby" ph="にっぽんばし2">日本橋</phoneme>
 <phoneme type="ruby" ph="にっぽんばし(おおさか)">日本橋(大阪)</phoneme>
 <phoneme type="ruby" ph="にっぽーーばし">日本橋</phoneme> 

次の例のようにタグの内部に文字列のない状態でルビタグを使用すると、何も合成されません。

<phoneme type="ruby" ph="にっぽんばし"></phoneme> → 無音

発音仮名で発音をコントロールする

ルビタグはアクセントを細かくコントロールできないため、用をなさない場合があります。「雨」、「飴」のようにアクセントが変わることで単語の意味が変わることがありますし、また、同じ単語であっても、文脈に応じてアクセントが変わる場合があります。たとえば、「音声」という単語の発音は「オ’ンセー」のように最初の拍 (音節) にアクセントが付きます(頭高型)。(アポストロフィは、ピッチの下がるアクセント拍を示しています。)「合成」という単語はアクセントのない「ゴーセー」と発音されます(平板型)。

ただし、2 つの単語が組み合わさって、「音声合成」という複合語が形成されると、アクセントの位置が移動し、「オ’ンセーゴーセー」ではなく、「オンセーゴ’ーセー」と発音されます。したがって、語や文章のアクセントを予測することは、TTS にとって容易ではありません。ML モデルを使ってある程度は解決できますが、時々間違うこともあります。そこで SSML alphabet 属性である x-amazon-pron-kana が役立ちます。x-amazon-pron-kana は、発音仮名と呼ばれる発音表記を使用しており、アクセントを直接かつ明示的に指定することができます。

x-amazon-pron-kana を使用すると、「毎日新聞を読む」という文章の 2 つの読み方を区別できます。1 つは「毎日、新聞を読む」という意味で、もう 1 つは「毎日新聞という新聞を読む」という意味です。最初のパターンは、現在 Amazon Polly が予測するデフォルトのアクセントです。

次の例は、2 番目のアクセントのパターンを適用する方法を示しています。

<phoneme alphabet="x-amazon-pron-kana" ph="マイニチシ'ンブン">毎日新聞</phoneme>を読む
Listen now

Voiced by Amazon Polly

x-amazon-pron-kana(発音仮名)は片仮名で表記され、振り仮名に似ていますが、いくつかの点で異なります。この違いを無視すると、不自然な発音につながる可能性があります。

振り仮名は必ずしも発音を正確に反映するわけではありませんが、発音仮名は忠実に反映します。たとえば、助詞「は」は、発音仮名では「ハ」ではなく「ワ」と表記します。助詞「へ」は、「ヘ」ではなく「エ」と表記し、助詞「を」は「ヲ」ではなく「オ」と表記します。「格子」と「子牛」は、振り仮名では両方とも「こうし」ですが、発音仮名ではそれぞれ「コーシ」と「コウシ」と、表記が異なります。

発音仮名では、アポストロフィはピッチが下がる位置を示します。アポストロフィがない場合、アクセントがないものとみなされます(平板アクセント)。

次の例は、アクセントの違いを示しています。

<phoneme alphabet="x-amazon-pron-kana" ph="カ'レシ">彼氏</phoneme>
Listen now

Voiced by Amazon Polly

<phoneme alphabet="x-amazon-pron-kana" ph="カレシ">彼氏</phoneme>
Listen now

Voiced by Amazon Polly

各単語には、最大 1 つのアクセントを含めることができます。ここでいう単語とは韻律語を意味し、各単語につき最大 1 箇所ピッチが下がる拍を指定できるというわけです。タグ付けする語句に複数のアクセント(ピッチの複数のピーク)がある場合は、各単語の発音仮名をスペースで区切るか、別々のタグで囲む必要があります。

次の例は、韻律語の分け方の違いによるイントネーションの違いを示しています。同じ句をさまざまな方法で韻律語に分割できるため、これらはすべて同じ発音仮名で表されますが、スペースの位置によってイントネーションが異なります。

<phoneme alphabet="x-amazon-pron-kana" ph="バ'ス ガスバ'クハツ">バスガス爆発</phoneme>
Listen now

Voiced by Amazon Polly

<phoneme alphabet="x-amazon-pron-kana" ph="バ'ス ガ'ス バクハツ">バスガス爆発</phoneme>
Listen now

Voiced by Amazon Polly

<phoneme alphabet="x-amazon-pron-kana" ph="バスガスバ'クハツ">バスガス爆発</phoneme>
Listen now

Voiced by Amazon Polly

phoneme alphabet="x-amazon-pron-kana" phoneme type="ruby" とは異なり、その周囲に単語境界を強制挿入するので、送り仮名のある単語に x-amazon-pron-kana を用いる場合、送り仮名を含む単語全体にタグ付けする必要があります。

次の表は、振り仮名(片仮名表記)と発音仮名の違いの一部をまとめたものです。

彼は北欧神話に登場する神を紹介した。
振り仮名(片仮名表記) カレハホクオウシンワニトウジョウスルカミヲショウカイシタ
発音仮名(x-amazon-pron-kana) ホクオンワニ トジョスル カ ショカイシタ

まとめ

この投稿では、日本語の TTS システムの開発において、その書記体系の複雑さにより生じるいくつかの課題について説明しました。このサービスでは、いくつかの ML モデルを使用して発音およびアクセントを予測しますが、日本語固有の SSML タグを使用することで、Amazon Polly の自然な日本語音声のコンテンツをより簡単に作成できます。この投稿の目的は、お客様の開発プロセスを高速化し、Amazon Polly での作業をより快適にすることです。Amazon Polly が提供する言語と音声の完全なリストについては、「Amazon Polly の音声」を参照してください。

 


著者について

柳澤佳代子は Amazon Text-to-Speech チームの Senior Research Scientist です。Amazon Polly および Amazon Alexa の日本語の音声合成の立ち上げで中心的な役割を果たしました。趣味はビオラで、4 年半かけて製作した自作の楽器をオーケストラや弦楽四重奏で演奏しています。