Alexaの喋り方を制御できるSSMLを色々と試してみました

2018.02.09

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

モバイルアプリサービス部の中安です。

Alexaのカスタムスキルの作成では、プログラム側(Lambda)に何も考えずにただ文字列を書いてあげるだけでスラスラと澱みない言葉で話してくれます。素晴らしいかぎりですね。

ただ、やはり個性を出すためには、細かいところを「もう少しこう喋ってくれないかなぁ」という気持ちにもなることがあると思います。

そこで登場するのが、SSML というものです。

SSMLは "Speech Synthesis Markup Language" の略で、日本語では「音声合成マークアップ言語」といいます。

マークアップ言語ということもあり、まるで XML や HTML を書くかのように Alexa に対して「喋り方」を決めることができてしまいます。

SSMLを組む方法として専用のビルダーも存在していますが、その詳しい説明は こちらのブログ記事 (SSMLの組み立てが超便利なssml-builderについて) におまかせするとして、今回はその SSML の挙動のまとめと、その結果 Alexa がどう話し方が変わるの?ってところを実験してみたいと思います。

準備

まずは準備として、開発者コンソールでテスト用のインテントを足しました。

  "intents": [
    (略)
    {
      "intent": "TestIntent"
    },
    (略)
  ]

サンプル発話には、上記テストインテントを走らせられるように設定します。

TestIntent テスト

で、Lambda に流す node.js は色々と端折りますが、こんな感じ。

    'TestIntent': function () {
        this.emit(':tell', '何か喋ります');
    },

これで、「アレクサ、(呼び出し名)でテスト」というと、「何か喋ります」と返してくれます。以降、"何か喋ります"の部分を変えながら実験していきます。

※ 今回の呼び出し名は「SSML」にしています。

エフェクト

amazon:effect タグは、Alexaに特殊な話し方をさせたい時に使います。

現時点ではまだ「ささやく」ことしかできないようですが、そのうち色んなエフェクトが増えるのかなぁと期待しつつ、ちょっと喋らせてみます。

Lambdaのスクリプト(node.js)を以下のようにします。

    'TestIntent': function () {
        this.emit(':tell', '<amazon:effect name="whispered">おはようございます</amazon:effect>');
    },

エフェクトを加えてやりたい箇所をタグで囲ってやるだけです。name 属性には効果の名前を書くのですが、先ほども書いたとおり現時点では「ささやき」しかできないので、whispered にします。

さて、結果は・・・

今からアイドルの部屋に寝起きドッキリしに行くみたいになりましたね。

強調

emphasis タグは、直訳すると「強調」です。

この強調表現には以下のような種類があります。

  • strong: 音量を上げ、話す速度を遅くすることにより、音声は、より大きな声、かつゆっくりになります。
  • moderate: 音量を上げ、話す速度を遅くしますが、strongを設定した場合より控えめになります。これは、levelを指定しなかった場合のデフォルトとして使用されます。
  • reduced: 音量を下げ、話す速度を速くします。音声は、ソフトで早口になります。

普通の話し方と、これらの全種類の違いが分かるようにLambdaのスクリプトを以下のようにしてみます。

    'TestIntent': function () {
        var noemphasis = '何も指定せずに話します。なまむぎなまごめなまたまご<break time="2s"/>';
        var moderate = '頃合いの強調で話します。<emphasis level="moderate">なまむぎなまごめなまたまご</emphasis><break time="2s"/>';
        var strong = '強くゆっくり話します。<emphasis level="strong">なまむぎなまごめなまたまご</emphasis><break time="2s"/>';
        var reduced = '小さく早めに話します。<emphasis level="reduced">なまむぎなまごめなまたまご</emphasis><break time="2s"/>';
        this.emit(':tell', noemphasis + moderate + strong + reduced);
    },

さて、結果は・・・

休止

break タグは、Alexaの喋る内容に任意の時間だけ休止させることができるものです。

