Watson SpeechToTextでBoxにある音声ファイルをテキスト化してみる(Ⅲ.プログラミング)

#概要
この記事は、会議などの音声ファイルをWatson Speech To Textを使って自動でテキスト化するチュートリアルです。
この記事は　Ⅲ.プログラミングです。

>Ⅱ.環境構築編はこちら
>[Watson SpeechToTextでBoxにある音声ファイルをテキスト化してみる(Ⅱ.環境構築編)](http://qiita.com/tokotan/items/d8198af88d24cb72c0b4)

#プログラミング
Node.jsとrestifyウェブフレームワークを利用します。
（プログラミングは独学のため（業務経験なし)、間違いがあれば指摘ください。)


##Boxからのリクエストを受け取る

```server.js
'use strict';

//Import Modules
const restify = require('restify');
const expressSession = require('express-session');
const watson = require('./watson-service.js');

// Setup Restify Server
const server = restify.createServer();
server.listen(process.env.port || process.env.PORT || 3978, function () {
   console.log('%s listening to %s', server.name, server.url);
});

server.use(restify.queryParser());
server.use(restify.bodyParser());
server.use(expressSession({ secret: 'keyboard cat', resave: true, saveUninitialized: false }));

server.get('/api/box/ja', function(req, res){
  res.send('I will upload the script of this file. Close this window, and please wait a minute.');
  watson.stt(req,'ja-JP_BroadbandModel', function(){
    console.log(res);
  });
});
```
##Boxからのリクエストを受け取る
Boxで[日本語テキスト化]メニューをクリックすると、BoxからGETで下記のパラメータが渡されます。
-　auth_code:OAuth2.0の認証コード。30秒以内にこのコードを使ってAccessToken,RefreshTokenを取得することができますが、今回は何もしません。
-　user_id:メニューをクリックしたBoxユーザーのID
-　file_id:クリックされたファイルのID
-　file_extension:クリックされたファイルの拡張子

```watson-service.js
exports.stt = function (req, lang) {
  const authCode = req.query.auth_code;
  const userId = req.query.user_id;
  const fileId = req.query.file_id;
  const fileExtension = req.query.file_extension;
}
```

##Boxからリクエストを受けたファイルをダウンロードする
Boxへのアクセスは、box-node-sdkを使います。
インストール方法や使い方は、下記を参照してください。
> https://github.com/box/box-node-sdk

Boxからダウンロードしたファイルは一時的にHerokuサーバーの/tmp配下にダウンロードします。Herokuでは基本的にファイルの保存はできないのですが、唯一/tmpフォルダ配下は書き込みができます。しかし、再起動で消えるので、本当に一時的な利用となります。今回はテストのために利用します。

```watson-service.js
'use strict';

//Herokuへセットした環境変数を読み込みます
const BOX_CLIENT_ID_JWT = process.env.BOX_CLIENT_ID_JWT;
const BOX_CLIENT_SECRET_JWT　= process.env.BOX_CLIENT_SECRET_JWT;
const PRIVATE_KEY = process.env.PRIVATE_KEY;
const APP_ENTERPRISE_ID = process.env.APP_ENTERPRISE_ID;
const BOX_KEY_ID = process.env.BOX_KEY_ID
const BOX_PASSPHRASE = process.env.BOX_PASSPHRASE;

let Promise = require('bluebird');
const fs = require('fs');
const BoxSDK = require('box-node-sdk');

exports.stt = function (req, lang) {
  var audiofile = '/tmp/'+fileId+'.'+fileExtension;
  var fileInfo = {'filename':'', 'folderId':''};

  var sdk = new BoxSDK({
  	clientID: BOX_CLIENT_ID_JWT,
  	clientSecret: BOX_CLIENT_SECRET_JWT,
  	appAuth: {
      keyID: BOX_KEY_ID,
      privateKey: PRIVATE_KEY,
      passphrase: BOX_PASSPHRASE
  	}
  });

  let promise = new Promise((resolve, reject) => {
    var appUserClient = sdk.getAppAuthClient('user', '<box App UserのユーザーID>');
    appUserClient.files.get(fileId, null, function(err, res){
      if(err){
        reject(err);
      }
      fileInfo.filename = res.name;
      fileInfo.folderId = res.parent.id;
      resolve();
    });
  });

  promise.then(() => {
    var appUserClient = sdk.getAppAuthClient('user', '<box App UserのユーザーID>');

    appUserClient.files.getReadStream(fileId, null, function(error, stream) {
      if (err) {
        console.log(err);
        reject(err);
      }
      var output = fs.createWriteStream(audiofile);
      stream.pipe(output);
      output.on('close', function(){
        resolve(fileInfo);
      });
    });
  }).catch((err) => {
    console.error(err);
  });
};
```

##Watson Speech To Textでテキスト化する&Boxへファイルをアップロードする
Watsonへのアクセスは、watson-developer-cloud/node-sdkを使います。
インストール方法や使い方は、下記を参照してください。
> https://github.com/watson-developer-cloud/node-sdk?cm_mc_uid=32231396635114809028629&cm_mc_sid_50200000=1502807420&cm_mc_sid_52640000=1502807420

パラメータは、下記を参照してください。
> Transcribing audio: Input features and parameters
> https://www.ibm.com/watson/developercloud/doc/speech-to-text/input.html

```watson-service.js
'use strict';

//Herokuへセットした環境変数を読み込みます
const WATSON_USERNAME = process.env.WATSON_USERNAME;
const WATSON_PASSWORD = process.env.WATSON_PASSWORD;

const SpeechToTextV1 = require('watson-developer-cloud/speech-to-text/v1');
const async = require('async');
const request = require('request');

exports.stt = function (req, lang) {
　　　　：
  //Boxからファイルをダウンロードする処理は省略
　　　　：
}).then(() => {
    return new Promise((resolve, reject) => {
      let speech_to_text = new SpeechToTextV1({
        username: WATSON_USERNAME,
        password: WATSON_PASSWORD
      });

      const params = {
        audio: fs.createReadStream(audiofile),
        content_type: 'audio/'+fileExtension,
        model: lang
      };

      speech_to_text.recognize(params, function(err, res) {
        if (err) {
          console.log(err);
          reject(err);
        }
        async.eachSeries(res.results,function(value,next){
          fs.appendFile('/tmp/'+fileId+'.txt', value.alternatives[0].transcript+'.\n', function (err) {
            if (err) {
              console.log(err);
              throw err;
            } else {
              next();
            }
          });
        },function(err){
          // Get an app user client
          const appUserClient = sdk.getAppAuthClient('user', '<box App UserのユーザーID>');
          const stream = fs.createReadStream('/tmp/'+fileId+'.txt');
          appUserClient.files.uploadFile(fileInfo.folderId, fileInfo.filename+'.txt', stream, function(err, response) {
            if(err){
              console.log(err);
              reject(err);
            }
            console.log(response);
            resolve();
          });
        });
      });
    });
  }).catch((err) => {
    console.error(err);
  });
};
```
#デプロイ
Herokuへデプロイします。

```
$ git add . && git commit -m "<your message>" && git push heroku master
```

ログを確認する場合は、下記コマンドです。

```
$ heroku logs --tail
```

#続き
実行結果を確認したいと思います。
また、このチュートリアルを作成するにあたり、ハマったポイントを紹介します！

>Ⅳ.動作確認編はこちら
>[Watson SpeechToTextでBoxにある音声ファイルをテキスト化してみる(動作確認)](http://qiita.com/tokotan/items/9ae5a5fd4ef1d2f92ce4)