WebRTC permitirá comunicación en tiempo real desde el navegador. En esta charla vimos los desafíos que se presenta para hacer videoconferencia multiusuario y enseñamos Lynckia, un API que facilita su implementación a los desarrolladores JavaScript.
Global Azure Lima 2024 - Integración de Datos con Microsoft Fabric
Presentación WebRTC y Lynckia
1. WebRTC
Comunicaciones en tiempo real desde tu navegador
Javier Cerviño Alvaro Alonso Pedro Rodriguez
jcervino@dit.upm.es aalonsog@dit.upm.es prodriguez@dit.upm.es
@jcague @larsonalonso @lodoyun
Nestor Toribio Joaquín Salvachúa
nestortoribioruiz@gmail.com jsr@dit.upm.es
@nehko1 @jsalvachua
Grupo de Internet de Nueva Generación
Departamento de Ingeniería de Sistemas Telemáticos
Universidad Politécnica de Madrid
2. Previously on GING
Isabel 1995 (o por ahi)
Aplicación de escritorio
Ubuntu/Windows
P2P/Centralizado
Pasarelas SIP
Marte 2007
Aplicación Flash sobre el navegador
Centralizado
Desktop
VaaS 2010
Cloud Computing
Aplicación Flash sobre el navegador
Desktop y Móviles
Javier Cerviño Alvaro Alonso
@jcague @larsonalonso
3. Índice
1. Introducción a WebRTC
1. Descripción
2. Ejemplo de llamada
3. Estado actual
2. Problemas de WebRTC
3. Videoconferencia multiusuario
1. Lynckia, componentes y API
2. Ejemplos
Javier Cerviño Alvaro Alonso
@jcague @larsonalonso
4. Índice
1. Introducción a WebRTC
1. Descripción
2. Ejemplo de llamada
3. Estado actual
2. Problemas de WebRTC
3. Videoconferencia multiusuario
1. Lynckia, componentes y API
2. Ejemplos
Javier Cerviño Alvaro Alonso
@jcague @larsonalonso
7. PROTOCOLOS PROPIETARIOS
HTTP/WEBSOCKETS
JS/CSS/HTML JS/CSS/HTML
TRANSMISIÓN
Navegador Navegador
DE MEDIOS
Javier Cerviño Alvaro Alonso
@jcague @larsonalonso
8. APIs de WebRTC en JavaScript
Tres Grandes APIs
getUserMedia
Obtención de flujos locales
StreamAPI
Manejo de flujos multimedia
PeerConnection
Conexiones entre pares
Javier Cerviño Alvaro Alonso
@jcague @larsonalonso
9. Ejemplo de llamada
1. getUserMedia() 5. getUserMedia()
2. pc = new PeerConnection() 6. pc = new PeerConnection()
3. onLocalSignallingMessage(sdpOffer) 7. pc.processSignalingMessage(sdpOffer)
8. onLocalSignallingMessage(sdpAnswer)
10. pc.processSignalingMessage(sdpAnswer)
11. onLocalSignallingMessage(sdpOk) 13. pc.processSignalingMessage(sdpOk
)
14
Alice Javier Cerviño Bob
Alvaro Alonso
@jcague @larsonalonso
10. Google
Proyecto de código libre escrito en C++
Respaldado por Google, Mozilla y Opera entre otros.
Implementación de todo WebRTC
Javier Cerviño Alvaro Alonso
@jcague @larsonalonso
11. Google
Primera Fase
• Librería en C++ implementando rtcweb
Segunda Fase
• Inclusión de la librería en navegadores
• Implica implementación del API JavaScript
Actualmente:
• Primera versión disponible: iteraciones y pruebas
Javier Cerviño Alvaro Alonso
@jcague @larsonalonso
12. Ericsson Labs
Javier Cerviño Alvaro Alonso
@jcague @larsonalonso
13. Ericsson Labs
Bowser
Navegador Web en el móvil
Soporte WebRTC
Disponible para iOS y Android
https://labs.ericsson.com/apps/bowser
Javier Cerviño Alvaro Alonso
@jcague @larsonalonso
14. Mozilla
Firefox 18 con soporte completo de WebRTC
GetUserMedia
StreamAPI
PeerConnection
Lanzamiento en enero de 2013
https://hacks.mozilla.org/2012/09/full-webrtc-support-is-soon-coming-to-a-web-browser-near-you/
Javier Cerviño Alvaro Alonso
@jcague @larsonalonso
15. Internet Explorer
Soporte experimental de GetUserMedia
navigator.msGetUserMedia(options, cameraStarted);
function cameraStarted(mediaStream) {
msMediaStream = mediaStream;
document["imgPreview"].src = URL.createObjectURL(mediaStream);
}
http://blogs.msdn.com/b/ie/archive/2012/03/16/media-capture-prototype-improved-support-for-real-world-web-apps.aspx
Javier Cerviño Alvaro Alonso
@jcague @larsonalonso
17. Índice
1. Introducción a WebRTC
1. Descripción
2. Ejemplo de llamada
3. Estado actual
2. Problemas de WebRTC
3. Videoconferencia multiusuario
1. Lynckia, componentes y API
2. Ejemplos
Javier Cerviño Alvaro Alonso
@jcague @larsonalonso
23. Índice
1. Introducción a WebRTC
1. Descripción
2. Ejemplo de llamada
3. Estado actual
2. Problemas de WebRTC
3. Videoconferencia multiusuario
1. Lynckia, componentes y API
2. Ejemplos
Javier Cerviño Alvaro Alonso
@jcague @larsonalonso
24. Lynckia
Erizo
Nuve
Javier Cerviño Alvaro Alonso
@jcague @larsonalonso
25. Lynckia - Salas
Una sala es una MCU
Permite publicar streams
Video, audio, datos
Permite subscribirse a ellos
Control desde el navegador
Permitirá transcodificar/grabar
Javier Cerviño Alvaro Alonso
@jcague @larsonalonso
26. Lynckia - Nuve API
Accesible a través del Backend
Dirigido a servicios
Administración de salas
Nuve
Gestiona la escalabilidad
Monitoriza
Creación de tokens
Javier Cerviño Alvaro Alonso
@jcague @larsonalonso
27. Lynckia - Erizo
Accesible a traves del
Frontend
Erizo
Contiene las MCU
Cada sala es una de ellas
Gestiona los streams
Audio, video y datos
Javier Cerviño Alvaro Alonso
@jcague @larsonalonso
28. Lynckia - Erizo
Erizo
Disponible en:
https://github.com/ging/erizo
Erizo Codigo C++
Protocolos WebRTC
Linux/Mac
Erizo API
Disponible en:
https://github.com/ging/erizoAPI
Wrapper en Node.js
Pronto a traves de NPM
Javier Cerviño Alvaro Alonso
@jcague @larsonalonso
29. Lynckia API
API Servidor Streams
Rooms Rooms
Tokens Events
Users
API Cliente Javier Cerviño Alvaro Alonso
@jcague @larsonalonso
30. API Servidor
Comunicación con Nuve
API para gestión del Servicio
Salas videoconferencia
Tokens autenticación
Usuarios
Código
Node.js
Python
(Ruby)
Javier Cerviño Alvaro Alonso
@jcague @larsonalonso
31. API Servidor - Room
Propiedades Funciones
Room._id createRoom (name)
Room.name getRooms ()
getRoom (roomId)
deleteRoom (roomId)
Ejemplo
var N = require('./nuve');
N.API.init(serviceId, serviceKey);
var roomName = 'myFirstRoom';
N.API.createRoom(roomName, function(room) {
console.log('Room created with id: ', room._id);
});
Javier Cerviño Alvaro Alonso
@jcague @larsonalonso
32. API Servidor - Token
String con las credenciales de autenticación
Funciones
createToken (roomId, name, role)
Ejemplo
var roomId = '30121g51113e74fff3115502';
var name = 'userName';
var role = '';
N.API.createToken(room, name, role, function(token) {
console.log('Token created: ', token);
});
Javier Cerviño Alvaro Alonso
@jcague @larsonalonso
33. API Servidor - User
Propiedades Funciones
User.name getUsers (roomId)
User.role
Ejemplo
var roomId = '30121g51113e74fff3115502';
N.API.getUsers(roomId, function(users) {
console.log('This room has ', users.length, 'users');
for (var i in users) {
console.log('User ', i, ':', users[i].name,
'role: ', users[i].role);
}
});
Javier Cerviño Alvaro Alonso
@jcague @larsonalonso
34. Lynckia API
API Servidor Streams
Rooms Rooms
Tokens Events
Users
API Cliente Javier Cerviño Alvaro Alonso
@jcague @larsonalonso
35. API Cliente
Comunicación con Erizo
Manejo flujos (Streams)
Audio
Vídeo
Datos
Interacción salas (Rooms)
Conexión
Intercambio flujos
Captura eventos (Events)
En flujos
En salas
Javier Cerviño Alvaro Alonso
@jcague @larsonalonso
36. API Cliente - Stream (I)
Crear un Stream
var stream = Erizo.Stream({audio:false, video:true, data: true,
attributes: {name:'myStream', type: 'public'}});
Iniciar y mostrar el Stream
stream.addEventListener('access-accepted', function(event) {
console.log("Access to webcam and microphone granted");
stream.show('myVideoId');
});
stream.addEventListener('access-denied', function(event) {
console.log("Access to webcam and microphone rejected");
});
stream.init();
Javier Cerviño Alvaro Alonso
@jcague @larsonalonso
37. API Cliente - Stream (II)
Usando el Stream
stream.addEventListener('stream-data', function(evt) {
console.log('Received data ', evt.msg, 'from stream ', evt.stream.getID());
}
stream.sendData({text:'Hello world', timestamp:12321312});
var frame;
var url;
var ctx = document.getElementById('myCanvas').getContext('2d');
var img = document.getElementById('myImg');
setInterval (function() {
frame = stream.getVideoFrame();
ctx.putImageData(frame, 0, 0);
url = stream.getVideoFrameURL();
img.src = url;
}, 100);
Javier Cerviño Alvaro Alonso
@jcague @larsonalonso
38. API Cliente - Room (I)
Conectarse a una sala
var room = Erizo.Room({token:'213h8012hwduahd-321ueiwqewq'});
room.addEventListener('room-connected', function(roomEvent) {
console.log('Connected! Streams in the room: ', roomEvent.streams);
}
room.connect();
Publicar mi stream
room.addEventListener('stream-added', function(streamEvent) {
if (localStream.getID() === streamEvent.stream.getID()) {
console.log('Published!');
}
}
room.publish(localStream);
Javier Cerviño Alvaro Alonso
@jcague @larsonalonso
39. API Cliente - Room (II)
Suscribirse a un Stream
room.addEventListener('stream-subscribed', function(streamEvent) {
console.log('Subscribed to stream: ', streamEvent.stream.getID());
}
room.subscribe(stream);
Y además…
room.addEventListener('stream-removed', function(streamEvent) {
console.log('Removed stream: ', streamEvent.stream.getID());
}
room.unpublish(localStream);
room.unsubscribe(stream);
room.disconnect();
Javier Cerviño Alvaro Alonso
@jcague @larsonalonso
40. API Cliente - Events
Yo ERIZO Otros
Clientes localStream.init()
access-accepted
room.connect()
room-connected (streams)
room.subscribe (stream)
stream-subscribed
room.publish (localStream)
stream-added stream-added
room.unpublish (stream)
stream-removed stream-removed
stream.sendData (msg) stream-data
Javier Cerviño Alvaro Alonso
@jcague @larsonalonso
41. ViaS
<html><head><title>Lynckia Example</title> room.addEventListener("stream-added", function (streamEvent) {
<script type="text/javascript" src="http://…/erizo.js"></script> var streams = [];
<script type="text/javascript”> streams.push(streamEvent.stream);
window.onload = function () { subscribeToStreams(streams);
});
var localStream = Erizo.Stream({audio: true, video: true, data: true}); room.addEventListener("stream-removed", function (streamEvent) {
var room = Erizo.Room({token: '213h8012hwduahd-321ueiwqewq'}); var stream = streamEvent.stream;
if (stream.elementID !== undefined) {
localStream.addEventListener("access-accepted", function () {
var element = document.getElementById(stream.elementID);
var subscribeToStreams = function (streams) { document.body.removeChild(element);
for (var index in streams) { }
var stream = streams[index]; });
if (localStream.getID() !== stream.getID())
room.subscribe(stream);
} room.connect();
}; localStream.show("myVideo");
room.addEventListener("room-connected", function (roomEvent) { });
room.publish(localStream);
subscribeToStreams(roomEvent.streams);
localStream.init();
});
};
room.addEventListener("stream-subscribed", function(streamEvent) { </head>
var stream = streamEvent.stream; </script>
<body>
var div = document.createElement('div');
div.setAttribute("style", "width: 320px; height: 240px;"); <div id="myVideo" style="width:320px; height: 240px;”></div>
div.setAttribute("id", "test" + stream.getID()); </body>
document.body.appendChild(div); </html>
stream.show("test" + stream.getID());
}); Javier Cerviño Alvaro Alonso
@jcague @larsonalonso