Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

この投稿は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年
」です!

tmisuoka0423
ProtoOutStudio 2期生/産んで育てるエンジニアになりたい
https://github.com/tmitsuoka0423
protoout-studio
プロトアウトスタジオは日本初のプロトタイピング専門スクールです。プログラミングだけではなく、企画力と発信力を身に付けて”自分で課題を見つけて実装し、発信し続ける人”を育成しています。 圧倒的なアウトプット力を身に付けましょう。 学生募集中です。
https://protoout.studio
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away