Lambdaのスクリプトを以下のようにします。

    'TestIntent': function () {
        this.emit(':tell', '正解は<break time="10s"/>越後製菓');
    },

さて、結果は・・・

このようにクイズの溜めなんかに使ってみるのなんてどうでしょう。

ちなみに指定できる最大の時間は10秒です。また、秒かミリ秒かの指定が必要なので、数字のあとの「s」をお忘れなく。

韻律

prosody タグは、直訳すると「韻律」とされるものです。あまり聞き慣れない言葉ですが、言語学では音楽でいうところのメロディに近いもののようです。(ググりました)

設定できるのは大きくは下記の属性です。

  • rate: 音声の速さ
  • pitch: 音声のトーン(高さ)
  • volume: 音声の音量

レート

文字で指定できる音声の速さは以下のものがあります。

  • x-slow
  • slow
  • medium
  • fast
  • x-fast

このタグは属性とその値にバリエーションがあり、すべてをカバーするのは大変そうなので掻い摘んで実験してみます。 普通の話し方との違いが分かるようにLambdaのスクリプトを以下のようにしてみました。

    'TestIntent': function () {
        var norate = '何も指定せずに話します。なまむぎなまごめなまたまご<break time="2s"/>';
        var xslow = 'ゆっくり話します。<prosody rate="x-slow">なまむぎなまごめなまたまご</prosody><break time="2s"/>';
        var slow = '少しゆっくり話します。<prosody rate="slow">なまむぎなまごめなまたまご</prosody><break time="2s"/>';
        var medium = 'ふつうに話します。<prosody rate="medium">なまむぎなまごめなまたまご</prosody><break time="2s"/>';
        var fast = '少し早く話します。<prosody rate="fast">なまむぎなまごめなまたまご</prosody><break time="2s"/>';
        var xfast = '早く話します。<prosody rate="x-fast">なまむぎなまごめなまたまご</prosody><break time="2s"/>';
        this.emit(':tell', norate + xslow + slow + medium + fast + xfast);
    },

さて、結果は・・・

文字ではなく、パーセンテージを指定する方法もあり、もっと細かくチューニングすることもできます。今回は割愛しますので、興味ある方は色々と試してみてください。

ピッチ

文字で指定できる音声の高さは以下のものがあります。

  • x-low
  • low
  • medium
  • high
  • x-high

普通の話し方と、これらの全種類の違いが分かるようにLambdaのスクリプトを以下のようにしてみました。

    'TestIntent': function () {
        var nopitch = '何も指定せずに話します。なまむぎなまごめなまたまご<break time="2s"/>';
        var xlow = '低く話します。<prosody pitch="x-low">なまむぎなまごめなまたまご</prosody><break time="2s"/>';
        var low = '少し低く話します。<prosody pitch="low">なまむぎなまごめなまたまご</prosody><break time="2s"/>';
        var medium = 'ふつうに話します。<prosody pitch="medium">なまむぎなまごめなまたまご</prosody><break time="2s"/>';
        var high = '少し高く話します。<prosody pitch="high">なまむぎなまごめなまたまご</prosody><break time="2s"/>';
        var xhigh = '高く話します。<prosody pitch="x-high">なまむぎなまごめなまたまご</prosody><break time="2s"/>';
        this.emit(':tell', nopitch + xlow + low + medium + high + xhigh);
    },

さて、結果は・・・

こちらもパーセンテージを指定する方法があります。「最小33.3%〜最大50%」と少し限界値がややこしいのが注意点です。

ボリューム

文字で指定できる音声の大きさは以下のものがあります。

  • silent
  • x-soft
  • soft
  • medium
  • loud
  • x-loud

