Last active
August 29, 2015 14:07
-
-
Save mganeko/cc491e1657d414a3a56b to your computer and use it in GitHub Desktop.
WebRTC Signaling by Hand
This file contains hidden or 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> | |
| <title>WebRTC 1 to 1 handshake V3</title> | |
| </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> | |
| <br /> | |
| <div> | |
| <video id="local-video" autoplay style="width: 240px; height: 180px; border: 1px solid black;"></video> | |
| <video id="remote-video" autoplay style="width: 240px; height: 180px; border: 1px solid black;"></video> | |
| </div> | |
| <p> | |
| SDP to send:<br /> | |
| <textarea id="text-for-send-sdp" rows="5" cols="100" disabled="1">SDP to send</textarea> | |
| </p> | |
| <p> | |
| SDP to receive:<br /> | |
| <textarea id="text-for-receive-sdp" rows="5" cols="100"></textarea><br /> | |
| <button type="button" onclick="onSDP();">Receive SDP</button> | |
| </p> | |
| <p> | |
| ICE Candidate to send:<br /> | |
| <textarea id="text-for-send-ice" rows="5" cols="100" disabled="1" onclick="this.focus(); this.select();">ICE Candidate to send</textarea> | |
| </p> | |
| <p> | |
| ICE Candidates to receive:<br /> | |
| <textarea id="text-for-receive-ice" rows="5" cols="100"></textarea><br /> | |
| <button type="button" onclick="onICE();">Receive ICE Candidates</button> | |
| </p> | |
| <script> | |
| var localVideo = document.getElementById('local-video'); | |
| var remoteVideo = document.getElementById('remote-video'); | |
| var localStream = null; | |
| var peerConnection = null; | |
| var peerStarted = false; | |
| var mediaConstraints = {'mandatory': {'OfferToReceiveAudio':true, 'OfferToReceiveVideo':true }}; | |
| // ----------------- handshake -------------- | |
| var textForSendSDP = document.getElementById('text-for-send-sdp'); | |
| var textForSendICE = document.getElementById('text-for-send-ice'); | |
| var textToReceiveSDP = document.getElementById('text-for-receive-sdp'); | |
| var textToReceiveICE = document.getElementById('text-for-receive-ice'); | |
| var iceSeparator = '------ ICE Candidate -------'; | |
| var CR = String.fromCharCode(13); | |
| function onSDP() { | |
| var text = textToReceiveSDP.value; | |
| var evt = JSON.parse(text); | |
| if (peerConnection) { | |
| onAnswer(evt); | |
| textForSendICE.focus(); | |
| textForSendICE.select(); | |
| } | |
| else { | |
| onOffer(evt); | |
| } | |
| textToReceiveSDP.value =""; | |
| } | |
| //--- multi ICE candidate --- | |
| function onICE() { | |
| var text = textToReceiveICE.value; | |
| var arr = text.split(iceSeparator); | |
| for (var i = 1, len = arr.length; i < len; i++) { | |
| var evt = JSON.parse(arr[i]); | |
| onCandidate(evt); | |
| } | |
| textToReceiveICE.value =""; | |
| textForSendICE.focus(); | |
| textForSendICE.select(); | |
| } | |
| function onOffer(evt) { | |
| console.log("Received offer...") | |
| console.log(evt); | |
| setOffer(evt); | |
| sendAnswer(evt); | |
| } | |
| function onAnswer(evt) { | |
| console.log("Received Answer...") | |
| console.log(evt); | |
| setAnswer(evt); | |
| } | |
| function onCandidate(evt) { | |
| var candidate = new RTCIceCandidate({sdpMLineIndex:evt.sdpMLineIndex, sdpMid:evt.sdpMid, candidate:evt.candidate}); | |
| console.log("Received Candidate...") | |
| console.log(candidate); | |
| peerConnection.addIceCandidate(candidate); | |
| } | |
| function sendSDP(sdp) { | |
| var text = JSON.stringify(sdp); | |
| console.log("---sending sdp text ---"); | |
| console.log(text); | |
| textForSendSDP.value = text; | |
| textForSendSDP.focus(); | |
| textForSendSDP.select(); | |
| } | |
| function sendCandidate(candidate) { | |
| var text = JSON.stringify(candidate); | |
| console.log("---sending candidate text ---"); | |
| console.log(text); | |
| textForSendICE.value = (textForSendICE.value + CR + iceSeparator + CR + text + CR); | |
| textForSendICE.scrollTop = textForSendICE.scrollHeight; | |
| } | |
| // ---------------------- video handling ----------------------- | |
| // start local video | |
| function startVideo() { | |
| navigator.webkitGetUserMedia({video: true, audio: false}, | |
| function (stream) { // success | |
| localStream = stream; | |
| localVideo.src = window.webkitURL.createObjectURL(stream); | |
| localVideo.play(); | |
| localVideo.volume = 0; | |
| }, | |
| function (error) { // error | |
| console.error('getUserMedia error occurred'); | |
| console.log(error); | |
| 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); | |
| sendCandidate({type: "candidate", | |
| sdpMLineIndex: evt.candidate.sdpMLineIndex, | |
| sdpMid: evt.candidate.sdpMid, | |
| candidate: evt.candidate.candidate | |
| }); | |
| } else { | |
| console.log("ice event 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.webkitURL.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() { | |
| peerConnection = prepareNewConnection(); | |
| peerConnection.createOffer(function (sessionDescription) { // in case of success | |
| peerConnection.setLocalDescription(sessionDescription); | |
| console.log("Sending: SDP"); | |
| console.log(sessionDescription); | |
| sendSDP(sessionDescription); | |
| }, function () { // in case of error | |
| console.log("Create Offer failed"); | |
| }, mediaConstraints); | |
| } | |
| function setOffer(evt) { | |
| if (peerConnection) { | |
| console.error('peerConnection alreay exist!'); | |
| } | |
| peerConnection = prepareNewConnection(); | |
| peerConnection.setRemoteDescription(new RTCSessionDescription(evt)); | |
| } | |
| function sendAnswer(evt) { | |
| console.log('sending Answer. Creating remote session description...' ); | |
| if (! peerConnection) { | |
| console.error('peerConnection NOT exist!'); | |
| return; | |
| } | |
| peerConnection.createAnswer(function (sessionDescription) { // in case of success | |
| peerConnection.setLocalDescription(sessionDescription); | |
| console.log("Sending: SDP"); | |
| console.log(sessionDescription); | |
| sendSDP(sessionDescription); | |
| }, function () { // in case of error | |
| console.log("Create Answer failed"); | |
| }, mediaConstraints); | |
| } | |
| function setAnswer(evt) { | |
| if (! peerConnection) { | |
| console.error('peerConnection NOT exist!'); | |
| return; | |
| } | |
| peerConnection.setRemoteDescription(new RTCSessionDescription(evt)); | |
| } | |
| // -------- handling user UI event ----- | |
| // start the connection upon user request | |
| function connect() { | |
| //if (!peerStarted && localStream && channelReady) { | |
| if (!peerStarted && localStream) { | |
| sendOffer(); | |
| peerStarted = true; | |
| } else { | |
| alert("Local stream not running yet - try again."); | |
| } | |
| } | |
| // stop the connection upon user request | |
| function hangUp() { | |
| console.log("Hang up."); | |
| stop(); | |
| } | |
| function stop() { | |
| peerConnection.close(); | |
| peerConnection = null; | |
| peerStarted = false; | |
| } | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment