はじめに
Amazon Polly は AWS 上で使える AI による音声合成 = 文書の読み上げサービスです
ブラウザからお手軽に試す場合、以下の記事を参考にしてください
本記事では Elixir の Livebook から Polly を使い、文章の読み上げを実装します
実装したノートブックはこちら
Livebook とは
Livebook は Elixir のコードをブラウザから実行し、結果を表示してくれるツールです
Python における Jupyter のようなもので、 Elixir 入門や Elixir を使ったデータ分析、データの視覚化などに適しています
はじめ方は以下の記事を参考にしてください
セットアップ
Livebook で新しいノートブックを開いたら、先頭のセットアップセルに以下のコードを入力し、実行してください
Mix.install([
{:aws, "~> 0.13"},
{:hackney, "~> 1.20"},
{:kino, "~> 0.11"}
])
AWS サービスの操作用に AWS Elixir というモジュールをインストールしています
クライアントの準備
AWS の認証情報を入力するためのテキストボックスを準備します
access_key_id_input = Kino.Input.password("ACCESS_KEY_ID")
secret_access_key_input = Kino.Input.password("SECRET_ACCESS_KEY")
region_input = Kino.Input.text("REGION")
[
access_key_id_input,
secret_access_key_input,
region_input
]
|> Kino.Layout.grid(columns: 3)
セルを実行して表示されたテキストボックスにそれぞれ入力してください
AWS の API と通信するためのクライアントを用意します
この際、先ほどの認証情報を受け渡します
client =
AWS.Client.create(
Kino.Input.read(access_key_id_input),
Kino.Input.read(secret_access_key_input),
Kino.Input.read(region_input)
)
音声合成
Polly には standard と neural の2種類のエンジン(音声合成を処理するプログラム)があります
まずは standard を試してみます
describe_voices
で standard エンジンの日本語( js-JP
)で使える声の一覧を取得しましょう
voice_list =
client
|> AWS.Polly.describe_voices("standard", nil, "ja-JP")
|> elem(1)
|> Map.get("Voices")
|> Enum.map(fn voice ->
Map.take(voice, ["Id", "Gender", "Name", "LanguageName"])
end)
Kino.DataTable.new(voice_list)
男性の Takumi と女性の Mizuki が使えるようです
今回は Takumi を使ってみましょう
次に読み上げる文章を入力するため、テキストエリアを作ります
text_input = Kino.Input.textarea("TEXT")
表示されたテキストエリアに読み上げさせたい文章を入力します
本記事では「オオカミと七ひきの子ヤギ」の冒頭を読ませてみます
synthesize_speech
にエンジン、言語、声の ID 、出力フォーマット、読ませたい文章を指定します
通常の AWS の API は実行結果が JSON で返ってきますが、 synthesize_speech
の場合、音声のバイナリデータが返ってきます
そのため、 JSON として結果を読み込まないよう、オプション(第3引数)に receive_body_as_binary?: true
を指定しています
result =
client
|> AWS.Polly.synthesize_speech(
%{
"Engine" => "standard",
"LanguageCode" => "ja-JP",
"VoiceId" => "Takumi",
"OutputFormat" => "mp3",
"Text" => Kino.Input.read(text_input)
},
receive_body_as_binary?: true
)
|> elem(1)
|> Map.get("Body")
実行結果
<<73, 68, 51, 4, 0, 0, 0, 0, 0, 35, 84, 83, 83, 69, 0, 0, 0, 15, 0, 0, 3, 76, 97, 118, 102, 53, 56,
46, 55, 54, 46, 49, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 243, 96, 196, 0, ...>>
このバイナリデータを Base64 形式に変換することで、 Web 上で再生できるようになります
result
|> Base.encode64()
|> then(fn base64 ->
Kino.HTML.new("""
<audio controls src="data:audio/mp3;base64,#{base64}">
</audio>
""")
end)
表示されたコントロールの再生ボタンをクリックすると、以下の動画のように音声が再生されます
多少ぎこちなくはありますが、きちんと読み上げています
neural エンジンも試してみましょう
neural エンジンの日本語で使用可能な声の一覧を取得します
voice_list =
client
|> AWS.Polly.describe_voices("neural", nil, "ja-JP")
|> elem(1)
|> Map.get("Voices")
|> Enum.map(fn voice ->
Map.take(voice, ["Id", "Gender", "Name", "LanguageName"])
end)
Kino.DataTable.new(voice_list)
Takumi は neural エンジンでも付き合えるようなので、引き続き Takumi に喋ってもらいます
client
|> AWS.Polly.synthesize_speech(
%{
"Engine" => "neural",
"LanguageCode" => "ja-JP",
"VoiceId" => "Takumi",
"OutputFormat" => "mp3",
"Text" => Kino.Input.read(text_input)
},
receive_body_as_binary?: true
)
|> elem(1)
|> Map.get("Body")
|> Base.encode64()
|> then(fn base64 ->
Kino.HTML.new("""
<audio controls src="data:audio/mp3;base64,#{base64}">
</audio>
""")
end)
実行結果
さっきより滑らかになりました
まとめ
Livebook から Amazon Polly による音声合成が実行できました
Livebook は音声や画像などのデータも簡単に扱えるのが便利ですね
Transcribe と Polly を組み合わせれば、音声での自動応答システムも簡単に作れそうです