使っている環境について
概要
現在(2020/10/27)使っている環境です。もしこのブログを参考にしてる人がいたらここの環境を参考にしてください。たまに更新し忘れると思います。どこまで書けばいいかわかんない。
相棒
ノートPC
MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports)
CPU : 2.3Ghz クアッドコアIntel Corei7
メモリ : 32GB 3733MHz LPDDR4X
GPU : Intel Iris Plus Graphics 1536MB
OS : macOS Catalina ver.10.15.7
大体いつもこの子で作業をしてます。
macを使うのはこの子が初めてだったりします。
この前に使っていたノートPCがsurfaceだったので大裏切りをかましました。
開発環境
python 3.7
conda 4.9.0
pip 20.0.2
...こんなところ...?
[React] WebRTC x React でP2Pビデオ電話アプリを作ってみる 番外編#3 ~MUIで見た目を整える~
概要
WebRTCとReactでビデオ電話アプリを作る番外編第3回です。今回はReactのUIライブラリであるMaterial-UIを用いて外見を整えていきます。
MUIのインストール
frontendディレクトリでnpm install @mui/material @emotion/react @emotion/styled
でOKです。とても簡単
コードの変更
今回のコードはGitHubのfrontend/src/VideoConnect5.js
に記載してます。
大きく変えたのは以下の部分です。
VideoConnect5.js
import React from 'react'; // import './Video.css'; import socketClient from 'socket.io-client'; import { Box, Button, Grid, Card, CardMedia, CardActions, Typography, CardContent } from '@mui/material'; // 追加 // 省略 // 以下大幅変更 return ( <div className="VideoView"> <Grid container spacing={2} alignItems="flex-start" justifyContent="center"> <Grid item xs> <div> <Card sx={{ width: 400, height: 280 }}> <CardMedia sx={{ height: 225 }} component="video" playsInline autoPlay ref={localVideoRef} /> <CardActions> <Button variant="contained" onClick={calling} disabled={!canCalling}>CALL</Button> <Button variant="contained" onClick={allowJoin} disabled={!isKnocking}>ALLOW</Button> </CardActions> </Card> </div> </Grid> <Grid item xs> <Card sx={{ width: 400, height: 225 }}> <CardMedia sx={{ height: 225 }} component="video" playsInline autoPlay ref={remoteVideoRef} /> </Card> </Grid> </Grid> </div> )
まとめ
- MUIを使うと簡単に見た目を整えられる!すごい!
[React] WebRTC x React でP2Pビデオ電話アプリを作ってみる 番外編#2 ~別ブラウザにも対応させる~
概要
WebRTCとReactを使ったビデオ電話アプリ制作の番外編第2回です。今回はブラウザの対応範囲を増やしたいと思います。
これまでのコードは基本的にChrome向けのコードだったのでMacユーザーの方はもしかしたら途中で意味不明エラー(これは関数じゃないよ的な)が出ていたと思います。(かくゆう私もMacユーザーですが)
それをバシッと今回解決します。
そもそもなんでそんなことが起こるのか
ここでWebRTCの関数などについて調べるとわかるのですが、どうやらブラウザごとに対応バージョンが違うらしく、Chromeが一番最新まで対応しているということみたいです。(WebRTCもChromeもGoogle製みたいなところですからね)
解決方法
Google側もこの状況をほっといているわけではなく、adapter.js
というコードを公開しています。このコードを読み込んであげるだけでブラウザを気にせず最新バージョンで書いてOKって感じみたいです。
なので、今回はこのコードを読み込んで解決していきます。
今回のコードはGitHubにVideoConnect4.js
としてアップしています。
VideoConnect4.js
// 省略 React.useEffect(() => { navigator.mediaDevices.getUserMedia(constraints) .then((stream) => { localStream = stream; console.log(localStream); localVideoRef.current.srcObject = stream; setCanCalling(true); }) .catch((error) => { console.log("ERROR", error); }); const adapterScript = document.createElement('script'); // 追加 adapterScript.src = "https://webrtc.github.io/adapter/adapter-latest.js"; // 追加 adapterScript.async = true; // 追加 document.body.appendChild(adapterScript); // 追加 return () => { // 追加 document.body.removeChild(adapterScript); // 追加 }; // 追加 }, []); // 省略
fontend/src/index.js
import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import reportWebVitals from './reportWebVitals'; import VideoConnect4 from './VideoConnect4'; // 変更 ReactDOM.render( <React.StrictMode> <VideoConnect4 /> // 変更 </React.StrictMode>, document.getElementById('root') ); // If you want to start measuring performance in your app, pass a function // to log results (for example: reportWebVitals(console.log)) // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals reportWebVitals();
これでOKです。どのブラウザからもうまく動くようになったと思います。
まとめ
- adapter.jsのおかげでブラウザを気にせず実装ができる。素晴らしい。
[React] WebRTC x React でP2Pビデオ電話アプリを作ってみる 番外編#1 ~Herokuにデプロイ~
概要
WebRTCとReactを使ったビデオ通話アプリケーションの番外編第1回です。これまでとりあえずうまく通話ができた(localhost内)ので今度はインターネットに公開してみます。
無料で使用できるHerokuというサービスで公開します。
Heroku
Herokuは基本料金無料で使用できるクラウドアプリケーションサービスです。
会員登録
ここから会員登録をします。必要事項を入力してください。
デプロイ
ダッシュボード右上のNewボタンからCreate New Appを選択します。
このページでアプリの名前と使用するサーバ(アメリカorヨーロッパ)を指定します。
その後のページでは、DeployタグのDeployment method欄でデプロイの方法を選択できるのですが、おすすめはGitHub連携です。(それしか使ったことがないなんて言えない)
この方法だと連携したGitHubレポジトリが更新されるたびにHeroku側も更新してくれるため楽です。
デプロイするコード
本編で使用したコードをそのままデプロイしても全然動きません。なので少し手を加えていきます。
と言っても手を加えるのはごく一部です。
backend/index.js
// 省略 const io = require('socket.io')(server, { cors: { //origin: 'http://localhost:3000',から変更 origin: 'http://<appの名前>.herokuapp.com', methods: ['GET', 'POST'], } }); app.use(express.static(path.join(__dirname, '../frontend/build'))); // 追加 // 省略
VideoConnect2.js
// 省略 // "http://localhost:3001"から変更 const SERVER = "https://<appの名前>.herokuapp.com"; // 省略
/package.json
// 省略 "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "node backend/index-heroku.js", "heroku-postbuild": "npm install && cd frontend && npm install && npm run build" }, // 省略
fontend/index.js
import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import reportWebVitals from './reportWebVitals'; import VideoConnect3 from './VideoConnect3'; // 変更 ReactDOM.render( <React.StrictMode> <VideoConnect3 /> // 変更 </React.StrictMode>, document.getElementById('root') ); // If you want to start measuring performance in your app, pass a function // to log results (for example: reportWebVitals(console.log)) // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals reportWebVitals();
上記の部分を変更してください。<appの名前>はHerokuでのApp作成時の自分で決めたAppの名前を入力してください。変更後のものをGithubにbackend/index-heroku.js
、frontend/src/VideoConnect3.js
として保存してます。
最後にbackend内でnpm run build
を実行してください。実行後にbuildフォルダができれば完成です。
動作確認
ダッシュボード右上のOpen appをクリックすると自分のAppが開きます。同じURLでもう一つタブを立ち上げ本編第5回と同様に使用してみましょう。うまく動くはずです。
うまく動かない時は、Herokuのダッシュボード右上MoreからView logsにエラーが出ていると思います。
まとめ
- Herokuは偉大なサービスです。無料で利用できてこんな簡単にデプロイできるのすごい
[React] WebRTC x React でP2Pビデオ電話アプリを作ってみる #5 ~データ通信・交換編~
概要
WebRTCとReactを使用したビデオ電話アプリ製作の第5回です。今回は、別のブラウザ間でのアクセスを可能にします。 今回もだいぶ重いです...
追加の準備
今回はサーバーにexpress、WebSocketを使用するためにsocket.ioを使用します。そのために追加で準備です。 まずは、react-webrtc(トップディレクトリ)内で
npm install express socket.io
を実行します。(express、socket.ioのインストール)
次にfrontend内で
npm install socket.io-client
を実行します。(socket.ioのクライアント側をインストール)
最後に、react-webrtc(トップディレクトリ)内のpackage.jsonの"script"に
"script": { "start": "node backend/index.js" }
を追記します。
これで準備は完了です。
今回のコード
今回のコードも長くなってしまったので、ここに載せてあります。
変更(追加)したのはfrontend/src/VideoConnect2.js
、backend/index.js
です。src/index.js
も変更しているのでここに載せておきます。
import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import reportWebVitals from './reportWebVitals'; import VideoConnect from './VideoConnect'; import VideoConnect2 from './VideoConnect2'; // 変更点 ReactDOM.render( <React.StrictMode> <VideoConnect2 /> // 変更点 </React.StrictMode>, document.getElementById('root') ); // If you want to start measuring performance in your app, pass a function // to log results (for example: reportWebVitals(console.log)) // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals reportWebVitals();
コードの説明
使い方
- 2つのターミナル①、②を準備します。
- ①でトップディレクトリで
npm start
- ②でfrontend内で
npm start
- ブラウザで
http://localhost:3000
にアクセス - Callボタンを押す
- 他のタブで
http://localhost:3000
にアクセス - Callボタンを押す
- 1つ目のタブでAllowボタンを押す
- つながる!
大体の流れ
- ページを読み込む時にカメラの映像をローカルビデオとしてセット
- Callボタンを押すと、サーバとの通信を始める
- サーバに部屋がなければ作成して自分がホストになる。
- サーバに部屋があれば参加する。
- SDPを交換してリモートピアのビデオを受けとる。
- リモートビデオを表示する。
socket.on() socket.emit()
socket.ioを用いてwebsocketで通信する時に使用する関数です。
socket.emitで関数を呼び、その呼び出される関数をsocket.onで記述します。
まとめ
- socket.ioを用いてサーバと通信することで別のタグなどから同時にアクセス可能
[React] WebRTC x React でP2Pビデオ電話アプリを作ってみる #4 ~データ交換編~
概要
WebRTC と React を使ってビデオ電話アプリを作成する第4回です。今回は前回取得したデータを交換します。 今回は割と重かったりします。
今回のコード
今回のコードは長くなってしまったのでここに載せてあります。
変更したのはsrc/VideoConnect.js
とsrc/Video.css
です。src/index.js
も変更しているのでここに載せておきます。
src/index.js
import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import reportWebVitals from './reportWebVitals'; import VideoConnect from './VideoConnect'; // 変更点 ReactDOM.render( <React.StrictMode> <VideoConnect /> // 変更点 </React.StrictMode>, document.getElementById('root') ); // If you want to start measuring performance in your app, pass a function // to log results (for example: reportWebVitals(console.log)) // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals reportWebVitals();
コードの説明
大体の流れ
今回のコードは次のような流れで動いています。
[ページを開いた瞬間]
- localVideoRef, localVideoStreamに映像がセットする。
[CALLボタン押下後]
localPeerConnectionおよびremotePeerConnectionを作成。
それぞれにicecandidate、iceconnectionstatechangeを追加する。(remotePeerConnectionにはaddstreamも)
localPeerConnectionにlocalVideoStreamを設定。
localPeerConnectionからOfferを作成する。
remotePeerConnectionからAnswerを作成する。
という感じです。
RTCIceCandidate
そもそもICEとはなんですか?という話です。
ICE (Interactive Connectivity Establishment) は、ネットワークトポロジー (通常は音声および/またはビデオのチャット) に関係なく、2 つのピアを互いに接続するための WebRTC に (他の技術があまたある中で) 使用されるフレームワークです。 このプロトコルを使用すると、ネットワークアドレストランスレーター (NAT) を使用してそれぞれのローカルネットワーク上の他のデバイスとグローバル IP アドレスを共有していても、2 つのピアが相互に接続を見つけて確立することができます。
ICE - MDN Web Docs 用語集: ウェブ関連用語の定義 | MDN
とのことです。NATを超えてピアを接続するためのフレームワークってことみたいです。
このICEですが、5つの段階に分かれていて
通信できそうな候補を集める
集めた候補を交換する
受け取った候補と自分の候補を合わせる
ペアを用いて接続試行
接続成功した候補ペアからいいものを決定
という手順を踏みます。
ここでの候補がRTCIceCandidateです。
RTCPeerConnection
RTCPeerConnectionはローカルコンピューターとリモートピアをWebRTCで繋ぐためのインターフェースです。
RTCPeerConnection.addIceCandidate
リモートピアをリモートピアのICECandidateを追加するメソッドです。
Peer.addIceCandidate(newIceCandidate) .then(() => { console.log("connection success"); // 成功時の処理 }) .catch(() => { console.log("connection failure"); // 失敗時の処理 });
今回のコードではこのように使っています。
RTCPeerConnection.setLocalDescription / setRemoteDescription
PeerConnectionにローカル/リモートの情報を紐づけるメソッドです。
RTCPeerConnection.createOffer / createAnswer
WebRTCでの接続をするためにSDP offer / answerするための関数です。SDP(Session Description Protocol)とは、接続に必要なパラメータを記述する形式の一つです。
localPeerConnection.createOffer(offerOptions) .then(createdOffer) // 成功時の処理 .catch((error) => { console.log('createOffer Error', error); // 失敗時の処理 })
今回はこのようなコードになっています。
成功時にcreatedOfferが実行されるようになってます。createdOfferの中身は
localPeerConnection.setLocalDescription(description) remotePeerConnection.setRemoteDescription(description) remotePeerConnection.createAnswer() .then(createdAnswer)
というような感じで、ローカルピアとリモートピアそれぞれに各々のDescriptionを設定し、リモートピアがAnswerを作成します。 Answer作成時にcreatedAnswerが実行されます。createdAnswerの中身は
remotePeerConnection.setLocalDescription(description) localPeerConnection.setRemoteDescription(description)
というような感じで、それぞれのピアにもう片方のピアのDescriptionを設定します。
まとめ
- 同じブラウザ内でのデータ交換をした
- ICEすごい
参考文献
www.slideshare.net
次のページ→ [React] WebRTC x React でP2Pビデオ電話アプリを作ってみる #5 ~データ通信・交換編~ - やってみたらなんとかなる
[React] WebRTC x React でP2Pビデオ電話アプリを作ってみる #3 ~映像・音声取得編~
概要
WebRTCとReactを使った簡単なビデオ通話アプリ作成の第3回です。 今回は、映像の取得まで行います。
今回行うこと
- getUserMedia()を使った映像と音声の取得
今回使用するコード
次の①、②のコードを書いた後にnpm start
でカメラに映った自分が表示されると思います。
①src/VideoView.js (新規作成)
import React from 'react'; export default function VideoView() { const videoRef = React.useRef(null); const constraints = { video: true, audio: false, } React.useEffect(() => { navigator.mediaDevices.getUserMedia(constraints) .then((stream) => { videoRef.current.srcObject = stream; }) .catch((error) => { console.log(error); }) }, []); return ( <div className="VideoView"> <video playsInline autoPlay ref={videoRef} /> </div> ) }
②src/index.js (編集)
import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import reportWebVitals from './reportWebVitals'; import VideoView from './VideoView'; // 変更点 ReactDOM.render( <React.StrictMode> <VideoView /> // 変更点 </React.StrictMode>, document.getElementById('root') ); // If you want to start measuring performance in your app, pass a function // to log results (for example: reportWebVitals(console.log)) // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals reportWebVitals();
コードの中身
React.useRef
useRefはReact内でタグのパラメータを操作する時に使用します。
タグの中に<video src="./hogehoge.mp4" />
のように書き込めればそれでいいのですが、
今回使用するパラメータsrcObjectはそのように書き込めません。
そんな時に便利なのがuseRefです。
タグに<video ref={videoRef}>
のようにrefパラメータを記述し、その変数videoRefを受け取ります。
そこからvideoRef.current.srcObject = stream
のようにパラメータに値を代入するとという使い方です。
React.useEffect
useEffectは「この変数の値が変更されたらこの処理を実行したい」という時に使います。
React.useEffect(() => { // 実行したい処理 }, [. 変更を検知したい変数達. ]);
こんな感じで使用します。変更を検知したい変数はArrayとして複数指定することが可能です。
今回のコードのように空のArrayが指定された場合は、最初に読み込まれた時のみ処理が実行されます。
navigator.mediaDevices.getUserMedia
今回の主役です。ユーザーのビデオもしくはオーディオを取得します。
navigator.mediaDevices.getUserMedia(取得制約) .then((stream) => { // 取得成功時の処理 }) .catch((error) => { // 取得失敗時の処理 })
ビデオ等を取得する時にはブラウザ側から「ビデオとか取得するけどOK?」という確認があります。
この確認で拒否されてしまった場合やそもそもビデオがない時などに「取得失敗時の処理」行われます。
取得制約は何を取得するのかをjson形式で指定します。
{ video: true, audio: false }
のように指定すると、「ビデオは取得するけど、オーディオは取得しません」という意味になります。
今回の場合、audio: true
にするとハウリングが起こるので注意してください。
まとめ
今回はgetUserMediaを用いてビデオ・オーディオの取得を行いました。次回は取得したデータを相手に渡します。
次のページ→ [React] WebRTC x React でP2Pビデオ電話アプリを作ってみる #4 ~データ交換編~ - やってみたらなんとかなる
[React] WebRTC x React でP2Pビデオ電話アプリを作ってみる #2 ~準備編~
# 概要 第2回は準備編です。環境構築などを進めます。
今回やること
- node.jsのインストール
- 作業ディレクトリの作成
- Reactのインストール
node.jsのインストール
Reactを使用するのにはnode.jsが必要です。このインストールはOSごとにやり方が違うので公式とかここ(Windows)とかここ(Mac)とかを参考にしてみてください。参考までに僕がインストールした手順を残しておきます。(僕のPCのOSはmacOS Montereyです。)
①nodebrewのインストール
brew install nodebrew
②node.js(最新版)のインストール
nodebrew install-binary latest
これでOKのはずです。
作業ディレクトリの作成
適当な場所に作業ディレクトリを作ります。 僕は、Documentsディレクトリ内にreact-webrtcというディレクトリを作成しました。
npm init -y
でpackage.jsonを作成しておきましょう。
Reactのインストール
Reactをインストールします。(Reactをインストールって言い方あっているのかとても不安です。教えてください詳しい方...)
npx create-react-app frontend
この後、
cd frontend
でfrontendディレクトリに移動した後
npm start
その後、ブラウザでhttp://localhost:3000にアクセスして のような画面が表示されればOKです。
まとめ
ひとまずこれで準備完了です。次回から製作に入る予定です。
次のページ→ [React] WebRTC x React でP2Pビデオ電話アプリを作ってみる #3 ~映像・音声取得編~ - やってみたらなんとかなる