Node.js
AWS
lambda
linebot
Clova

LINE Botから送った音声メッセージをClovaで再生する(Node.js)

この投稿はLINEBot&Clova Advent Calendar 2018の7日目の投稿です。

はじめに

LINEの音声メッセージ入力で録音した音声をClovaで非同期に再生できると、
いろいろとコミュニケーションの幅が広がるのではないかと思い、サンプルアプリを作成しました。
LINEが提供しているMessaging APICEKを使用して簡単に実現できたので、その解説を行います。

想定環境と作るもののイメージ

学校がおわり、家でお留守番している子供にがClovaに話しかけると、親があらかじめ録音しておいた伝言を再生します。
グループ化 7.png

構成要素

  • AWS
    • API Gateway
    • Lambda
    • DynamoDB
    • S3(音声メッセージ保存用)
  • Node.js
  • LINE
    • Messaging API SDK
    • CEK(Clova Extensions Kit)

仕組み/システム構成図

グループ化 6.png

  • 音声メッセージ登録処理:
    • Messaging APIのコンテンツを取得するを参考に、音声メッセージをm4aとして取得。
    • 取得した音声メッセージをS3に格納する。
    • DynamoDBにS3のURLをLINE IDと紐づけて格納する。
  • 音声メッセージ取得処理:

サンプルコード

全ソースはこちら(mono0423/dengonkun)をご参照ください。
ポイントとなる部分のみをピックアップします。

LINEBot_音声ファイル取得部分
exports.handler = async (event) {
  const body = JSON.parse(event.body);

  // 音声ファイルを取得
  const audioData = await fetchAudioMessage(body.events[0].message.id);

  // S3にpublic-readで音声ファイルを格納する
  const paramS3 = {
    ACL: 'public-read',
    Body: audioData,
    Bucket: process.env.AUDIO_BUCKET,
    Key: "audio.m4a",
  };
  await s3.putObject(paramS3).promise(); 

  // DynamoDBにS3のURLをインサートする。
  // (省略)
}

// messageIdをもとに、音声ファイルをバイナリで取得する
const fetchAudioMessage = async (messageId) => {
  return new Promise((resolve, reject) => {
    lineClient.getMessageContent(messageId).then((stream) => {
      const content = [];
      stream
          .on('data', (chunk) => {
            content.push(new Buffer(chunk));
          })
          .on('error', (err) => {
            reject(err);
          })
          .on('end', function() {
            resolve(Buffer.concat(content));
          });
    });
  });
}


ClovaSkill側ソース
exports.handler = async (event) => {
  const context = new clova.Context(JSON.parse(event.body));
  const requestType = context.requestObject.request.type;
  const requestHandler = clovaSkillHandler.config.requestHandlers[requestType];

  await requestHandler.call(context, context);

  return {
    statusCode: 200,
    body: JSON.stringify(context.responseObject),
  };
};

// Clovaスキル実行時の動作を設定
const clovaSkillHandler = clova.Client.configureSkill()
    .onLaunchRequest(async (responseHelper) => {
      // DynamoからS3のURLを取得し、s3urlに格納(省略)
      const s3url = "urlToAudioFileFromDynamoDB";

      responseHelper.setSimpleSpeech(
          // createSpeechUrlメソッドに音声ファイルへのURLを渡して再生する
          clova.SpeechBuilder.createSpeechUrl(s3url),
      ).endSession();
    });

まとめ

Messaging APIとCEKを利用し、非同期な音声メッセージの再生を簡単に実現することができました。
Clovaスキル作成方法の記事もどんどん増えてきているので、みなさんもスキル作成にチャレンジしてみてはいかがでしょうか。

明日の記事は@vui_rieさんの「LINE Clova&BOTと生きた2018年
」です!