Last active
November 7, 2021 00:29
-
-
Save clemos/9dbd351972dcf6ac4d89a8449511989e to your computer and use it in GitHub Desktop.
quick and dirty nodejs webrtc server
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
var pc = new RTCPeerConnection(); | |
var localVideo = document.getElementById('local'); | |
var remoteVideo = document.getElementById('remote'); | |
var isBroadcaster = document.location.hash.indexOf('broadcast') > -1; | |
var watcherId; | |
function broadcast(stream) { | |
localVideo.src = URL.createObjectURL(stream); | |
pc.addStream(stream); | |
connect(); | |
} | |
function post(endpoint, payload, cb) { | |
var x = new XMLHttpRequest(); | |
x.open('POST',endpoint); | |
x.onreadystatechange = function(e){ | |
console.log('ready',x); | |
if(x.readyState==4){ | |
console.log('got answer',x.responseText); | |
cb(x.responseText); | |
} | |
}; | |
x.send(payload); | |
} | |
function connect(){ | |
var ch = pc.createDataChannel('test'); | |
pc.ondatachannel = function(e){ | |
console.log('got remote datachannel', e.channel); | |
} | |
pc.onaddstream = function(e){ | |
console.log('got remote stream', e.stream); | |
remoteVideo.src = URL.createObjectURL(e.stream); | |
} | |
function sendOffer(){ | |
console.log('sending offer',pc.localDescription); | |
var payload = JSON.stringify(pc.localDescription); | |
var endpoint = '/broadcast'; | |
post(endpoint,payload,function(data){ | |
pc.setRemoteDescription(new RTCSessionDescription(JSON.parse(data))); | |
}); | |
} | |
function sendAnswer(){ | |
console.log('sending answer', watcherId,pc.localDescription); | |
var payload = JSON.stringify({ | |
session:pc.localDescription, | |
watcherId:watcherId | |
}); | |
var endpoint = '/answer'; | |
post(endpoint,payload,function(){ | |
console.log('done sending answer'); | |
}); | |
} | |
function getOffer(){ | |
console.log('retrieving offer'); | |
post('/watch','', function(json){ | |
var data = JSON.parse(json); | |
watcherId = data.watcherId; | |
pc.setRemoteDescription(new RTCSessionDescription(data.session)) | |
.then(()=>{ | |
console.log('success setting remote description'); | |
}); | |
pc.onaddstream = (e)=>{ | |
console.log('GOT REMOTE STREAM !!',e); | |
remoteVideo.src = URL.createObjectURL(e.stream); | |
} | |
pc.createAnswer().then((answer)=>{ | |
console.log('got answer', answer); | |
pc.setLocalDescription(new RTCSessionDescription(answer)); | |
}); | |
}); | |
} | |
pc.onicecandidate = function(e){ | |
console.log('got ice candidate',e); | |
if(e.candidate==null){ | |
if( isBroadcaster ) { | |
sendOffer(); | |
} else { | |
sendAnswer(); | |
} | |
} | |
} | |
if( isBroadcaster ) { | |
pc.createOffer().then((offer)=>{ | |
pc.setLocalDescription(offer); | |
console.log('got offer', offer); | |
}); | |
} else { | |
getOffer(); | |
} | |
} | |
var br; | |
if( isBroadcaster ) { | |
navigator.getUserMedia({video:true, audio:true},(stream)=>{ | |
br = stream; | |
broadcast(stream); | |
}, (err)=>{ | |
console.error('error getting user media',err); | |
}); | |
}else{ | |
connect(); | |
} | |
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
var http = require('http'); | |
var fs = require('fs'); | |
var webrtc = require('./index.js'); | |
const PORT = 3000; | |
function index(req,res){ | |
res.writeHead(200, { | |
"content-type":"text/html" | |
}); | |
res.write('<html><head></head><body><video id="local" autoplay></video><video id="remote" autoplay></video><script src="/client.js"></script></body></html>'); | |
res.end(); | |
} | |
function client(req,res){ | |
fs.createReadStream('client.js').pipe(res); | |
} | |
function readRequest(req, cb) { | |
var chunks = []; | |
req.on('data',(data)=>{ | |
chunks.push(data); | |
}); | |
req.on('end',()=>{ | |
cb(Buffer.concat(chunks).toString()); | |
}); | |
} | |
function createConnection(cb){ | |
var pc = new webrtc.RTCPeerConnection({}); | |
pc.addEventListener('icecandidate', (e)=>{ | |
console.log('got ice candidate',e); | |
if( e.candidate == null ) { | |
cb(); | |
} | |
}); | |
pc.addEventListener('datachannel', (e)=>{ | |
console.log('got remote datachannel',e); | |
e.channel.addEventListener('message', function(m){ | |
console.log('got message on remote channel',m.data); | |
}); | |
}); | |
var ch = pc.createDataChannel('test'); | |
ch.addEventListener('message',function(m){ | |
console.log('got message on local datachannel', m); | |
}); | |
return pc; | |
} | |
var broadcast = null; | |
function doBroadcast(req,res){ | |
console.log('do broadcast'); | |
var pc; | |
readRequest(req,(data)=>{ | |
var offer = JSON.parse(data); | |
var remote = new webrtc.RTCSessionDescription(offer); | |
pc = createConnection(()=>{ | |
res.writeHead(200,{"content-type":"text/json"}); | |
res.write(JSON.stringify(pc.localDescription)); | |
res.end(); | |
}); | |
pc.addEventListener('addstream', (e)=>{ | |
console.log('got broadcast stream'); | |
broadcast = e.stream; | |
}); | |
pc.setRemoteDescription(remote,function(){ | |
console.log('success setting remote description'); | |
}, function(err){ | |
console.log('error setting remote description'); | |
}); | |
pc.createAnswer().then((answer)=>{ | |
var local = new webrtc.RTCSessionDescription(answer); | |
pc.setLocalDescription(local).then(()=>{ | |
console.log('success setting local description'); | |
}); | |
}); | |
}); | |
} | |
var watchers = []; | |
function doWatch(req,res){ | |
if( broadcast == null ) { | |
res.writeHead(404,{"content-type":"text/json"}); | |
res.write('{"error":"no broadcast stream"}'); | |
res.end(); | |
return; | |
} | |
console.log('DO WATCH'); | |
var pc; | |
var watcherId = watchers.length; | |
pc = createConnection(()=>{ | |
res.writeHead(200,{"content-type":"text/json"}); | |
var data = { | |
session: pc.localDescription, | |
watcherId: watcherId | |
}; | |
console.log('sending data to peer', data); | |
res.write(JSON.stringify(data)); | |
res.end(); | |
}); | |
console.log('adding PC to watchers list', watcherId); | |
watchers.push(pc); | |
pc.addStream(broadcast); | |
pc.createOffer().then((offer)=>{ | |
var local = new webrtc.RTCSessionDescription(offer); | |
pc.setLocalDescription(local).then(()=>{ | |
console.log('success setting local description'); | |
}); | |
}); | |
} | |
function doAnswer(req,res){ | |
readRequest(req,(json)=>{ | |
var data = JSON.parse(json); | |
console.log('got answer ',data); | |
var watcherId = data.watcherId; | |
console.log('picking watcher', watcherId, "out of", watchers.length); | |
var pc = watchers[watcherId]; | |
pc.setRemoteDescription(new webrtc.RTCSessionDescription(data.session)).then(function(){ | |
console.log('success setting session description for watcher #' + watcherId ); | |
res.end(); | |
}); | |
}); | |
} | |
const server = http.createServer(function(req,res){ | |
console.log('got req ', req.url); | |
switch(req.url){ | |
case '/': | |
return index(req,res); | |
case '/client.js': | |
return client(req,res); | |
case '/broadcast': | |
return doBroadcast(req,res); | |
case '/watch': | |
return doWatch(req,res); | |
case '/answer': | |
return doAnswer(req,res); | |
default: | |
res.writeHead(404,{}); | |
res.end(); | |
} | |
}); | |
server.listen(PORT); |
Hi
What does the var webrtc = require('./index.js'); file refer to?
It was very probably referring to this webrtc implementation for node.js : aisouard/node-webrtc#5
Unfortunately, this project is pretty much dead. But 4 years later, there probably exists a better webrtc package for node.js somewhere 🤷
Just curious: what are you working on ?
Thanks 🙏
Hi, thank you for your reply.
I will continue look around for a more updated webrtc nodejs implementation.
A new type of video conferencing platform.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi Clément, this is great!
What does the var webrtc = require('./index.js'); file refer to?
I know it was a long time ago, though your help would be great.