今回はskyWayというビデオ通話アプリ・ml5.jsという画像解析ライブラリ・canvasを使ってビデオアプリで遊んでみました。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ml5jsTest</title>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/p5.min.js"></script>
<script src="https://unpkg.com/ml5@0.4.3/dist/ml5.min.js"></script>
<script src="https://cdn.webrtc.ecl.ntt.com/skyway-latest.js"></script>
<script src="main.js"></script>
</body>
</html>
let capture;
let theirVideo;
let img;
let poses = [];
let theirPoses = [];
function preload() {
img = loadImage("./bird1.png"); //画像をロード
}
function setup() {
createCanvas(640, 240); //canvas作成
//自分用カメラ設定と姿勢検出
capture = createCapture({ video: { width: 640, height: 480 }, audio: false });
capture.hide(); //キャンバスで描くので非表示
ml5.poseNet(capture).on("pose", (results) => {
poses = results;
});
// skywayのインスタンスを作成
let peer = new Peer({
key: "", //skywayのAPI Key
});
// skywayでドメインを許可していれば実行される
peer.on("open", () => {
console.log("open! id=" + peer.id);
createP("Your id: " + peer.id);
});
// id入力タグの生成
let idInput = createInput("");
// 送信ボタンの生成
createButton("Call").mousePressed(() => {
// ボタンが押されたら
const callId = idInput.value(); //id入力欄の値を取得
console.log("call! id=" + peer.id);
const call = peer.call(callId, capture.elt.srcObject); //id先を呼び出し
addVideo(call);
});
// // 相手から呼び出された実行される
peer.on("call", (call) => {
console.log("be called!");
call.answer(capture.elt.srcObject); //呼び出し相手に対して返す
addVideo(call);
});
// 相手の映像を追加処理
function addVideo(call) {
call.on("stream", (theirStream) => {
console.log("stream!");
//相手のビデオを作成
theirVideo = createVideo();
theirVideo.elt.autoplay = true;
theirVideo.elt.srcObject = theirStream;
theirVideo.hide(); //キャンバスで描くので非表示
//相手のビデオから姿勢検出
ml5.poseNet(theirVideo).on("pose", (results) => {
theirPoses = results;
});
});
}
}
function draw() {
//それぞれもしビデオの準備ができていたらキャンバスに半分の大きさで描く
if (capture) image(capture, 0, 0, 320, 240);
if (theirVideo) image(theirVideo, 320, 0, 320, 240);
// 自分の鼻の位置を取得
let myNosePos = getPartsPosition(poses, "nose");
let myFace_x = myNosePos.x - 260;
let myFace_y = myNosePos.y - 290;
//相手の鼻の位置を取得
let thNosePos = getPartsPosition(theirPoses, "nose");
let thFace_x = thNosePos.x + 60;
let thFace_y = thNosePos.y - 290;
//鳥の画像を表示する///
image(img, myFace_x, myFace_y);
image(img, thFace_x, thFace_y);
console.log(myFace_x);
console.log(thFace_x);
}
// 指定された名前の部位の座標を取得できる
function getPartsPosition(poses, partsName) {
if (poses[0])
for (let i = 0; i < poses[0].pose.keypoints.length; i++)
if (poses[0].pose.keypoints[i].part == partsName)
return poses[0].pose.keypoints[i].position;
return { x: 0, y: 0 };
}
鼻の位置を基に鳥の顔画像を配置して、鳥人っぽくなるようにしました。
https://quizzical-gates-7c4a37.netlify.app
相手の動画が表示されても2つ目の鳥画像がのるようにして、知人に頼んでいざテストしたところ・・・
相手にはiPhoneから入ってもらったのですが、相手の動画が表示されない・・・!
自分のiPhone、iPadで開いてもカメラ起動せず・・・
モバイルのブラウザではカメラ起動しないのだろうか・・・
自分のカメラ付きPCだと動きました。
鳥人になれるWeb会議に挑戦してみたけど、相手のカメラ起動しなかった・・・。自分が許す限りは時間使い放題の自分一人のテストより、相手が存在するテストではもっとちゃんと準備しないといけないと学んだ pic.twitter.com/yzI3yX12ti
— hiromae (@hiromae_studyng) June 11, 2020
アプリ設定ではGoogleChromeからカメラへのアクセス許可しているのですが。
カメラが起動しないのでテストは終了・・・。
もっと自分単独でテストした上で相手とのテストに臨むべきでした。
自分以外の誰かを巻き込む際は相手の時間ももらうことになるので、コケないよう入念に準備すべきだったと学びました。そして笑い飯の鳥人ネタは面白かったです。