LoginSignup
3
0

More than 1 year has passed since last update.

はじめに

この記事は「Twilioを使うためのコツ、TIPSなど、Twilioのことなら何でも共有しよう!」の7日目の記事です.

このご時世,業務・プライベート関わらずオンラインでビデオ通話をする機会が多いと思います.
でも,「このビデオ通話そろそろ抜けたいなぁ」と思うことがあるんじゃないでしょうか.
例えば
- 眠たくなってきたオンライン飲み会
- 次の仕事に行きたいけど,延長している会議
- そろそろ休憩したい作業通話 etc...

そんなとき「そろそろ僕はこのへんで...」と伝えるの,すごくハードルが高いですよね.
それを解決するためにボタンを押すとそろそろ抜けたい..と匿名で伝えてくれるビデオ通話アプリを作成しました.

本題

こんな感じで終わりたい人がいることを全員に伝えたいです.
スクリーンショット 2021-11-21 22.00.13.jpg

今回の実装は Githubで確認できます.

概要

ビデオ通話機能には,Twilio を使います.

準備

1. Twilioアカウントを作成します.

2. ベースとなるコードをFork & Cloneする.

基本的なビデオ機能は既に実装したものを使いましょう.

3. 必要となる認証情報を準備する

ACCOUNT SIDを取得する

ACCOUNT_SIDは Consoleから取得できます.

API KEYを作成する

API_KEY_SIDとAPI_KEY_SECRETは API Keysから「Create API Key」を選択します.

スクリーンショット 2021-11-12 19.40.19.jpg

API KEYに分かりやすい名前をつけます.今回は「Finish Button」にします.
スクリーンショット 2021-11-12 19.42.04.jpg

するとSIDとSecretが表示されるので,次項の.envへコピペします.

.envに書き込む

.env.templateがあるので,これを.envという名前に変更し,中身を以下のように書き換えます.

.env
TWILIO_ACCOUNT_SID=ACCOUNT_SIDをコピペする
TWILIO_API_KEY_SID=API_KEY_SIDをコピペする
TWILIO_API_KEY_SECRET=API_KEY_SECRETをコピペする

4. 依存関係をインストールする

今回はPythonを使うのでvenvを使って仮想環境を準備し,pip installします.

$ python -m venv venv
$ source /venv/bin/activate
(windowsの人は $ source venv\Scripts\activate)
(venv) $ pip install -r requirements.txt

5. 起動してみる

(venv) $ FLASK_ENV=development flask run

ブラウザでlocalhost:5000にアクセスし,別タブからも同様に接続すると以下のような画面が表示されると思います.ビデオと音声の使用は許可してください.

スクリーンショット 2021-11-21 18.34.05.jpg

実装していく

ここからがこの記事のメインです.「そろそろ終わりたいなぁと○人が思っています」を伝える機能を作っていきます.

1. UI(ボタン・表示領域)を用意する

templates/index.html
 ... 省略 ...

 <form>
  <label for="username">Name: </label>
  <input type="text" name=”username” id="username">
  <button id="join_leave">Join call</button>
+ <button id="wanna_finish_button" disabled>Wanna finish this call</button>
 </form>
 <p id="count">Disconnected.</p>
+<h2 id="wanna_finish_presenter" class="wanna_finish"></h2>
 <div id="container" class="container">
 ... 省略 ...

ボタンを通話がつながっている時に1回だけ押せるようにします.

static/app.js
+ const wannaFinishButton = document.getElementById("wanna_finish_button");

const disconnect = () => {
 ... 省略 ...
  toogleChat.disabled = true;
+ wannaFinishButton.disabled = true;
  connected = false;
  updateParticipantCount();
};

const connectButtonHandler = (event) => {
    event.preventDefault();
    ... 省略 ...
    connect(username).then(()=>{
      joinLeaveButton.innerText = "Leave call";
      joinLeaveButton.disabled = false;
+     wannaFinishButton.disabled = false;
})
      ... 省略 ...
 }
};

2. 自分だけに表示する

まずは自分の画面だけに「そろそろ終わりたいなぁと○人が思っています」を表示しましょう

static/app.js
+ let wannaFinishCount = 1;
+
+ const wannaFinishHandler = (event) => {
+   event.preventDefault();
+   addToWannaFinishPresenter(`そろそろ終わりたいなぁと${wannaFinishCount}人が思っています`)
+   wannaFinishButton.disabled = true;
+ }
+ 
+ 
+ const addToWannaFinishPresenter = (newText) => {
+   let presenter = document.getElementById("wanna_finish_presenter");
+   presenter.innerHTML = newText;
+ }
+ 
+ wannaFinishButton.addEventListener('click', wannaFinishHandler);

この時点で以下のように「Wanna finish this call」ボタンが表示されます.
スクリーンショット 2021-11-21 22.13.32.jpg

ボタンを押すと「そろそろ終わりたいなぁと1人が思っています」と表示されます.

スクリーンショット 2021-11-21 22.12.49.jpg

3. 通話に参加している他の人にも「そろそろ終わりたいなぁと○人が思っています」を送る

static/app.js
+ let dataTrack;

const connect = (username) =>
  new Promise((resolve, reject) => {
  ... 省略 ...
  fetch("/login", {
   ... 省略 ...
  }).then(_room => {
  room = _room;
+  room.localParticipant.publishTrack(dataTrack);
   room.participants.forEach(participantConnected);
   ... 省略 ...
});

const trackSubscribed = (div, track) => {
+   if (track.kind === 'data') {
+       track.on("message", (data) => {
+       addToWannaFinishPresenter(JSON.parse(data).message);
+           wannaFinishCount++;
+       });
+    } else {
    div.appendChild(track.attach());
+  }
};

const trackUnsubscribed = (track) => {
+   if (track.kind === 'data') {
+ document.getElementById("wanna_finish_presenter").innerHTML = "";
+   } else {
  track.detach().forEach((element) => element.remove());
+   }
};

const wannaFinishHandler = (event) => {
    event.preventDefault();
    addToWannaFinishPresenter(`そろそろ終わりたいなぁと${wannaFinishCount}人が思っています`)
+   sendDataToRoom(`そろそろ終わりたいなぁと${wannaFinishCount}人が思っています`);
    wannaFinishButton.disabled = true;
}
+ 
+const addLocalData = () => {
+   dataTrack = new Twilio.Video.LocalDataTrack();
+}
+
+  const sendDataToRoom = (data) => {
+   dataTrack.send(JSON.stringify({
+       message: data
+   }))
+ };
+
+ addLocalData();

Tracks とは

Twilio の Programmable Video APIのTracksとは 個別の音・ビデオやデータなど,(通話)ルームで共有されるものを表します.今回は,このTracksにメッセージを載せて共有します.

ここまで実装すれば完成です.
複数のタブでlocalhost:5000へアクセスし,join call -> wanna finish this callを押すことで「そろそろ終わりたいなぁと○人が思っています」と表示されるはずです.

スクリーンショット 2021-11-21 22.00.13.jpg

尚,排他制御は行っていないので,複数人が同時にボタンを押すと数がバグる可能性はあります.

最後に

Twilioを用いることで非常に簡単にビデオ通話機能とデータ共有が実装できました.参考リンクにあるように,emoji機能をつけることもできますし,色々応用が効きそうですね.

参考

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0