Amazon Pollyを触ってみたよ by PHP

# まえがき
1年以上ぶりにAWSのコンソールを開いてみたところ、知らないサービスが山ほどあった。
ホント、AWSは機能追加とか多いんで、ついていってる人ってスゴイよね(´・ω・｀)

で。
やたら増えたサービス一覧をうすらボンヤリ眺めていたら
**「人工知能」**
なる魅惑的な項目が・・・・(ﾟ∀ﾟ)
そのうちで自分が使ってる東京リージョンで**「Amazon Polly」**が使えるようだったので、
気になった記念に触ってみたって話です。

あと、自分がゆっくり（softalkとか棒読みちゃんとか）が好きなんで「しゃべるアプリケーション」てのにテンションが上がったから・・・・。

あ、本文中にやたらゆっくりのことが話に挙がると思うんで、キライな人はスルーしてください(=_=)


# Amazon Pollyとは
>Amazon Polly はテキストをリアルなスピーチに変換するクラウドサービスです。Amazon Polly を使用して、エンゲージメントやアクセス性を高めるアプリケーションを開発できます。Amazon Polly では多様な言語がサポートされており、さまざまのリアルな音声が含まれています。そのため、お客様に最適なボイスを使用して、さまざまな場所で機能する音声対応アプリケーションを構築できます。Amazon Polly は、合成したテキスト分のみお支払いいただくだけで利用可能です。また、追加コストなしで、Amazon Polly が生成した音声をキャッシュして再生できます。