普通の話し方と、これらの全種類の違いが分かるようにLambdaのスクリプトを以下のようにしてみました。

    'TestIntent': function () {
        var novolume = '何も指定せずに話します。なまむぎなまごめなまたまご<break time="2s"/>';
        var silent = 'サイレントで話します。<prosody volume="silent">なまむぎなまごめなまたまご</prosody><break time="2s"/>';
        var xsoft = '小さく話します。<prosody volume="x-soft">なまむぎなまごめなまたまご</prosody><break time="2s"/>';
        var soft = '少し小さく話します。<prosody volume="soft">なまむぎなまごめなまたまご</prosody><break time="2s"/>';
        var medium = 'ふつうに話します。<prosody volume="medium">なまむぎなまごめなまたまご</prosody><break time="2s"/>';
        var loud = '少し大きく話します。<prosody volume="loud">なまむぎなまごめなまたまご</prosody><break time="2s"/>';
        var xloud = '大きく話します。<prosody volume="x-loud">なまむぎなまごめなまたまご</prosody><break time="2s"/>';
        this.emit(':tell', novolume + silent + xsoft + soft + medium + loud + xloud);
    },

さて、結果は・・・

こちらは相対的なデシベル(dB)を数値で指定する方法でチューニングができます。いきなり大きくして周りをびっくりさせないようにしましょうね。

置換

sub タグは、おそらく "substitution" の略だと思います。つまり、囲った言葉を別の言葉に置き換えて喋ってくれます。

Lambdaのスクリプトには、「親友」を「マブダチ」と読ませたくてこのように書きました。

    'TestIntent': function () {
        this.emit(':tell', '彼は<break time="0.2s" />私の<break time="0.2s" /><sub alias="マブダチ">親友</sub><break time="0.2s" />です');
    },

さて、結果は・・・

日本語においては、上記のような使い方よりは、難読漢字や正しく読んでくれない文字などの「振り仮名」として使う機会があるかもですね。

音声ファイルの再生

audio タグは、音声ファイルの再生をしてくれるタグです。

このタグは、HTMLでいうところのimageタグにイメージが近いです。音声ファイルをどこかのサーバに置いておいて、そのURLをsrc属性で指定してやります。

リファレンスに詳しく書いてありますが、このタグの使用にはいくつかの制約があるので注意が必要です。

  • HTTPSでホストされている必要がある
  • 自己署名証明書はダメ
  • ファイルの種類は、MP3ファイル(MPEGバージョン2)である必要がある
  • 90秒以内の音声でなければならない
  • ビットレートは48kbpsである必要がある
  • サンプリングレートが16000Hzである
  • 一度の応答の中で使用できる音声ファイルは5個まで

48kbpsは、ビットレート的には「音楽を再生するには一般に品質がやや不十分」とされているので、用途はできるだけ音楽再生ではなく音声再生という使い方にするのがよいかと思います。

「そんなファイルどうやって用意したらいいの・・・」ってなりそうですが、やさしいことにリファレンスには ffmpeg を使った変換方法まで書いてくれています。 すでに ffmpeg がマシンに入っているならば、下記のようなコマンドを打つだけでAlexaに適したファイルを作ることができます。

$ ffmpeg -i <input-file> -ac 2 -codec:a libmp3lame -b:a 48k -ar 16000 <output-file.mp3>

あとは、AWSのS3にアップロードして公開権限を適切につけてあげれば、上記の条件はおおかたクリアできると思います。

下記が実装例です。

    'TestIntent': function () {
        this.emit(':tell', 'ちょっと今から爆笑させていただきます。<prosody volume="x-loud"><audio src="https://s3-ap-northeast-1.amazonaws.com/(割愛)/hahaha.mp3" /></prosody>。失礼いたしました。');
    },

音声ファイル(hahaha.mp3)は無料の音声素材を提供しているところから適当に引っ張ってきました。

さて、結果は・・・

このように声優さんを使えば、すごくリッチなVUIが完成しそうです。

まとめ

今回さわりの部分だけ実験してみましたが、まだまだ紹介していないタグがあります。 ぜひぜひ色々と試して、Alexaの話し方に個性をつけてみてください。

SSMLの日本語のリファレンスはこちらにあります。