WebRTCのサンプルコード(クライアント)などを試したいとき、シグナリングサーバーを用意する必要があり少々面倒です。
そこで、シグナリングサーバーの代わりをやってくれる拡張機能を作ってみました。
Chromeでかつタブ間での通信というかなり限られた環境用となりますが、シグナリングサーバーを用意する手間が省けます。
(ルーム機能などは一切ありません。)
シグナリングサーバーシミュレーター
使用方法
以下のコードを、コードに追加します。
var SignalingChannelSim = function () {
var btnSender = document.createElement('input');
btnSender.type = 'button';
btnSender.style.display = 'none';
btnSender.id = 'btnRTCSender';
btnReceiver = document.createElement('input');
btnReceiver.type = 'button';
btnReceiver.style.display = 'none';
btnReceiver.id = 'btnRTCReceiver';
btnReceiver.onclick = (function () {
var evt = { data: btnReceiver.value };
this.onmessage && this.onmessage(evt);
}).bind(this);
document.body.appendChild(btnSender);
document.body.appendChild(btnReceiver);
this.send = function (message) {
btnSender.value = message;
btnSender.click();
}
};
コードを見るとわかるとおり、ボタンを使って拡張機能を通して他のタブにメッセージのやり取りを行うというものです。
使用例
<!DOCTYPE html>
<html>
<head>
<title>シグナリングサーバーシミュレーター使用例</title>
<meta charset="utf-8" />
</head>
<body>
<video id="selfView" autoplay></video>
<video id="remoteView" autoplay></video>
<input type="button" onclick="start()" value="接続" />
<script>
var SignalingChannelSim = function () {
var btnSender = document.createElement('input');
btnSender.type = 'button';
btnSender.style.display = 'none';
btnSender.id = 'btnRTCSender';
btnReceiver = document.createElement('input');
btnReceiver.type = 'button';
btnReceiver.style.display = 'none';
btnReceiver.id = 'btnRTCReceiver';
btnReceiver.onclick = (function () {
var evt = { data: btnReceiver.value };
this.onmessage && this.onmessage(evt);
}).bind(this);
document.body.appendChild(btnSender);
document.body.appendChild(btnReceiver);
this.send = function (message) {
btnSender.value = message;
btnSender.click();
}
};
</script>
<script>
// WebRTCサンプルコード
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
window.RTCPeerConnection = window.mozRTCPeerConnection || window.webkitRTCPeerConnection;
var signalingChannel = new SignalingChannelSim();
var configuration = { "iceServers": [{ "url": "stun:stun.example.org" }] };
var pc;
function start() {
pc = new RTCPeerConnection(configuration);
pc.onicecandidate = function (evt) {
evt.candidate && signalingChannel.send(JSON.stringify({ "candidate": evt.candidate }));
};
pc.onnegotiationneeded = function () {
pc.createOffer(localDescCreated, logError);
}
pc.onaddstream = function (evt) {
remoteView.src = URL.createObjectURL(evt.stream);
};
navigator.getUserMedia({ "audio": false, "video": true }, function (stream) {
selfView.src = URL.createObjectURL(stream);
pc.addStream(stream);
}, logError);
}
function localDescCreated(desc) {
pc.setLocalDescription(desc, function () {
signalingChannel.send(JSON.stringify({ "sdp": pc.localDescription }));
}, logError);
}
signalingChannel.onmessage = function (evt) {
!pc && start();
var message = JSON.parse(evt.data);
message.sdp && pc.setRemoteDescription(new RTCSessionDescription(message.sdp), function () {
(pc.remoteDescription.type == "offer") && pc.createAnswer(localDescCreated, logError);
}, logError);
message.candidate && pc.addIceCandidate(new RTCIceCandidate(message.candidate), function () { }, logError);
};
function logError(error) {
console.log(error);
}
</script>
</body>
</html>