Blog

リモート会議のリアクションわかりづらい問題を解消する「もじこえ」を作ってみた

はじめに

こんにちは!新卒入社4年目の小松です。主にお客様が初めて@niftyをご利用になる際の無料ID会員登録システム、いろいろなサービスをご利用になる際のログインシステムの開発・運用を担当しています。

今回はリモート会議のリアクションわかりづらい問題を解消するツール「もじこえ」を作ってみたので、紹介したいと思います。社内でも一部の会議では実際に使われています。

リモート会議はリアクションがわかりづらい

対面での会議と違って、参加者のリアクションがわかりづらいと感じたときはありませんか。
カメラ・マイクがオフの時はもちろん、うなずきや笑い声など些細なリアクションがわかりづらく、伝わっているのか不安になることがあります。
また実際にはワイワイとしている会議も、コメントを拾い忘れたり、盛り上がりに欠けるなと感じたこともあります。
そこで「もじこえ」を作りました。

もじこえ

AI音声でコメント読み上げてくれる匿名チャットツールWebアプリです。
使い方は、リモート会議時に参加者が「もじこえ」をブラウザで開いてチャットします。
読み上げ音声は現在3種類で、コメント投稿ごとに切り替えできます。
実際に使ってみないと伝わりづらいかと思いますが、画面はこんな感じです。
まだデザインを考え中なので、プロトタイプになっています。

ちなみに名前の由来は、GoogleMeet拡張機能の「こえもじ」というものがありまして、Meetで話した内容を文字起こしして、コメント欄に追加してくれるものです。
その逆(テキスト→音声)もあればと思ったのが始まりでした。 試しに社内に公開してみましたが、意外と反応があり、社内のLT大会や勉強会などでも使われています。ちなみに私が所属するサービスインフラチームでは、毎日使っています。

もじこえ の中身

構成

バックエンドはNode.js + Expressで、Socket.IOを使ってリアルタイムチャットできるようにしています。音声変換はAWS SDKのPollyを使っています。
フロントは生HTMLとJQueryです。デザインはあとまわしにしているので、のちのちReactなどで作り直したいと思っています。
これらをAWSのFargateで動かしています。
後ほど紹介するSlack連携では、Slack Appを作成し、 Lambdaも使用しています。

読み上げ音声はAWSのAmazon Pollyを使用

Amazon Polly はテキストを音声に変換してくれるAWSのサービスです。様々な言語に対応し、日本語にも対応しています。
料金は、100万文字ごとに4ドルなので、そこまで気にせず使えるかなと思っています。今までで最高でも3ドル未満でした。

もじこえ には、3種類の音声を採用

日本語が話せる3種類の音声を採用しました。結構リアルです。
一番人気はマシューです。
  • ミズキ(女性)
  • タクミ(男性)
  • マシュー(外国籍で日本語も話せる男性)
マシューの音声サンプル

ソース紹介

まだリポジトリを公開できる状態ではないため、一部を紹介していきます。

テキスト→音声変換 部分

Node.js + Expressのサーバ側で、AWS SDKでPollyを使用します。 getSynthesizeSpeechUrlを使って、テキストを音声URLに変換します。
テキストの省略は、長すぎる文章と、URLは考慮して行っています。
そのままだと、URLは律儀に1文字ずつ読み上げてくれます。
ただし、各クライアント側で表示されるテキストは省略せずそのままで、音声変換時のみ省略されたテキストを使います。

チャット部分

Socket.IOを使ったチャット自体はよくある使い方です。単純にテキストと、音声変換した音声URLを各部屋のクライアント側に送信しているだけです。

サーバー側

ここはシンプルですが、受け取ったテキストを音声URLに変換して、クライアント側に送信します。
channelIdがあれば、Slackにも送信します。

クライアント側

URLパス(/room/{各部屋番号})ごとに部屋を分けるようにしているので、各部屋に入室させます。
Slack連携については、後述します。
音声URLの再生はシンプルで、Audio()を使っています。

Slack連携

Slack連携をするようにした背景は、ニフティでは特定のリモート会議(大人数が参加するイベントなど)ではSlack実況チャンネルというものが存在していて、実況の分断をなくすためです。
現時点では、「もじこえ」、Slackの双方向にコメントがそれぞれのコメントが流れるようにしました。

もじこえ → Slackのチャンネル

部屋番号をSlackのチャンネルIDにすることで、(/room/{SlackのチャンネルID})でチャンネルIDを取得します。Slack連携にチェックをつければ、サーバ側でwebhookを使ってSlackチャンネルに送信します。
SlackにPOSTするデータは以下です。現状おそらくSlackで音声再生はできないのですが、再生ボタンの絵文字を押せば、音声URLが開く仕組みにしています。

Slackのチャンネル → もじこえ

こちらは、Slack Appを作成して、メッセージデータを取れるようにしました。
データの受取先は手軽なAWS Lambda + API Gatewayにしました。

Lambda + API Gateway

APIGatewayはLambdaのAPI化に使っただけで、特に珍しいこともしていないので、説明は省きます。 Lambdaソースは以下になります。 SlackのRequestを受け取るにはSlack Appで承認される必要があります。リクエストデータにchallengeが含まれていたら、特定のレスポンスを返すようにします。

また双方向の実装するにあたり、考慮する必要があったのが、「もじこえ」→Slackに送信された場合、Slack AppのEventが発火され、「もじこえ」→ Slack → 「もじこえ」のように再び送信しようとすることです。
以下のように、SlackからPOSTされるデータのeventsubtypeを見ると、bot_messageになっているのがわかったので、ここで判別するようにしました。ちなみに、普通にSlackに投稿した場合は"type": "message"になります。 「もじこえ」に送信する部分については、「もじこえ」のサーバ側で簡単なAPIを作成したので、それを呼ぶだけです。
まずサーバ側で部屋名とメッセージを受け取り、音声はランダムにして、音声URLを作成し、対象の部屋に送信します。

サーバ側のソース

Slack Appの設定

Subscribe to bot eventsmessage.channelsを追加すると、作成したSlack Appが追加されているチャンネルでメッセージが投稿されたときに、連携したURLにデータをPOSTしてくれます。
※外部にSlackメッセージが送信されるので、扱いには気をつける必要があります。
Lambda + API Gatewayで受け取るRequest URLに追加して連携します。上で説明した、特定のレスポンスを返す用に実装しておくと承認されます。
準備ができたので、あとは連携したいチャンネルにSlack Appを招待。
「もじこえ」のURLを/room/{SlackのチャンネルID}にして、Slack連携のチェックをいれれば、完成です。

今後やること

もともと勉強で作り始めたもので、まだまだやることがいっぱいあります。
  • フロントをReactなどで書き換える
  • Slack連携のオンオフ制御
  • 社内SSO連携
    • 現在匿名でのコメントになるので、チームで相談してログ整備は必要ということになりました。
  • Meetの拡張機能にできないか調査
  • などなど
またなにか進展があれば、ブログに書こうかと思ってます!

【告知】NIFTY Tech Dayで「もじこえ」について話すかもしれません!

We are hiring!

ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください!