Compare commits
10 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
a171e044b1 | |
|
|
dec89dac53 | |
|
|
cd7177d2d6 | |
|
|
93d28dd9c0 | |
|
|
f0bcf2615a | |
|
|
bd7ea806ac | |
|
|
dbcb4ba82d | |
|
|
5f67119e4e | |
|
|
147a02d695 | |
|
|
a5967c46f5 |
14
README.md
14
README.md
|
|
@ -1,8 +1,6 @@
|
|||
WebRTC Example
|
||||
==============
|
||||
|
||||
#### shane tully (shanetully.com)
|
||||
|
||||
An 'as simple as it gets' WebRTC example.
|
||||
|
||||
See [https://shanetully.com/2014/09/a-dead-simple-webrtc-example/](https://shanetully.com/2014/09/a-dead-simple-webrtc-example/) for a detailed walkthrough of the code.
|
||||
|
|
@ -18,18 +16,17 @@ $ npm install
|
|||
$ npm start
|
||||
```
|
||||
|
||||
With the server running, open a recent version of Firefox or Chrome and visit `https://localhost:8443`.
|
||||
With the server running, open Firefox/Chrome/Safari and visit `https://localhost:8443`.
|
||||
|
||||
Please note the following:
|
||||
|
||||
* Note the HTTPS! There is no redirect from HTTP to HTTPS.
|
||||
* You\'ll need to accept the invalid TLS certificate as it is self-signed and WebRTC must be run over TLS.
|
||||
* Some browsers or OSs may not allow the webcam to be used by multiple pages at once. You may need to use two different browsers or machines.
|
||||
|
||||
## TLS
|
||||
|
||||
Recent versions of Chrome require secure websockets for WebRTC. Thus, this example utilizes HTTPS. Included is a self-signed certificate that must be accepted in the browser for the example to work.
|
||||
|
||||
## Problems?
|
||||
|
||||
WebRTC is a rapidly evolving beast. Being an example that I don't check often, I rely on users for reports if something breaks. Issues and pull requests are greatly appreciated.
|
||||
This is a short example that I don't check often. As such, I rely on users for reports if something breaks. Issues and pull requests are greatly appreciated.
|
||||
|
||||
## License
|
||||
|
||||
|
|
@ -54,4 +51,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
|
|
|
|||
60
cert.pem
60
cert.pem
|
|
@ -1,32 +1,32 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
KKNHDiqV4JiP4WWFN+pc2lOVaLJwTe4FrbG7AA==
|
||||
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
|
||||
-----END CERTIFICATE-----
|
||||
|
|
|
|||
|
|
@ -6,12 +6,16 @@
|
|||
</head>
|
||||
|
||||
<body>
|
||||
<video id="localVideo" autoplay muted style="width:40%;"></video>
|
||||
<video id="remoteVideo" autoplay style="width:40%;"></video>
|
||||
<video id="localVideo" autoplay playsinline muted style="width:40%;"></video>
|
||||
<video id="remoteVideo" autoplay playsinline style="width:40%;"></video>
|
||||
|
||||
<br />
|
||||
<div style="margin-top: 10px;">
|
||||
Open this page in a second browser window then click below to start the WebRTC connection.
|
||||
</div>
|
||||
|
||||
<input type="button" id="start" onclick="start(true)" value="Start Video"></input>
|
||||
<div style="margin-top: 10px;">
|
||||
<input type="button" id="start" onclick="start(true)" value="Start WebRTC"></input>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
pageReady();
|
||||
|
|
|
|||
|
|
@ -1,48 +1,54 @@
|
|||
var localVideo;
|
||||
var localStream;
|
||||
var remoteVideo;
|
||||
var peerConnection;
|
||||
var uuid;
|
||||
var serverConnection;
|
||||
let localStream;
|
||||
let localVideo;
|
||||
let peerConnection;
|
||||
let remoteVideo;
|
||||
let serverConnection;
|
||||
let uuid;
|
||||
|
||||
var peerConnectionConfig = {
|
||||
const peerConnectionConfig = {
|
||||
'iceServers': [
|
||||
{'urls': 'stun:stun.services.mozilla.com'},
|
||||
{'urls': 'stun:stun.stunprotocol.org:3478'},
|
||||
{'urls': 'stun:stun.l.google.com:19302'},
|
||||
]
|
||||
};
|
||||
|
||||
function pageReady() {
|
||||
async function pageReady() {
|
||||
uuid = createUUID();
|
||||
|
||||
localVideo = document.getElementById('localVideo');
|
||||
remoteVideo = document.getElementById('remoteVideo');
|
||||
|
||||
serverConnection = new WebSocket('wss://' + window.location.hostname + ':8443');
|
||||
serverConnection = new WebSocket(`wss://${window.location.hostname}:8443`);
|
||||
serverConnection.onmessage = gotMessageFromServer;
|
||||
|
||||
var constraints = {
|
||||
const constraints = {
|
||||
video: true,
|
||||
audio: true,
|
||||
};
|
||||
|
||||
if(navigator.mediaDevices.getUserMedia) {
|
||||
navigator.mediaDevices.getUserMedia(constraints).then(getUserMediaSuccess).catch(errorHandler);
|
||||
} else {
|
||||
if(!navigator.mediaDevices.getUserMedia) {
|
||||
alert('Your browser does not support getUserMedia API');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function getUserMediaSuccess(stream) {
|
||||
try {
|
||||
const stream = await navigator.mediaDevices.getUserMedia(constraints);
|
||||
|
||||
localStream = stream;
|
||||
localVideo.srcObject = stream;
|
||||
} catch(error) {
|
||||
errorHandler(error);
|
||||
}
|
||||
}
|
||||
|
||||
function start(isCaller) {
|
||||
peerConnection = new RTCPeerConnection(peerConnectionConfig);
|
||||
peerConnection.onicecandidate = gotIceCandidate;
|
||||
peerConnection.ontrack = gotRemoteStream;
|
||||
peerConnection.addStream(localStream);
|
||||
|
||||
for(const track of localStream.getTracks()) {
|
||||
peerConnection.addTrack(track, localStream);
|
||||
}
|
||||
|
||||
if(isCaller) {
|
||||
peerConnection.createOffer().then(createdDescription).catch(errorHandler);
|
||||
|
|
@ -52,17 +58,17 @@ function start(isCaller) {
|
|||
function gotMessageFromServer(message) {
|
||||
if(!peerConnection) start(false);
|
||||
|
||||
var signal = JSON.parse(message.data);
|
||||
const signal = JSON.parse(message.data);
|
||||
|
||||
// Ignore messages from ourself
|
||||
if(signal.uuid == uuid) return;
|
||||
|
||||
if(signal.sdp) {
|
||||
peerConnection.setRemoteDescription(new RTCSessionDescription(signal.sdp)).then(function() {
|
||||
peerConnection.setRemoteDescription(new RTCSessionDescription(signal.sdp)).then(() => {
|
||||
// Only create answers in response to offers
|
||||
if(signal.sdp.type == 'offer') {
|
||||
if(signal.sdp.type !== 'offer') return;
|
||||
|
||||
peerConnection.createAnswer().then(createdDescription).catch(errorHandler);
|
||||
}
|
||||
}).catch(errorHandler);
|
||||
} else if(signal.ice) {
|
||||
peerConnection.addIceCandidate(new RTCIceCandidate(signal.ice)).catch(errorHandler);
|
||||
|
|
@ -78,7 +84,7 @@ function gotIceCandidate(event) {
|
|||
function createdDescription(description) {
|
||||
console.log('got description');
|
||||
|
||||
peerConnection.setLocalDescription(description).then(function() {
|
||||
peerConnection.setLocalDescription(description).then(() => {
|
||||
serverConnection.send(JSON.stringify({'sdp': peerConnection.localDescription, 'uuid': uuid}));
|
||||
}).catch(errorHandler);
|
||||
}
|
||||
|
|
@ -99,5 +105,5 @@ function createUUID() {
|
|||
return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
|
||||
}
|
||||
|
||||
return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
|
||||
return `${s4() + s4()}-${s4()}-${s4()}-${s4()}-${s4() + s4() + s4()}`;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
|
||||
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 3650 -nodes
|
||||
|
|
|
|||
100
key.pem
100
key.pem
|
|
@ -1,52 +1,52 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
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
|
||||
BfXBs2eSpBE70GwrztgDS2fco6tzQQ==
|
||||
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
|
||||
ZEbffYj4hKrpVVuPFYwKzuLcXP1vTFQ=
|
||||
-----END PRIVATE KEY-----
|
||||
|
|
|
|||
|
|
@ -1,33 +1,44 @@
|
|||
{
|
||||
"name": "WebRTC-Example",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"async-limiter": {
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "WebRTC-Example",
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
|
||||
"integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
|
||||
"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
|
||||
},
|
||||
"ultron": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz",
|
||||
"integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og=="
|
||||
},
|
||||
"ws": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz",
|
||||
"integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==",
|
||||
"requires": {
|
||||
"async-limiter": "1.0.0",
|
||||
"safe-buffer": "5.1.1",
|
||||
"ultron": "1.1.1"
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ws": "^8.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.13.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
|
||||
"integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": ">=5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"ws": {
|
||||
"version": "8.13.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
|
||||
"integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==",
|
||||
"requires": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@
|
|||
"bugs": {
|
||||
"url": "https://github.com/shanet/WebRTC-Example/issues"
|
||||
},
|
||||
"homepage": "https://github.com/shanet/WebRTC-Example#readme",
|
||||
"homepage": "https://github.com/shanet/WebRTC-Example",
|
||||
"dependencies": {
|
||||
"ws": "^3.3.2"
|
||||
"ws": "^8.13.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,19 +5,24 @@ const https = require('https');
|
|||
const WebSocket = require('ws');
|
||||
const WebSocketServer = WebSocket.Server;
|
||||
|
||||
// Yes, TLS is required
|
||||
// Yes, TLS is required for WebRTC
|
||||
const serverConfig = {
|
||||
key: fs.readFileSync('key.pem'),
|
||||
cert: fs.readFileSync('cert.pem'),
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
function main() {
|
||||
const httpsServer = startHttpsServer(serverConfig);
|
||||
startWebSocketServer(httpsServer);
|
||||
printHelp();
|
||||
}
|
||||
|
||||
// Create a server for the client html page
|
||||
const handleRequest = function(request, response) {
|
||||
// Render the single client html file for any request the HTTP server receives
|
||||
console.log('request received: ' + request.url);
|
||||
function startHttpsServer(serverConfig) {
|
||||
// Handle incoming requests from the client
|
||||
const handleRequest = (request, response) => {
|
||||
console.log(`request received: ${request.url}`);
|
||||
|
||||
// This server only serves two files: The HTML page and the client JS file
|
||||
if(request.url === '/') {
|
||||
response.writeHead(200, {'Content-Type': 'text/html'});
|
||||
response.end(fs.readFileSync('client/index.html'));
|
||||
|
|
@ -25,35 +30,40 @@ const handleRequest = function(request, response) {
|
|||
response.writeHead(200, {'Content-Type': 'application/javascript'});
|
||||
response.end(fs.readFileSync('client/webrtc.js'));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const httpsServer = https.createServer(serverConfig, handleRequest);
|
||||
httpsServer.listen(HTTPS_PORT, '0.0.0.0');
|
||||
const httpsServer = https.createServer(serverConfig, handleRequest);
|
||||
httpsServer.listen(HTTPS_PORT, '0.0.0.0');
|
||||
return httpsServer;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
function startWebSocketServer(httpsServer) {
|
||||
// Create a server for handling websocket calls
|
||||
const wss = new WebSocketServer({server: httpsServer});
|
||||
|
||||
// Create a server for handling websocket calls
|
||||
const wss = new WebSocketServer({server: httpsServer});
|
||||
|
||||
wss.on('connection', function(ws) {
|
||||
ws.on('message', function(message) {
|
||||
wss.on('connection', (ws) => {
|
||||
ws.on('message', (message) => {
|
||||
// Broadcast any received message to all clients
|
||||
console.log('received: %s', message);
|
||||
console.log(`received: ${message}`);
|
||||
wss.broadcast(message);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
wss.broadcast = function(data) {
|
||||
this.clients.forEach(function(client) {
|
||||
wss.broadcast = function(data) {
|
||||
this.clients.forEach((client) => {
|
||||
if(client.readyState === WebSocket.OPEN) {
|
||||
client.send(data);
|
||||
client.send(data, {binary: false});
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
console.log('Server running. Visit https://localhost:' + HTTPS_PORT + ' in Firefox/Chrome.\n\n\
|
||||
Some important notes:\n\
|
||||
* Note the HTTPS; there is no HTTP -> HTTPS redirect.\n\
|
||||
* You\'ll also need to accept the invalid TLS certificate.\n\
|
||||
* Some browsers or OSs may not allow the webcam to be used by multiple pages at once. You may need to use two different browsers or machines.\n'
|
||||
);
|
||||
function printHelp() {
|
||||
console.log(`Server running. Visit https://localhost:${HTTPS_PORT} in Firefox/Chrome/Safari.\n`);
|
||||
console.log('Please note the following:');
|
||||
console.log(' * Note the HTTPS in the URL; there is no HTTP -> HTTPS redirect.');
|
||||
console.log(' * You\'ll need to accept the invalid TLS certificate as it is self-signed.');
|
||||
console.log(' * Some browsers or OSs may not allow the webcam to be used by multiple pages at once. You may need to use two different browsers or machines.');
|
||||
}
|
||||
|
||||
main();
|
||||
|
|
|
|||
Loading…
Reference in New Issue