AWS PollyとMicrosoft Translator APIを使って、テキストを翻訳して音声に変換する

## はじめに

AWS Pollyが面白そうだったので、Node.jsを使ってコマンドラインでテキストを翻訳してmp3ファイルにするスクリプトを書いてみました。

説明めんどいので、以下のあたりを参考にしてください。

[Node.js 内の AWS SDK for JavaScript](https://aws.amazon.com/jp/sdk-for-node-js/)
[AWS SDK for Node.js を使い始める ｜ Developers.IO](http://dev.classmethod.jp/cloud/aws-sdk-for-node-js-start/)
[Class: AWS.Polly](http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Polly.html)
[Microsoft Translator Text APIをNode.jsから使ってみる](http://qiita.com/n0bisuke/items/350752978b16f4429b31)
[Microsoft Translator APIを使ってみる](http://qiita.com/kemayako/items/21fe36005e6e729aff77)
[PollyをAWS SDK for Pythonからコールする](http://qiita.com/motchi0214/items/df08855bd6947809268a)


## コード

```polly.js
'use strict'

var fs = require('fs');
var http = require('http');
var https = require('https');
var qs = require('querystring');
var AWS = require('aws-sdk');

AWS.config.update({region:'us-east-1'});

var polly = new AWS.Polly({
    apiVersion: '2016-06-10',
    endpoint: 'https://polly.us-east-1.amazonaws.com'
});

if(process.argv.length <= 2){
    console.log('Usage: node polly.js TEXT');
    process.exit();
}



class Talker {
    talk(text){
        var params = {
            OutputFormat: 'mp3',
            Text: text,
            VoiceId: 'Mizuki',
            SampleRate: '22050', /* for mp3 8000, 16000 or 22050. for pcm 8000 or 16000 */
            TextType: 'text'
        };
        polly.synthesizeSpeech(params, function(err, data) {
            if (err){
                console.log(err, err.stack); // an error occurred
            } else {
                var audio = data.AudioStream;
                var filename = process.argv[2] + '.mp3';
                fs.writeFile(filename, audio , function (err) {
                    console.log(err);
                });
            }
        });
    }
}

class Translator {
    constructor(client_id, client_secret){
        this.client_id = client_id;
        this.client_secret = client_secret;
    }

    translate(text, callback){
        var _this = this;
        this.getAccessToken(function (token) {
            _this.call_ms_translator(token, text, callback);
        });
    }

    getAccessToken(callback) {
        var body = '';
        var req = https.request({
            host: 'datamarket.accesscontrol.windows.net',
            path: '/v2/OAuth2-13',
            method: 'POST'
        }, function (res) {
            res.setEncoding('utf8');
            res.on('data', function (chunk) {
                body += chunk;
            }).on('end', function () {
                var resData = JSON.parse(body);
                callback(resData.access_token);
            });
        }).on('error', function (err) {
            console.log(err);
        });
        var data = {
            'client_id': this.client_id,
            'client_secret': this.client_secret,
            'scope': 'http://api.microsofttranslator.com',
            'grant_type': 'client_credentials'
        };

        req.write(qs.stringify(data));
        req.end();
    }

    call_ms_translator(token, text, callback) {
        var options = '&from=en&to=ja' +
                '&text=' + qs.escape(text);
        var body = '';
        var req = http.request({
            host: 'api.microsofttranslator.com',
            path: '/V2/Ajax.svc/Translate?' + options,
            method: 'GET',
            headers: {
                Authorization: 'Bearer ' + token,
            }
        }, function (res) {
            res.setEncoding('utf8');
            res.on('data', function (chunk) {
                body += chunk;
            }).on('end', function () {
                body = body.substr(2, body.length - 3);
                callback(body);
            });
        }).on('error', function (err) {
            console.log(err);
        });

        req.end();
    }
}

var text = process.argv[2];
var talker = new Talker();

var client_id = 'MS Translatorの自分のアプリケーションのクライアントID';
var client_secret = 'MS Translatorの自分のアプリケーションのクライアントシークレット';
var translator = new Translator(client_id, client_secret);
translator.translate(text, function(translated){
    talker.talk(translated);
});
```

## 使い方

>あらかじめ、```~/.aws/credentials```にPollyのフルアクセス権（？）を持ったIDとパスワード的なものを保存しておく必要があります。
>また、Microsoft TranslatorのIDとパスワード的なものを取得してコード上で指定しておきます。

コマンドライン引数に翻訳したい英文を指定します。

```bash:音声ファイル作成
$ node polly.js "This is a pen."
```

Macの場合、以下のコマンドで音声が再生されます（環境にもよりますがiTunesが起動し再生します）。

```bash:再生（Macの場合）
$ open This\ is\ a\ pen..mp3
```

「これはペンです。」と再生されたら成功です。