Added webRTC media connection
This commit is contained in:
parent
c0ba6d31d5
commit
9dad2c131b
|
|
@ -0,0 +1,187 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
let stream;
|
||||||
|
let localStream;
|
||||||
|
let localPeer;
|
||||||
|
let remotePeer;
|
||||||
|
|
||||||
|
const constraints = {
|
||||||
|
video: {
|
||||||
|
mediaSource: "screen", // whole screen sharing
|
||||||
|
//mediaSource: "window", // choose a window to share
|
||||||
|
//mediaSource: "application", // choose a window to share
|
||||||
|
width: {max: '1920'},
|
||||||
|
height: {max: '1080'},
|
||||||
|
frameRate: {max: '10'}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const offerOptions = {
|
||||||
|
OfferToReceiveAudio: 1,
|
||||||
|
OfferToReceiveVideo: 1
|
||||||
|
};
|
||||||
|
|
||||||
|
var configuration = {
|
||||||
|
"iceServers": [{ "urls": "stun:stun.1.google.com:19302" }]
|
||||||
|
};
|
||||||
|
|
||||||
|
let iceCandidates = [];
|
||||||
|
|
||||||
|
|
||||||
|
function checkUsers() {
|
||||||
|
streamws.send(
|
||||||
|
JSON.stringify({
|
||||||
|
type: "check-users",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empezar el streaming local:
|
||||||
|
// 1. Desactivar el botón de start, localVideo.play(),
|
||||||
|
// obtener el media stream, establecer localVideo.srcObject = stream y
|
||||||
|
// dar valor a la variable localStream con el stream que hemos obtenido.
|
||||||
|
// 2. Crear la instancia de la RTCPeerConnection
|
||||||
|
// 3. Crear el handler del evento icecandidate
|
||||||
|
// 4. Añadir los media tracks del localStream para que sean enviadas
|
||||||
|
// al remote peer
|
||||||
|
// 5. Crear la oferta de candidato en el extremo local
|
||||||
|
// 6. Crear la descripción local de localPeer
|
||||||
|
async function startLocalStream(){
|
||||||
|
console.log('[NOVNC] empezando stream local');
|
||||||
|
// Obtener el stream del usuario
|
||||||
|
if(!canvas){
|
||||||
|
console.log('[NOVNC] Error: no CANVAS');
|
||||||
|
return
|
||||||
|
}
|
||||||
|
stream = canvas.captureStream();
|
||||||
|
|
||||||
|
// Mostrar el video
|
||||||
|
localVideo.srcObject = stream;
|
||||||
|
|
||||||
|
// Establecer cual es el localStream
|
||||||
|
localStream = stream;
|
||||||
|
|
||||||
|
// Crear instancia de RTCPeerConnection
|
||||||
|
localPeer = new RTCPeerConnection(configuration);
|
||||||
|
|
||||||
|
// Send candidate to the remote peer
|
||||||
|
localPeer.addEventListener('icecandidate', event => onIceCandidate(localPeer, event));
|
||||||
|
|
||||||
|
// Añadir los media tracks que genera el localStream a
|
||||||
|
// las tracks de localPeer para enviarlas al remote peer
|
||||||
|
localStream.getTracks().forEach(track => localPeer.addTrack(track, localStream));
|
||||||
|
console.log('[NOVNC] Adding tracks');
|
||||||
|
|
||||||
|
// Crear oferta
|
||||||
|
localPeer.createOffer(offerOptions);
|
||||||
|
|
||||||
|
// Establecer la descripcion de localPeer
|
||||||
|
localPeer.addEventListener('negotiationneeded', addLocalDescription(localPeer));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cuando recibo un socket del tipo offer:
|
||||||
|
// 1. Creo la instancia de la conexión RTC del extemo remoto
|
||||||
|
// 2. Creo el hadler para el evento icecandidate
|
||||||
|
// 3. Handler para recibir los mediatracks
|
||||||
|
// 4. Notifico si el estado del remotePeer cambia
|
||||||
|
// 5. Establezco la descripcion remota del extremo remoto
|
||||||
|
// 6. Crear respuesta y establecer la descripcion local del extremo remoto
|
||||||
|
// 7. Enviar un websocket con la respuesta al otro peer
|
||||||
|
async function startRemoteStream(offer){
|
||||||
|
// Creo la instancia de la conexión remota
|
||||||
|
remotePeer = new RTCPeerConnection(configuration);
|
||||||
|
console.log('[NOVNC] RTC Remote Peer conection created');
|
||||||
|
|
||||||
|
// Handler para el evento icecandidate
|
||||||
|
// Send candidate to the remote peer
|
||||||
|
remotePeer.addEventListener('icecandidate', event => onIceCandidate(remotePeer, event));
|
||||||
|
|
||||||
|
// Recibir los media tracks del extremo local
|
||||||
|
remotePeer.ontrack = gotRemoteStream;
|
||||||
|
|
||||||
|
// Notificar si el estado remoto cambia
|
||||||
|
remotePeer.oniceconnectionstatechange = () => console.log('Remote ice state ' + remotePeer.iceConnectionState);
|
||||||
|
|
||||||
|
// Set remote description
|
||||||
|
try {
|
||||||
|
remotePeer.setRemoteDescription(offer);
|
||||||
|
console.log('[NOVNC] Remote description set');
|
||||||
|
} catch (error) {
|
||||||
|
console.log(`[NOVNC] Set remote description error: ${error}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Create answer
|
||||||
|
const answer = await remotePeer.createAnswer();
|
||||||
|
// Set local description of remote peer
|
||||||
|
remotePeer.setLocalDescription(answer);
|
||||||
|
// Signal localStream peer with the answer
|
||||||
|
signalRemotePeer(JSON.stringify({
|
||||||
|
'type':'answer',
|
||||||
|
'answer':answer
|
||||||
|
}));
|
||||||
|
}catch(error){
|
||||||
|
console.log(`[NOVNC] Failed to create local session description ${error}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function addIceCandidate(candidate) {
|
||||||
|
//var candidate = new RTCIceCandidate(cand)
|
||||||
|
if (localPeer === undefined) {
|
||||||
|
remotePeer.addIceCandidate(candidate);
|
||||||
|
} else {
|
||||||
|
localPeer.addIceCandidate(candidate);
|
||||||
|
}
|
||||||
|
console.log('[NOVNC] Candidate Added');
|
||||||
|
}
|
||||||
|
|
||||||
|
async function setAnswerDescription(answer){
|
||||||
|
try {
|
||||||
|
localPeer.setRemoteDescription(answer);
|
||||||
|
console.log("[NOVNC] Local Peer remote description set");
|
||||||
|
}catch(error){
|
||||||
|
console.log(`[NOVNC] Failed setting local peer remote description ${error}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Añadir los candidatos a la lista de candidatos
|
||||||
|
function onIceCandidate(peer, event){
|
||||||
|
if(event.candidate != null && event.candidate != undefined){
|
||||||
|
console.log(`[NOVNC] onicecandidate event on ${peer}`);
|
||||||
|
// Send the candidate to the other peer via WebSockets
|
||||||
|
signalRemotePeer(JSON.stringify({
|
||||||
|
'type':'candidate',
|
||||||
|
'candidate':event.candidate
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function addLocalDescription(peer) {
|
||||||
|
try {
|
||||||
|
const offer = await peer.createOffer(offerOptions);
|
||||||
|
peer.setLocalDescription(offer);
|
||||||
|
console.log(`[NOVNC] ${peer} local description set`);
|
||||||
|
signalRemotePeer(JSON.stringify({
|
||||||
|
'type':'offer',
|
||||||
|
'offer':offer
|
||||||
|
}));
|
||||||
|
} catch(err) {
|
||||||
|
console.log(`[NOVNC] ${peer} error setting local description`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function signalRemotePeer(data){
|
||||||
|
streamws.send(data);
|
||||||
|
console.log('[NOVNC] Signaling remote peer...');
|
||||||
|
}
|
||||||
|
|
||||||
|
function gotRemoteStream(e){
|
||||||
|
console.log('[NOVNC] Got remote video: ', e.streams[0]);
|
||||||
|
if (remoteVideo.srcObject !== e.streams[0]) {
|
||||||
|
//rightVideo.play();
|
||||||
|
remoteVideo.srcObject = e.streams[0];
|
||||||
|
console.log('[NOVNC] pc2 received remote stream');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// Create websocket for communication
|
||||||
|
const websocket = new WebSocket(
|
||||||
|
'ws://' +
|
||||||
|
window.location.host +
|
||||||
|
'/ws/chat/' +
|
||||||
|
room_name +
|
||||||
|
'/'
|
||||||
|
);
|
||||||
|
console.log('Websocket created for room: ', room_name);
|
||||||
|
|
||||||
|
let token = new Date().getTime() + Math.random();
|
||||||
|
console.log('token: ',token);
|
||||||
|
|
||||||
|
websocket.onmessage = function(event){
|
||||||
|
let message_data = JSON.parse(event.data);
|
||||||
|
console.log('WebSocket received: ', message_data);
|
||||||
|
|
||||||
|
// If the content type from the websocket is chat_message,
|
||||||
|
// the text field is appended to the chat box
|
||||||
|
if(message_data['type'] == 'chat_message'){
|
||||||
|
if(Number(token) !== Number(message_data['token'])){
|
||||||
|
console.log('Escribir mensaje');
|
||||||
|
add_message('receive', message_data['message']);
|
||||||
|
}
|
||||||
|
}else if(message_data['type'] == 'candidate'){
|
||||||
|
console.log('Candidate received');
|
||||||
|
addIceCandidate(message_data['candidate']);
|
||||||
|
}else if(message_data['type'] == 'offer'){
|
||||||
|
console.log('Offer received');
|
||||||
|
startRemoteStream(message_data['offer']);
|
||||||
|
}else if(message_data['type'] == 'answer'){
|
||||||
|
console.log('Answer received');
|
||||||
|
setAnswerDescription(message_data['answer']);
|
||||||
|
}else if(message_data['type'] == 'denied'){
|
||||||
|
console.log('Denied connection');
|
||||||
|
window.location.pathname = '/';
|
||||||
|
}else if(message_data['type'] == 'checkusers'){
|
||||||
|
if(message_data['users']){
|
||||||
|
startLocalStream()
|
||||||
|
}else{
|
||||||
|
console.log('No peer connected')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function add_message(direction, message){
|
||||||
|
let chat_log = document.querySelector('#chat-log');
|
||||||
|
|
||||||
|
if(direction === 'send'){
|
||||||
|
chat_log.innerHTML += ('<p class="send"> [You] ' + message + '</p>');
|
||||||
|
}else if(direction === 'receive'){
|
||||||
|
chat_log.innerHTML += ('<p class="receive"> [Sender] ' + message + '</p>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Focus al input text
|
||||||
|
document.querySelector('#chat-message-input').focus();
|
||||||
|
|
||||||
|
// On Enter pressed, the WebSocket is sent
|
||||||
|
document.querySelector('#chat-message-input').onkeyup = function(e) {
|
||||||
|
if (e.keyCode === 13) { // enter, return
|
||||||
|
document.querySelector('#chat-message-submit').click();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Al hacer click en el botón de enviar el websocket se envía
|
||||||
|
document.querySelector('#chat-message-submit').onclick = function(e) {
|
||||||
|
const messageInputDom = document.querySelector('#chat-message-input');
|
||||||
|
const message = messageInputDom.value;
|
||||||
|
websocket.send(JSON.stringify({
|
||||||
|
'type':'chat_message',
|
||||||
|
'token':token,
|
||||||
|
'message': message,
|
||||||
|
}));
|
||||||
|
console.log('WebSocket sent!');
|
||||||
|
add_message('send', message);
|
||||||
|
messageInputDom.value = '';
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue