vue + skywayでミュート・カメラオフ機能を実装する
2020/07/06の日報
Hanasot開発の日報、第10日目です。
やったことは
- vue + skywayでミュート・カメラオフ機能を実装する
です。
時間は、
- Hanasot開発 1h26min
- 日報ブログ 1h
です。
運動は
- レバー・プッシュアップ 左右17repsずつ→左右12repsずつ→左右13repsずつ
です。
vue + skywayでミュート・カメラオフ機能を実装する
ちょっと時間かかりましたが割とサクッとできました。読み込み時は下の画像のように
- カメラオン
- マイクオフ
の状態です。
このマイクボタンとカメラボタンをクリックすることによってオンオフが切り替わります。
で、今回追加したソースコードはこちらです。
<template> <div> <div class="c-video"> <video id="my-video" width="400px" autoplay muted playsinline></video> <div class="c-video__mic" @click="isMuted = !isMuted"> <img :src="require(isMuted ? '../assets/mic_off.svg' : '../assets/mic.svg')"> </div> <div class="c-video__camera" @click="isCameraOff = !isCameraOff"> <img :src="require(isCameraOff ? '../assets/camera_off.svg' : '../assets/camera.svg')"> </div> </div> ~~~~中略~~~~ data() { return { localStream: null, roomID: '', peer: {}, participants: [], isMuted: true, isCameraOff: false, } }, watch: { isCameraOff(newValue) { const stream = this.localStream stream.getVideoTracks()[0].enabled = !newValue; this.localStream = stream; }, isMuted(newValue) { const stream = this.localStream stream.getAudioTracks()[0].enabled = !newValue; this.localStream = stream; }, }, mounted() { // カメラ映像取得 navigator.mediaDevices.getUserMedia({video: true, audio: true}) .then( stream => { stream.getAudioTracks()[0].enabled = !this.isMuted; stream.getVideoTracks()[0].enabled = !this.isCameraOff; // 成功時にvideo要素にカメラ映像をセットし、再生 const videoElm = document.getElementById('my-video') videoElm.srcObject = stream; videoElm.play(); // 着信時に相手にカメラ映像を返せるように、グローバル変数に保存しておく this.localStream = stream; ~~~~中略~~~~
順番に解説していきます。
マイク・カメラボタンがクリックされたら画像を切り替える
この部分ですね。
<div class="c-video__mic" @click="isMuted = !isMuted"> <img :src="require(isMuted ? '../assets/mic_off.svg' : '../assets/mic.svg')"> </div>
これはマイクですが、カメラもほぼ一緒です。
重要なのは@click="isMuted = !isMuted"
と:src="require(isMuted ? '../assets/mic_off.svg' : '../assets/mic.svg')"
になります。前者がv-on
、後者はv-bind
と呼ばれる機能です。
クリックなどのイベントを検知するv-on
v-on:click=""
を省略して書くと@click=""
となります。コード量も少なくわかりやすいので基本的にこちらを使うことがほとんどです。今回は@click="isMuted = !isMuted"と記述しています。これは「ボタンがクリックされたときに、dataプロパティで定義している
isMuted = true```を trueならfalse に、 falseならtrue に反転させてください」という意味です。
htmlの属性にjsの処理を書けるv-bind
そしてその下のimgタグのsrc属性には:src="require(isMuted ? '../assets/mic_off.svg' : '../assets/mic.svg')"
とあります。これは「isMutedがtrueならマイクの画像を、falseならマイクに斜線の入った画像を表示してください」という意味ですね。v-bindの時はレンダリングの関係?でrequireでパスを指定しないと適切なパスが出力されないので注意。あ、v-bind:src=""
の省略は:src=""
で、src以外にも:class=""
とかもできます。属性ならなんでもOKです。
これらを使って、ボタンの表示を切り替えてます。ここまではUIの処理です。
isMutedとisCameraOffを監視して、カメラとマイクの使用許可を切り替える
次に本題のボタンの真偽値を監視して、カメラとマイクのオンオフ切り替えを行う処理ですね。watchプロパティを使います。
watch: { isCameraOff(newValue) { const stream = this.localStream stream.getVideoTracks()[0].enabled = !newValue; this.localStream = stream; }, isMuted(newValue) { const stream = this.localStream stream.getAudioTracks()[0].enabled = !newValue; this.localStream = stream; }, },
これなにをしているかというと、「関数名と同名のdataプロパティを監視して、値が切り替わったら関数を実行する」というものです。今回は「isMutedを監視して、真偽値が切り替わったら自分の映像を格納しているlocalStreamを取ってきて、マイクの許可をオンオフする」という処理をしてます。カメラも同じですね。
getAudioTracks()[0].enabled
という部分はデバイス使用の許可を表します。trueならマイクの使用可能、falseならマイクの使用不可です。これはskywayの機能ではなく、ブラウザのデフォルトの機能になります。映像や音声の送信を止めたりするというよりは、カメラやマイクが使えなくなって結果的にミュートになったりカメラオフになったりするというわけですね。
ちなみにmountedで
stream.getAudioTracks()[0].enabled = !this.isMuted; stream.getVideoTracks()[0].enabled = !this.isCameraOff;
このようにenabledを定義しています。これをしなくてもオンオフ切り替えはできるような気がするんですが、初期値が不許可の場合に限り上手く動きませんでした。ですので、dataプロパティの値を画面読み込み時に一応定義しておくのが無難かと思います。
所感
結構進みましたねー。いよいよそれらしくなってきた感じがします!まだまだ先は長いですが、「お題を出す機能」と「発言者を一人に限定する機能」さえ作ればアイスブレイクくらいはすぐ実装できそうです。がんばります!