概要
Twilioの Text-to-Speech(以下TTS) でテキストを音声に変換し読ませることができます。
私が開発運用を担当している社内システムでは以前からTTSを利用していますが、通常の発音には適さない単語を読ませるケースが発生しました。
この問題を解消するためどのような工夫を行ったかを紹介します。
TTSのおさらい
利用方法
TTSはTwilioの Voice API の一機能で、Twilio Studio や SDK を介したプログラムから利用できます。
テキストを読ませるにはTwiMLというXML形式のマークアップを使って、着信時にTwilioに何をさせるか指示していきます。
<?xml version="1.0" encoding="UTF-8"?> <Response> <Say>Hello, world!</Say> </Response>
詳細はTwilioのドキュメントを参照してください。
利用できる音声の種類
Twilioのサイトによると「26の言語と方言に対応」しており、社内システムでは日本語のみを利用しています。
また一つの言語で複数の音声が用意されています。以下はTwilioのコンソールから日本語で選択できる音声です。
- Basic (Alice)
- 料金: 無料
- SSML: 不可
- 基本の音声。ただし2023/06/26以降はサポートされなくなり、これに設定しても代替の “Polly.Mizuki” にリダイレクトされるようになっています。
- Amazon Polly
- 料金: $0.0008/100文字
- SSML: 可能
- Amazon Polly を利用した音声。Twilioのコンソール上では通常の Mizuki/Takumi と、ニューラル音声の3種類から選択できます。
- Google Text-To-Speech
- 料金: $0.0008/100文字
- SSML: 可能
- Google Text-To-Speech を利用した音声。11種類の音声から選ぶことができます。
発生した課題と対応
これまで社内システムでは “Alice” の音声で、利用者が任意に記述するかデフォルトで設定されている固定のテキストを読ませていました。
しかしシステムの機能拡張によりサーバーの「ホスト名」や、監視サービスの「アラートID」といった、ランダムな文字列の可能性がある単語も読ませる必要がでてきました。
そのような文字列をそのままTTSに渡すと、例えば以下のように読み上げられます。
<Say>i-123com456</Say>
発音: あいまいなすひゃくにじゅうさんこむよんひゃくごじゅうろく
このように「ハイフンの後が数字だとマイナスと読む」「文字種ごとに単語として読む」といったルールがあり、かつ連続して読み上げられるためいきなり聞いてもまず理解できません。
このような文字列の場合でも「一文字ずつ、ゆっくり」発音させるために2つの方法を試しました。
方法1: SSMLの利用
テキスト内に Speech Synthesis Markup Language (SSML) というマークアップを入れることで、単語間で一時停止したり発音の緩急をつけたりできます。
ただしSSMLを使うには有料の Amazon Polly や Google Text-To-Speech の音声を利用する必要があります。
試してみたところ「一文字ずつ、ゆっくり」発音させることは一応可能でした。
<Say> <phoneme><prosody rate="x-slow">i-123com456</prosody></phoneme> </Say>
発音: あぁいまいなすいちにぃさんしぃおぉえむよぉんごろく
文字で表現するのが難しく若干誇張した書き方ですが、やや間延びした発音と、あまりゆっくりにならない発音が混在している感じでした。
文字間の区切り(一時停止)がなく連続で読まれることもSSMLなしの場合と同様で、”-(ハイフン)” が「マイナス」と読まれるのも同じです。
タグや属性を変更してみるなどしてみたものの今回の狙いを満たすには至らず、また有料ということもあり候補から外すことにしました。
方法2: 文字間に読点を入れる
次に考えたのが各文字の間に読点「、」を挿入してからTTSに読ませるという、より原始的な方法です。
<Say>i、-、1、2、3、c、o、m、4、5、6</Say>
発音: あい いち に さん しー おー えむ よん ご ろく
強引ではあるものの一文字ずつ発音され、かつ一文字ごとに0.2秒程度の間があいて聞き取りやすかったためこの方法を採用することにしました。
デメリットとして記号(この例だとハイフン)が発音されない、というのがありますが、人対人の会話でも記号を省いて発音することはよくあるので大きな問題にはなりにくいと思います。
まとめ
読点を挟むというちょっとした工夫で今回の課題を解消することができました。
今後読み上げの速度を変えたり音量を上げたりといった微調整が必要になったらSSMLの併用も検討していきたいと思います。