I have tried to connect my video (No webcam) to sync with the other video remotely. But I don't know where I'm wrong. I did it taking into account that they were going to connect to the same room. One performs the stream (LocalVideo) and the other sees what the other does (Remote). Something very similar to this: https://webrtc.github.io/samples/src/content/capture/video-pc/. But I still haven't given an answer for the problem, PLEASE if someone who knows about node.js and WebRTC can rescue me!
main.js:
let divSelectRoom = document.getElementById("selectRoom")
let divConsultingRoom = document.getElementById("consultingRoom")
let divConsultingRoom2 = document.getElementById("consultingRoom2")
let inputRoomNumber = document.getElementById("roomNumber")
let btnGoRoom = document.getElementById("goRoom")
let localVideo = document.getElementById("localVideo")
let remoteVideo = document.getElementById("remoteVideo")
let locallabel = document.getElementById("locallabel")
let visitlabel = document.getElementById("visitlabel")
let roomNumber, localStream, remoteStream, rtcPeerConnection, isCaller
let stream;
const iceServers = {
'iceServer': [
{ 'urls': 'stun:stun.services.mozilla.com' },
{ 'urls': 'stun:stun.l.google.com:19302' }
]
}
const streamConstraints = {
audio: 1,
video: 1
}
let startTime;
const socket = io();
btnGoRoom.onclick = () => {
if (inputRoomNumber.value == '') {
alert("please type a room name")
} else {
roomNumber = inputRoomNumber.value
socket.emit('create or join', roomNumber)
divSelectRoom.style = "display: none"
}
}
function maybeCreateStream() {
if (stream) {
return;
}
if (localVideo.captureStream) {
stream = localVideo.captureStream();
console.log('Captured stream from localVideo with captureStream',
stream);
} else if (localVideo.mozCaptureStream) {
stream = localVideo.mozCaptureStream();
console.log('Captured stream from localVideo with mozCaptureStream()',
stream);
} else {
console.log('captureStream() not supported');
}
localStream = stream
}
localVideo.play();
socket.on('created', room => {
divConsultingRoom.style = "display: block"
// Video tag capture must be set up after video tracks are enumerated.
localVideo.oncanplay = maybeCreateStream;
if (localVideo.readyState >= 3) { // HAVE_FUTURE_DATA
// Video is already ready to play, call maybeCreateStream in case oncanplay
// fired before we registered the event handler.
maybeCreateStream();
}
isCaller = true
})
socket.on('joined', room => {
divConsultingRoom2.style = "display: block"
remoteVideo.srcObject = localStream;
isCaller = false
socket.emit('ready', roomNumber)
})
socket.on('ready', () => {
console.log('enter ready')
const videoTracks = stream.getVideoTracks();
const audioTracks = stream.getAudioTracks();
if (videoTracks.length > 0) {
console.log(`Using video device: ${videoTracks[0].label}`);
}
if (audioTracks.length > 0) {
console.log(`Using audio device: ${audioTracks[0].label}`);
}
if (isCaller) {
rtcPeerConnection = new RTCPeerConnection(iceServers)
rtcPeerConnection.onicecandidate = onIceCandidate
rtcPeerConnection.ontrack = onAddStream
rtcPeerConnection.addTrack(localStream.getTracks()[0], localStream)
rtcPeerConnection.addTrack(localStream.getTracks()[1], localStream)
rtcPeerConnection.createOffer()
.then(sessionDescription => {
console.log('sending offer', sessionDescription)
rtcPeerConnection.setLocalDescription(sessionDescription)
socket.emit('offer', {
type: 'offer',
sdp: sessionDescription,
room: roomNumber
})
}).catch(err => {
console.log(err)
})
}
})
socket.on('offer', (event) => {
console.log('enter offer', isCaller)
if (!isCaller) {
rtcPeerConnection = new RTCPeerConnection(iceServers)
rtcPeerConnection.onicecandidate = onIceCandidate
rtcPeerConnection.ontrack = onAddStream
//rtcPeerConnection.addTrack(localStream.getTracks()[0], localStream)
//rtcPeerConnection.addTrack(localStream.getTracks()[1], localStream)
console.log('received offer', event)
rtcPeerConnection.setRemoteDescription(new RTCSessionDescription(event))
rtcPeerConnection.createAnswer().then(sessionDescription => {
console.log('sending answer', sessionDescription)
socket.emit('answer', {
type: 'answer',
sdp: sessionDescription,
room: roomNumber
})
}).catch(err => {
console.log(err)
})
}
})
socket.on('answer', event => {
console.log('received answer', event)
rtcPeerConnection.setRemoteDescription(new RTCSessionDescription(event))
})
socket.on('candidate', event => {
const candidate = new RTCIceCandidate({
sdpMLineIndex: event.label,
candidate: event.candidate
})
console.log('received candidate', candidate)
rtcPeerConnection.addIceCandidate(candidate)
})
function onAddStream(event) {
console.log('Stream It')
remoteVideo.srcObject = event.streams[0];
remoteStream = event.streams[0]
console.log('visit received remote stream', event.streams[0]);
}
function onIceCandidate(event) {
if (event.candidate) {
console.log('sending ice candidate', event.candidate)
socket.emit('candidate', {
type: 'candidate',
label: event.candidate.sdpMLineIndex,
id: event.candidate.sdpMid,
candidate: event.candidate.candidate,
room: roomNumber
})
}
}
app.js:
const { Socket } = require('dgram')
const express = require('express')
const app = express()
let http = require('http').Server(app)
const port = process.env.PORT || 3000
let io = require('socket.io')(http)
app.use(express.static('public'))
http.listen(port, () => {
console.log('listening on', port)
})
io.on('connection', socket => {
console.log('a user connected')
socket.on('create or join', room => {
console.log('create or join to room', room)
const myRoom = io.sockets.adapter.rooms[room] || {length: 0}
const numClients = myRoom.length
console.log(room, 'has',numClients,'clients')
if(numClients == 0){
socket.join(room)
socket.emit('created', room)
}else if (numClients == 1){
socket.join(room)
socket.emit('joined', room)
}else{
socket.emit('full', room)
}
})
socket.on('ready', room => {
socket.broadcast.to(room).emit('ready')
})
socket.on('candidate', event => {
socket.broadcast.to(event.room).emit('candidate', event)
})
socket.on('offer', event => {
socket.broadcast.to(event.room).emit('offer', event.sdp)
})
socket.on('answer', event => {
socket.broadcast.to(event.room).emit('answer', event.sdp)
})
})
index.html:
<!DOCTYPE html>
<head>
<title>WebRTC Training</title>
</head>
<body>
<h1>WebRTC TRAINING</h1>
<div id="selectRoom">
<label>Type room name</label>
<input id="roomNumber" type="text"/>
<button id="goRoom">Go</button>
</div>
<div id="consultingRoom" style="display: none;">
<video id="localVideo" playsinline controls loop muted>
<source src="videos/dudu.webm" type="video/webm"/>
<source src="videos/dudu.mp4" type="video/mp4"/>
<p>This browser does not support the video element.</p>
</video>
<label id="locallabel">local</label>
</div>
<div id="consultingRoom2" style="display: none;">
<video id="remoteVideo" playsinline autoplay></video>
<label id="visitlabel">visit</label>
</div>
<script src="/socket.io/socket.io.js"></script>
<script src="main.js"></script>
</body>
This is a picture so you can understand it better.