LINE BOT AWARDSのハッカソンに参加した。ぷ◯きゅあがタスクの終了や寝る時間などを通知すると同時に音声合成でしゃべってくれる、という(いちおう)親子向けのBOTを作った。

LINE apiはeventに応じてwebhookが飛んでくる仕様になっているため、serverlessのアーキテクチャでシステムを作った。つまりlambda、step functionsをはじめとしたaws漬けだったのだが簡単に優れた設計のアプリが作れて僕スゴいじゃなくてawsマジすごい。

そのソースコードも公開する予定なのだが、スポンサー企業でもあったAITalkさんのAPIを呼んで音声合成したWAVEファイルをs3に保存するところは汎用性が高そうなのでgithubにrepositoryを作った。

https://github.com/Drunkar/aitalk_webapi_wav_generator_lambda

中身もいちおうここに貼っておく。めんどくさかったのは、jsのaws-sdkにはs3にファイルをアップロードする方法がなかった(rubyにはあるみたい)ので、jsのオブジェクトとしてメモリに保持した状態でputObject()することでI got Kotonaki. たぶんstreamを理解している人ならば一時ファイルとして/tmp以下に保存することなくs3にアップロードするコードが書けると思う。


var http = require("http");
var fs = require("fs");
var aws = require("aws-sdk");

var api_url = "http://webapi.aitalk.jp/webapi/v2/ttsget.php";

exports.handler = function(event, context) {
    var request_url = api_url +
        "?username=" + encodeURI(event.aitalk_username) +
        "&password=" + encodeURI(event.aitalk_password) +
        "&text=" + encodeURI(event.text) +
        "&speaker_name=" + encodeURI(event.aitalk_speaker_name) +
        "&volume=" + encodeURI(event.aitalk_volume) +
        "&speed=" + encodeURI(event.aitalk_speed) +
        "&pitch=" + encodeURI(event.aitalk_pitch) +
        "&range=" + encodeURI(event.aitalk_range) +
        "&ext=wav&use_wdic=1";

    var outFile = fs.createWriteStream("/tmp/" + event.filename);
    // start download
    http.get(request_url, function(res) {

        // output as a file
        res.pipe(outFile);

        // download end
        res.on("end", function() {
            outFile.close();

            // open the wav file as a js object and putObject to S3
            var s3 = new aws.S3();
            fs.readFile("/tmp/" + event.filename, function(err, data) {
                if (err) {
                    return console.log(err);
                }
                var params = {
                    Bucket: event.bucket,
                    Key: event.filename,
                    Body: data,
                    ContentType: "audio/wav",
                    ACL: "public-read"
                };
                s3.putObject(params, function(err, data) {
                    console.log(err, data);
                });
            });

        });
    }).on("error", function(e) {
        context.done("error", e);
    });
};

テストイベントを以下のように飛ばせばおk。


{
  "aitalk_username": "",
  "aitalk_password": "",
  "aitalk_speaker_name": "nozomi_emo",
  "aitalk_volume": "2.00",
  "aitalk_speed": "1.20",
  "aitalk_pitch": "0.90",
  "aitalk_range": "2.00",
  "text": "戦争に負けたから堕ちるのではないのだ。人間だから堕ちるのであり、生きているから堕ちるだけだ。",
  "filename": "voice.wav",
  "bucket": ""
}

関連記事

fitbitの睡眠スコアを90弱で安定させる良い睡眠を続ける簡単な方法

m1 ipad pro 12.9 2021のusb-cハブはコレがベスト

Time Machine不要!Macを11.2.3にダウングレードして原神をm1 macbook airでプレイする

MH-Z19CとM5StickCで二酸化炭素濃度モニタリング

【神軽量HMD】Avegant Glyph 改造: 瓶詰堂さんのaltglyphを作った

PC、iPad、Android、switchもドックいらず!あまりに万能なusb-cハブが最強だった

コメント

コメントを返信する

メールアドレスが公開されることはありません。 が付いている欄は必須項目です