Last active
August 29, 2015 14:16
-
-
Save mganeko/4d0f84c383722d1fb963 to your computer and use it in GitHub Desktop.
WebRTC 1to1 with "Simple Message Server" for WebSocket
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | |
<title>WebRTC 1to1</title> | |
<!--- this is demo for http://www.slideshare.net/mganeko/chromebook-webrtc --> | |
<!-- please install simple message server from here: https://chrome.google.com/webstore/detail/simple-message-server/bihajhgkmpfnmbmdnobjcdhagncbkmmp --> | |
</head> | |
<body> | |
<button type="button" onclick="startVideo();">Start video</button> | |
<button type="button" onclick="stopVideo();">Stop video</button> | |
| |
<button type="button" onclick="connect();">Connect</button> | |
<button type="button" onclick="hangUp();">Hang Up</button> | |
| |
<button type="button" onclick="disconnect_ws();">Disconnect WS</button> | |
<br /> | |
<div style="position: relative;"> | |
<video id="local-video" autoplay style="position: absolute; top: 0px; width: 160px; height: 120px; border: 1px solid black;"></video> | |
<video id="remote-video" autoplay style="position: absolute; top: 0px; left: 165px; width: 800px; height: 600px; border: 1px solid black;"></video> | |
</div> | |
<script> | |
// create socket | |
var url = 'ws://localhost:3001/'; | |
var ws = new WebSocket(url); | |
var socketId = null; | |
var localVideo = document.getElementById('local-video'); | |
var remoteVideo = document.getElementById('remote-video'); | |
var localStream = null; | |
var peerConn = null; | |
var peerStarted = false; | |
var channelReady = false; | |
var mediaConstraints = {'mandatory': { | |
'OfferToReceiveAudio':true, | |
'OfferToReceiveVideo':true }}; | |
function disconnect_ws() { | |
if (ws) { | |
ws.close(); | |
ws = null; | |
} | |
} | |
// --------------------- socket event --------------- | |
ws.onopen = onChannelOpened; | |
ws.onmessage = onMessage; | |
ws.onclose = onClose; | |
ws.onerror = onError; | |
function onChannelOpened(evt) { | |
console.log('Channel opened.'); | |
console.log(evt); | |
channelReady = true; | |
var msg; | |
//msg = 'hi'; | |
//ws.send(msg); | |
msg = JSON.stringify({type: "open", text: "hello"}); | |
ws.send(msg); | |
msg = JSON.stringify({type: "open", text: "あいうえおす"}); | |
ws.send(msg); | |
msg = "_system:getsocketid"; | |
ws.send(msg); | |
} | |
// socket: accept connection request | |
function onMessage(raw_evt) { | |
console.log("onMessage() evt=", raw_evt); | |
var msg = raw_evt.data; | |
var evt = JSON.parse(msg); | |
if (evt.type === '_system') { | |
if (evt.system === 'socketid') { | |
socketId = evt.socketid; | |
console.log('_system: getsocketid = ', socketId); | |
var msg = '_system:sendto=' + socketId + ', ' + JSON.stringify({type: "direct", text: "only for you"}); | |
ws.send(msg); | |
} | |
} | |
else if (evt.type === 'offer') { | |
console.log("Received offer...") | |
if (!peerStarted) { | |
sendAnswer(evt); | |
peerStarted = true; | |
} | |
} | |
else if (evt.type === 'answer' && peerStarted) { | |
console.log('Received answer...'); | |
console.log('Setting remote session description...' ); | |
peerConn.setRemoteDescription(new RTCSessionDescription(evt)); | |
} | |
else if (evt.type === 'candidate' && peerStarted) { | |
console.log('Received ICE candidate...'); | |
var candidate = new RTCIceCandidate({sdpMLineIndex:evt.sdpMLineIndex, sdpMid:evt.sdpMid, candidate:evt.candidate}); | |
console.log(candidate); | |
peerConn.addIceCandidate(candidate); | |
} | |
else if (evt.type === 'bye' && peerStarted) { | |
console.log("Received bye"); | |
stop(); | |
} | |
} | |
function onClose(raw_evt) { | |
console.log("onClose() evt=", raw_evt); | |
channelReady = false; | |
} | |
function onError(raw_evt) { | |
console.log("onError() evt=", raw_evt); | |
} | |
// ---------------------- video handling ----------------------- | |
// get the local video up | |
function startVideo() { | |
navigator.webkitGetUserMedia({video: true, audio: true}, successCallback, errorCallback); | |
function successCallback(stream) { | |
localStream = stream; | |
localVideo.src = window.URL.createObjectURL(stream); | |
localVideo.play(); | |
} | |
function errorCallback(error) { | |
console.error('An error occurred: [CODE ' + error.code + ']'); | |
return; | |
} | |
} | |
// stop local video | |
function stopVideo() { | |
localVideo.src = ""; | |
localStream.stop(); | |
} | |
// ---------------------- connection handling ----------------------- | |
function prepareNewConnection() { | |
var pc_config = {"iceServers":[]}; | |
var peer = null; | |
try { | |
peer = new webkitRTCPeerConnection(pc_config); | |
} catch (e) { | |
console.log("Failed to create PeerConnection, exception: " + e.message); | |
} | |
// send any ice candidates to the other peer | |
peer.onicecandidate = function (evt) { | |
if (evt.candidate) { | |
console.log(evt.candidate); | |
//socket.json.send({type: "candidate", | |
// sdpMLineIndex: evt.candidate.sdpMLineIndex, | |
// sdpMid: evt.candidate.sdpMid, | |
// candidate: evt.candidate.candidate}); | |
var candidate = {type: "candidate", | |
sdpMLineIndex: evt.candidate.sdpMLineIndex, | |
sdpMid: evt.candidate.sdpMid, | |
candidate: evt.candidate.candidate | |
}; | |
var msg = JSON.stringify(candidate); | |
ws.send(msg); | |
} else { | |
console.log("End of candidates. ------------------- phase=" + evt.eventPhase); | |
} | |
}; | |
console.log('Adding local stream...'); | |
peer.addStream(localStream); | |
peer.addEventListener("addstream", onRemoteStreamAdded, false); | |
peer.addEventListener("removestream", onRemoteStreamRemoved, false) | |
// when remote adds a stream, hand it on to the local video element | |
function onRemoteStreamAdded(event) { | |
console.log("Added remote stream"); | |
remoteVideo.src = window.URL.createObjectURL(event.stream); | |
} | |
// when remote removes a stream, remove it from the local video element | |
function onRemoteStreamRemoved(event) { | |
console.log("Remove remote stream"); | |
remoteVideo.src = ""; | |
} | |
return peer; | |
} | |
function sendOffer() { | |
peerConn = prepareNewConnection(); | |
peerConn.createOffer(function (sessionDescription) { // in case of success | |
peerConn.setLocalDescription(sessionDescription); | |
console.log("Sending: offer SDP"); | |
console.log(sessionDescription); | |
//socket.json.send(sessionDescription); | |
var msg = JSON.stringify(sessionDescription); | |
ws.send(msg); | |
}, function () { // in case of error | |
console.log("Create Offer failed"); | |
}, mediaConstraints); | |
} | |
function sendAnswer(evt) { | |
console.log('sending Answer. Creating remote session description...' ); | |
peerConn = prepareNewConnection(); | |
peerConn.setRemoteDescription(new RTCSessionDescription(evt)); | |
peerConn.createAnswer(function (sessionDescription) { // in case of success | |
peerConn.setLocalDescription(sessionDescription); | |
console.log("Sending: answer SDP"); | |
console.log(sessionDescription); | |
//socket.json.send(sessionDescription); | |
var msg = JSON.stringify(sessionDescription); | |
ws.send(msg); | |
}, function () { // in case of error | |
console.log("Create Answer failed"); | |
}, mediaConstraints); | |
} | |
// ---------------- handling user UI event ----- | |
// start the connection upon user request | |
function connect() { | |
if (!peerStarted && localStream && channelReady) { | |
sendOffer(); | |
peerStarted = true; | |
} else { | |
alert("Local stream not running yet - try again."); | |
} | |
} | |
// stop the connection upon user request | |
function hangUp() { | |
console.log("Hang up."); | |
//socket.json.send({type: "bye"}); | |
var msg = JSON.stringify({type: "bye"}); | |
ws.send(msg); | |
stop(); | |
} | |
function stop() { | |
if (peerConn) { | |
peerConn.close(); | |
peerConn = null; | |
} | |
peerStarted = false; | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment