LoginSignup
2
0

More than 3 years have passed since last update.

Docomo音声合成APIをSDKなしで利用する [Android]

Last updated at Posted at 2019-03-30

概要

※Docomo Developer Suport経由の音声合成API(エーアイ社提供は終了しました)

日頃、個人開発でDocomo Developer Supportにて提供をされている音声合成API(エーアイ社提供)にお世話になっているのですが、昨年12月こんな新着情報が。。

スクリーンショット 2019-03-31 1.32.35.png

2019年3月よりSDKを利用していたコードは動かなくなるとのことでした。
それに伴って既存のSDKを利用していたAndroidのソースコードを改修したので、その時のメモです。

※2019.12月追記: Docomo Developer Support経由の音声合成API(エーアイ社提供)はすでに終了しています。

実装

必要なもの

・Docomo Developer Supportへの登録
・アプリケーション登録(API KEYの入手)
・ガイドラインの確認

仕様

必要な情報は機能別リファレンスに一通り記載があります。

これまで提供されていたSDKは、主に
・音声合成APIとの通信処理
・レスポンスの再生処理
を行なっていたので、自前でその機能を用意してやります。

通信部分の処理

OkHttp3を使っている利用した前提でのメモになります。

リクエスト


            Request.Builder()
                    .url(ApiUrls.AI_TALK_API_URL + "?APIKEY=$apiKey")
                    .addHeader("Content-Type", "application/ssml+xml")
                    .addHeader("Accept", "audio/L16")
                    .post(createRequestBody()) // 後述
                    .build()

リクエストで指定するのは、ApiKey、Content-Type、Accecptの3点です。
Content-Typeに関しては機能別リファレンスを確認して、利用するContent-Typeを指定しましょう。
今回は「application/ssml+xml」を指定しています。

リクエストのBodyについては下記。

    private fun createRequestBody(text: String): RequestBody =
            RequestBody.create(
                    MediaType.parse("application/ssml+xml"),
                    "<?xml version=\"1.0\" encoding=\"utf-8\" ?><speak version=\"1.1\"><voice name=\"nozomi\">$text</voice></speak>"
            )

Bodyに必要なのは、MediaTypeとSSMLの中身。
SSMLは直書きしていますが、実運用する際は記述を工夫した方が良いです。textは読み上げたい文字列です。

※SSMLとは、音声合成用のマークアップ言語のことで、XML形式で読み上げのスピードやピッチ等を指定することができます。
https://dev.smt.docomo.ne.jp/?p=docs.api.page&api_name=text_to_speech&p_name=api_1#tag01

レスポンスの処理

上記のリクエストを行うと音声データがBinary形式でレスポンスが返ってきます。(Acceptにaudio/L16を指定した場合)
音声データは下記のフォーマットになっているので、AudioTrackを対応したパラメータを指定して生成してやれば、再生が可能です。

【符号化方式】
リニアPCM
【チャネル数】
1(モノラル)
【サンプル周波数】
16000
【ビット深度】
16bit(ビッグエンディアン)

                val body = response.body().bytes()
                convertByteOrder16(body)
                val bufSize = AudioTrack.getMinBufferSize(16000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT)
                val player = AudioTrack.Builder()
                        .setAudioFormat(AudioFormat.Builder()
                                .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
                                .setSampleRate(16000)
                                .setChannelMask(AudioFormat.CHANNEL_OUT_MONO)
                                .build())
                        .setBufferSizeInBytes(bufSize)
                        .build()

途中登場している「convertByteOrder16(body)」は、AudioTrackで再生をするためにビッグエンディアンをリトルエンディアンに変換しています。

fun convertByteOrder16(var1: ByteArray?) {
        if (var1 == null) {
            throw IllegalArgumentException("Input Parameter is Invalid.")
        } else {
            var var3 = 0
            while (var3 < var1.size) {
                val var2 = var1[var3 + 1]
                var1[var3 + 1] = var1[var3]
                var1[var3] = var2
                var3 += 2
            }

        }
    }

あとはAudioTrack再生するだけです。

   player.play()
   player.write(body, 0, body.size)

以上、細かいところをかい摘んでのメモではありますが、Docomo音声合成APIをSDKなしで利用した際の記録でした。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0