#概要
ここ数か月でオンラインセミナーやオンラインイベントが急激に増えていますね。その中であるあるなのが、画面真っ黒状態。何かというと、参加者がカメラオフにしていて参加者一覧画面が真っ黒に染まる事です。
これは主催や運営側として、参加者の感情を読み取りづらかったりつ辛い部分があるとのことです。そこで、少しでも華やかになりつつプライバシー保護を考慮したビデオチャットのプロトタイプを作ってみました!
どうしたかというと、相手の画像を「画風変換にかける」です。以下が実際のようです。
新時代のビデオチャットは画面を真っ暗にするのではなく、画風変換なんてのはいかがでしょう?
— まえぷー@出窓菜園ティスト (@kmaepu) June 11, 2020
これならある程度プライバシー保護されつつ、感情や身振り手振りも伝わりやすいと考え作ってみました!
※サーバーを消したので、今はつながりません。#protoout pic.twitter.com/PhJNEhOtUX
#技術解説
##開発環境
- ホストマシン: Windows10 x64
- エディタ:Visual Studio Code
- ブラウザ:Google Chrome
- ライブラリ;p5.js 、 ml5.js
ビデオチャットにはWebRTCを手軽に利用できるSkywayで行っています。
##画風変換について
画風変換はml5.jsの「styleTransfer」のサンプルを利用しています。このライブラリは、特定の画風を機械学習させておき、入力された画像に画風を加えて出力します。
こちらが公式のサンプルコードです。
##ソースコード
各所にコメントを載せていますので、styleTrasnferってこう使うんだなと思っていただければ幸いです。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>kmaepu-waiwai chat</title>
</head>
<body>
<div id="video-area"></div>
<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>
Skywayを利用するには認証が必要なので、アクセスキーを入手したら「skyway KEY」を差し替える必要があります。
let capture;
let theirVideo;
let style;
let mystyle;
let resultImg;
let myresultImg;
let img;
function setup() {
createCanvas(640, 200); //canvas作成
capture = createCapture({
video: { width: 640, height: 480 },
audio: false,
});
capture.hide(); //キャンバスで描くので非表示
capture.size(160, 120); //重いので小さく
resultImg = createImg("");
resultImg.hide(); //キャンバスで描くので非表示
myresultImg = createImg("");
myresultImg.hide(); //キャンバスで描くので非表示
//自分のにかけるときはここ
mystyle = ml5.styleTransfer("models/wave", capture, function () {
mystartTransfer();
});
// skywayのインスタンスを作成
let peer = new Peer({
key: "skyway 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.size(160, 120); //重いので小さく
theirVideo.hide(); //キャンバスで描くので非表示
//相手側のビデオ映像に対してstyle変換
style = ml5.styleTransfer("models/udnie", theirVideo, function () {
print("loaded");
startTransfer();
});
});
}
}
function draw() {
image(myresultImg, 0, 0);
image(resultImg, 160, 0);
}
function startTransfer() {
style.transfer(function (err, res) {
resultImg.attribute("src", res.src);
startTransfer();
});
}
function mystartTransfer() {
mystyle.transfer(function (err, res) {
myresultImg.attribute("src", res.src);
mystartTransfer();
});
}
#おわりに
ここまで作るのは、javascript初心者の私には酷でした。そんな私をサポートして下さったProtoout関連の方、誠にありがとうございました。
余談ですが、スマートフォンのようにカメラが2つある場合は動きませんでした。背面カメラとインカメラがあるためです。
この記事参考にできそうですが、自分には力及ばずという結果でした。気になる方は試してみてはいかがでしょうか。
#参考
p5.js
ml5.js
6_1:イメージ p5.js JavaScript
skyway javascript SDK
koji/fast_style_transfer_in_p5ML
6_1:画風変換(Style Transfer) ml5.js JavaScript
styleTransfer
guthub styleTransfer