明日から本気出す開発日記

2016/10/31 fc2ブログより引っ越しました。更新はまた明日から本気だす

Node.js 開発

SAP Cloud Platform Functionsで、上司に一方的に電話をかける

この記事は SAP Advent Calendar 16日目の記事です。

会議脱出ボタンが話題になっていますね。

今回は上司に一方的に電話をかけちゃうアプリを、SAP Cloud Platform Functionsを使って、作りたいと思います。

SAP Cloud Platform Functionsとは?

SAPがTechEd 2018ラスベガスで発表したサーバレスアーキテクチャのプログラム実行環境です。
Node.jsで作成したプログラムを実行することが出来ます。
AWS LambdaやAzure Functionsと大体同じです。

1つの強みとしては、S/4HANA及びSAP Cloud Platform Enterprise Messagingと組み合わせることで、オンプレミスS/4HANAのイベントをトリガーとして処理を実行することができます。

SAP Cloud Platform Functions参考ブログ
Part 1: SAP Cloud Platform FunctionsでLINE BOT開発(オウム返し編)
Part 2 : SAP Cloud Platform FunctionsでLINE BOT開発(画像判定編)

作ったもの

まずは下の画像を見て下さい。LINEトークに音声メッセージを送ると、あなたの代わりに(録音の音声を使って)電話をかけてくれます。
直接話したくないなぁ・・・・一方的に伝えることだけ伝えたいときに使いましょう。
IMG_0857

超ざっくりのアーキテクチャを示します。

joshi

なぜこれを作ったのか

  • 合成音声ではなく、自分の声を利用したアプリケーションが作ってみたかった。
  • 会議脱出ボタンをヒントに、一方的にガチャ切りするアプリもあってもいいかなと思った。
  • とにかく変なテンションで作ってしまった。反省している。
  • SAPはあんまり関係ないな・・・と思ったが、FunctionsはSAPだからと無理矢理自分に言い聞かせた。
  • 本当に反省しています。

0.事前準備

下記のサービスを利用しています

  • SAP Cloud Platform Functions (Beta)
  • LINE Messaging API
  • Twilio API
  • Amazon S3

以前私が書いたブログなどを参考に、SAP FunctionsやLINEアカウントの準備をして下さい。

1.音声ファイルの送信

LINEトークで送信した音声は、SAP Cloud Platform Functionsでは以下のようにして取得できます。
この時点での音声形式は、m4aです。

module.exports = { 
 handler: function (event, context) { 
    if (event.data) {
        if (event.data.events[0].type == "message" && event.data.events[0].message.type == "audio") {
            var voiceid = event.data.events[0].message.id;
                
            // ①LINE社のサーバに保存されている音声ファイルを取得
            var options = {
                method: 'GET',
                uri: 'https://api.line.me/v2/bot/message/' + voiceid + '/content',
                encoding: null,
                auth: {
                   bearer: "LINEのAPIトークン"
                }
            };
            request(options, function(error, response, body) {
                // ②音声のバイナリデータが取れた!
                var binarydata = new Buffer(body);
                    
                // do something
            });
        }
    }
  } 
 }

aws-sdkモジュールを使って、取得した音声ファイルをアップロードしてみます。


    var AWS = require('aws-sdk');
    // 先ほど取得した音声データ
    var binarydata = new Buffer(body);
    var s3 = new AWS.S3({
		accessKeyId: 'S3のアクセスキー',
		secretAccessKey: 'S3のシークレットアクセスキー',
		region: 'ap-northeast-1'
    });
    var params = {
		ACL: "public-read",
		Bucket: "S3のバケット名",
		Key: "hogehoge.aac"
    };
    params.Body = binarydata;

    s3.putObject(params, function(err, data) {
		if (err) console.log(err, err.stack);
		else     console.log(data);
    });

残念なことに、Twilioはm4aの音声を再生できないようなので、実際には一手間加えてファイル形式を変換する必要があります。

2.ファイル形式を変換

以下の2つのライブラリを使うことで、m4a形式からwav形式に変換できます。wavはTwilioで再生できる形式です。

  • web-audio-api
  • audiobuffer-to-wav
    var toWav = require('audiobuffer-to-wav');
    var AudioContext = require('web-audio-api').AudioContext;
    var audioContext = new AudioContext;

    // m4aの音声データのバイナリ
    var binarydata = new Buffer(body);

    audioContext.decodeAudioData(binarydata, function(audioBuffer){
        // wavにエンコード
        let wav = toWav(audioBuffer);
        
        // wavのバイナリ(S3にアップロードするやつ)
        var binaryWav = new Buffer(wav);
    });

3.Twilioを使って電話をかける

Twilioで電話をかける場合、メッセージの伝え方は以下の2通りの方法があります。

  • Text to Speech機能を使って合成音声のメッセージを送る。
  • 録音済のメッセージを送る。

今回は、録音済みのメッセージを送ります。

    var querystring = require('querystring');
    var twilio = require('twilio');
    var client = twilio('TwilioのアカウントSID', 'TwilioのAUTH TOKEN');
     
    // Functionsで先ほどwavに変換してアップロードしたファイルのURL
    var twiml = '<Response><Play>https://s3-ap-northeast-1.amazonaws.com/S3のバケット名/hogehoge.wav</Play></Response>';
    
    client.calls
      .create({
         url: 'http://twimlets.com/echo?Twiml=' + querystring.escape(twiml),
         to: '電話をかけたい相手の番号',
         from: 'Twilioの電話番号'
       })
      .then(call => console.log(call.sid))
      .done();

電話を取ると、LINEに送った音声メッセージが流れます。
IMG_0852

 

まとめ

  • 夏休みの宿題を最終日にやるのはやめましょう・・・謎のテンションで変なものができてしまいます。

今回は使いませんでしたが、Enterprise Messagingと組み合わせることでFunctionsは真価を発揮します。
Enterprise Messagingと組み合わせた真っ当な記事は、近いうちにSAPブログの方に寄稿したいと思います。

-Node.js, 開発