[Amazon Polly とは? - Amazon Polly](http://docs.aws.amazon.com/ja_jp/polly/latest/dg/what-is.html)

ですって(・ω・)
うーん・・・・「入力されたテキストを人工の声で再生できる」から人工知能枠なのかしら・・・・？
じゃあ、某ゆっくりも人工知能の可能性が微レ存・・・・？

>Amazon Polly は、文章をリアルな音声に変換するサービスで、話すことができるアプリケーションを作成でき、まったく新しいカテゴリの音声対応製品を構築できます。Amazon Polly は、高度なディープラーニング技術を使用したテキスト読み上げサービスで、人間の声のような音声を合成します。

[【Amazon Polly】（人工知能を活用したテキスト読み上げサービス）| AWS](https://aws.amazon.com/jp/polly/?hp=tile&so-exp=below)

あ、ディープラーニングつかってるのか。
ゆっくり人工知能説は微粒子レベルにも存在しないと・・・・。


# 触ってみる
触るのは簡単。

1. コンソールから「Amazon Polly」を選択
   * 初めて開くときはいつもの「ようこそ」的なのが出るので「いますぐ試す」的なサムシングなボタンをポチる
2. 「プレーンテキスト」タブを選択
    * たぶん最初から選択されてる
2. 表示されるテキスト入力欄に適宜テキストを入れる
    * 最初から「こんにちは、ミズキです。読みたいテキストをここに入力してください。」が入ってた（たぶん東京リージョンだからかな）
3. 「言語とリージョン」から適宜言語を選択
    * とりあえず「日本語」を選択してた
4. 「音声」に選択した言語で選べる音声がラジオボタン形式で表示されるのでどれか選択
    * 日本語の場合は女性のMizukiと男性のTakumiが選択可能（2017/11現在）
5. 「音声を聴く」ボタンをポチる
6. しゃべる

ね、簡単でしょう？
なお、「MP3のダウンロード」ボタンもあるので、作ったヤツは自分のPCにダウンロード可能。

しかし、思いのほか流暢にしゃべるのね。
ゆっくりを触ってた身としては吃驚するレベル。。


# APIもあるよ
これ、毎回ここで入れてMP3ダウンロードして・・・・なのか？
固定メッセージならいいけど、テキスト組み立てて再生とか出来ないのかしら？
なんてこと思ったりしたけどもそんなことはなくて、もちろん出来る。

APIが用意されているので、そちらからテキストを送って適宜ファイル化することが出来る。
それについては、[アプリケーション例](http://docs.aws.amazon.com/ja_jp/polly/latest/dg/examples-for-using-polly.html)としてマニュアルにも記載あり。
AWSに手抜かりなし。

・・・・なんだけど、サーバーサイドのサンプルがPythonとJava。。
私、PHP以外ろくに知らないんですけど・・・・(;´Д｀)
特にPython、たぶんいままでの人生でソース見た時間さえ10分とかそこらだと思うんですが・・・・(;´Д｀)

あきらめるしかないのかなぁ、、、と思ってたら、ちゃんと最新の「AWS SDK for PHP」に入ってる様子。
興が乗ったので試してみたよ。

# PHPからAPIでMizukiにしゃべらせてみるよ

## 試した環境

* PHP(ver7.1.12)
* FuelPHP(v1.8.0)

です。
や、手元でComposerがすぐ使える環境が↑だっただけで、特にそれ固有の処理をさせる気はないよ。

## ComposerでSDKインストール
おなじみ、Composerで「AWS SDK for PHP」を入れる。

```
php composer.pher required aws/aws-sdk-php
```

2017/11現在でver.3.39.2がインストールされた。
探してみたところ、ちゃんとPollyClient.phpが入っていたので一安心。

## で、試す
試す方法として、

1. 画面上でテキストの入力をする
2. PollyClientからAPIを実行
3. 2の結果をMP3ファイルに保存
4. 画面上で再生

な感じにしたい。
そこで思考錯誤した結果、↓のソースを作成した。

```php:fuel/app/classes/controller/polly.php
<?php
use Aws\Credentials\Credentials;
use Aws\Polly\PollyClient;

class Controller_Speak extends Controller
{
	/**
	 * 一覧
	 *
	 * @access public
	 * @return Response
	 */
	public function action_index()
	{
		$list = [];

		// 音声ファイルを探す
		$voice_dir = 'voice'.DIRECTORY_SEPARATOR;
		foreach (glob(DOCROOT.$voice_dir.'*.mp3') as $file) {
			$list[] = [
				'name' => basename($file),
				'url' => \Uri::base().$voice_dir.basename($file)
			];
		}

		return Response::forge(View::forge('polly/index', ['list' => $list]));
	}

	/**
	 * MP3ファイル追加
	 *
	 * @access  public
	 * @return  Response
	 * @see http://docs.aws.amazon.com/aws-sdk-php/v3/api/api-polly-2016-06-10.html#synthesizespeech
	 */
	public function action_add()
	{
		//Log::info(var_export(Input::param(), true));

		$credentials = new Credentials(
			'amazon_access_key',
			'amazon_secret_key');

		$client = new PollyClient([
			'region' => 'ap-northeast-1',
			'version' => 'latest',
			'credentials' => $credentials
		]);

		$result = $client->synthesizeSpeech([
			'OutputFormat' => 'mp3', // REQUIRED
			'Text' => Input::param('text'), // REQUIRED
			'TextType' => 'text',
			'VoiceId' => 'Mizuki', // REQUIRED
		]);

		Log::info(var_export($result, true));

		$voice_dir = DOCROOT.'voice'.DIRECTORY_SEPARATOR;
		if (!is_dir($voice_dir)) {
			mkdir($voice_dir, 0777);
		}

		// 保存
		file_put_contents($voice_dir.Input::param('file_name').'.mp3', $result['AudioStream']);

		// 一覧へ戻す
		Response::redirect('speak/');
	}
}
```
```php:fuel/app/views/polly/index.php
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>Polly</title>
	<?php echo Asset::css('bootstrap.css'); ?>
	<style type="text/css">
		body {
			padding: 0 10px;
		}
		h4 {
			background-color: lightgreen;
		}
		div {
			margin-bottom: 5px;
		}
	</style>
</head>
<body>
	<h1>Pollyの実験</h1>
	<div>
		<h4>新しく生成</h4>
		<form method="post" action="/speak/add">
			<div>
				ファイル名(拡張子は勝手につけるよ)： 
				<input type="text" name="file_name" value="">
			</div>
			<div>
				読ませるテキスト
				<textarea name="text" rows="4" cols="40"></textarea>
			</div>
			<input type="submit" value="追加">
		</form>
	</div>
	<div>
		<h4>生成済みファイル</h4>
		<?php if (!empty($list)) { ?>
			<table border="1">
				<tr>
					<th bgcolor="skyblue" width="150px">ファイル名</th>
					<th bgcolor="skyblue">再生</th>
				</tr>
				<?php foreach ($list as $file) { ?>
					<tr>
						<td><?php echo $file['name']; ?></td>
						<td><audio src="<?php echo $file['url']; ?>" type="audio/mp3" controls></audio></td>
					</tr>
				<?php } ?>
			</table>
		<?php } ?>
	</div>
</body>
</html>
```

最小限・・・・だけど、ちょっと見づらくてイヤになったのでスタイルいじってる。
ひとまずこれで試したかったものは動かすことができたよ(´▽｀)

ちなみに、`PollyClient::synthesizeSpeech` に渡す配列にはもっといろんなパラメータが設定できるみたい。
今回は最小限ってことで`Required`な項目しか入れてないけど、とりあえず試す分には問題なかった。



# 気になる料金は？
一旦動かせるようになると、気になってくるのが料金。
もしかして、いま試した分だけでン万円とか請求されないよね・・・・(;・∀・)

(【Amazon Polly】料金（人工知能を活用したテキスト読み上げサービス） | AWS)[https://aws.amazon.com/jp/polly/pricing/]

>無料利用枠
>Amazon Polly の無料利用枠では、音声の最初のリクエストから 12 か月間は 1 か月あたり 500 万文字まで、音声または Speech Marks リクエストを利用できます。

大丈夫、いつもの無料枠があるみたい(;´∀｀)-3　（2017/11現在）
うーん、実サービスは分からないけど、20分くらいの動画でゆっくりに適宜しゃべってもらったときは数万文字くらいだったから、相当しゃべらせられるイメージでいいのかしら・・・・？
や、ザル勘定だから何も保証できないけども(-_-;)

でも、この無料枠がなくなったら？

> Polly 料金
>音声リクエストについて、100 万文字あたり 4.00 USD の従量課金制 (無料利用枠を超えた場合)Speech Marks リクエストについて、100 万文字あたり 4.00 USD の従量課金制 (無料利用枠を超えた場合)

いつもの従量課金制ですな（2017/11現在）。
こうしてみると、無料枠の優待っぷりがスゴイな・・・・。


# 他にも機能があるよ
さて、これでやりたいことは済んで満足・・・・なのだけど。
実は他にもちょっと機能があったりするみたい。

## SSML
入力可能なテキストはプレーンテキストのほかに**SSML**がある。
あるんだけども、「SSML・・・・なんぞ？(´・ω・｀)」な自分は触れることさえできなかった。。。

AWSのヘルプを見てみると、どうもW3Cにより定義されてる記法みたい。
リンクがあったので見てみたんだけど英語だったので、和訳されてるものを探してみた↓

(音声合成マークアップ言語（SSML）バージョン1.1)[http://www.asahi-net.or.jp/~ax2s-kmtn/ref/accessibility/REC-speech-synthesis11-20100907.html]

>要約
>音声読み上げブラウザ・ワーキンググループは、音声対話によるウェブへのアクセスを可能にする標準の開発に取り組んできました。音声合成マークアップ言語仕様は、この標準のひとつであり、ウェブやその他のアプリケーションにおける合成音声の作成を支援するために豊かなXMLベースのマークアップ言語を提供することを目指しています。このマークアップ言語の本質的な役割は、合成可能なコンテンツの作成者に、合成に対応した様々なプラットフォームにおいて、発音、音量、ピッチ、速度などの読み上げに関する様々な側面を制御するための標準的な方法を提供することです。

なるほど、XMLを利用してもっと思い通りにしゃべらさせよう、というものなのかな。
ちょいとメンドい気もするけど、ホントにお金とるサービスになると必要なんだろうね。
方言とかの微妙なイントネーションとか再現させたいときとかに利用するのかしら？

いくつかMidukiにしゃべらせてみた感じ、そこまで必要とは感じないくらいには聞き取りやすいけどね（対ゆっくり）。


## 音声のカスタマイズ（レキシコン）
音声のカスタマイズの方法として、もうひとつ「レキシコン」というのがある。
「レキシコン」てのは「語彙」て意味の英語で、どうも「そのままだと読めない略称や単語を個別に読み方を定義できるもの」みたい。
この定義はファイルとして登録するようで、言語ごとに5つまで登録可能らしい。

これ知ったときは「いるのそれ？(;・∀・)」と思った。。
ま、ゆっくりはそういうのないからね、最初からかみ砕いたテキストいれれば済むだろって思ったわけ。
たとえば、
　Amazon Polly
をゆっくりに読ませると
　エーエムエーゼットオーエヌ　ピーオーエルエルワイ
とアルファベットを読んじゃうから、こっちで
　あまぞんぽりー
て入力してやる、とかね。

でも、実サービスとして使うんなら必須だろうね。
ユーザーにいちいちかみ砕いたテキスト入力させるとかストレスだろうし、守られなきゃそれで詰みだし・・・・。
そう考えると5件て少ない気もするけど、最悪API実行前にリプレイスするとかなのかな？

同じ単語・読みのレキシコンが多数登録されたら、そのうち未設定でも読めるように取り入れてくれるのかな・・・・。
AWSならやりそうな気もする・・・・。



# あとがき
なんか箸にも棒にも掛からないような記事だけど・・・・(-_-;)
公式サンプル、開発ブログなどなど、調べたときにPHPでのサンプルがなかったので、やったついでに書いてみたよってところです。

あと、他の記事（だいたい2016年記載のものだったかな）だと「日本語はMidukiのみ」とあったのが、実際に見るとTakumiがいて、こういうところもAWSっぽいなぁと感じたり。

ま、いまのところ具体的に「サービスで使おう」て想いがないので、SSML・レキシコンについては試してすらいないんだけど、、、

いずれゆっくり動画にまじってMidukiがしゃべってたりするのかなぁ・・・・(^。^)y-.。o○


# 余談
> Amazon Polly は、文章をリアルな音声に変換するサービスで、話すことができるアプリケーションを作成でき、まったく新しいカテゴリの音声対応製品を構築できます。

上にも書いたコレ、ゆっくりにMidukiっぽく読ませると、こんな感じ↓？

```
あまぞんぽりーは、文章を;リアルなおん'せいにへんかんするサー'ビスで、
話す/ことができる/あぷり'けーしょんをさくせいでき、
まったく新しい/カテゴリのおん'せい対応製品を構築できます
```

音声記号もなしにそれっぽく読めるMidukiはえらい子ですね。。。(;・∀・)