Codelab de Firebase y WebRTC

1. Introducción

En este codelab, aprenderás a compilar una aplicación de videochat simple usando la API de WebRTC en tu navegador y Cloud Firestore para la señalización. El app de Google se llama FirebaseRTC y funciona como un ejemplo sencillo que te enseñará los conceptos básicos de la creación de aplicaciones habilitadas para WebRTC.

Qué aprenderás

  • Iniciar una videollamada en una aplicación web con WebRTC
  • Realiza una señal a la parte remota con Cloud Firestore

Requisitos

Antes de comenzar este codelab, asegúrate de haber instalado lo siguiente:

  • npm que, por lo general, viene con Node.js: se recomienda Node LTS

2. Crea y configura un proyecto de Firebase

Crea un proyecto de Firebase

  1. En Firebase console, haz clic en Agregar Luego, asigna el nombre FirebaseRTC al proyecto de Firebase.

Recuerda el ID del proyecto de Firebase.

  1. Haz clic en Crear proyecto.

La aplicación que compilará usa dos servicios de Firebase disponibles en la Web:

  • Cloud Firestore para guardar datos estructurados en la nube y obtener una notificación cuando se actualizan los datos
  • Firebase Hosting, para alojar y entregar tus elementos estáticos

Para este codelab específico, ya configuraste Firebase Hosting en el proyecto que clonarás. Sin embargo, en el caso de Cloud Firestore, te guiaremos en la configuración y habilitación de los servicios usando Firebase console.

Cómo habilitar Cloud Firestore

La app usa Cloud Firestore para guardar los mensajes de chat y recibir chats nuevos. mensajes nuevos.

Deberás habilitar Cloud Firestore:

  1. En la sección Desarrollar del menú de Firebase console, haz clic en Base de datos.
  2. Haz clic en Crear base de datos en el panel de Cloud Firestore.
  3. Selecciona la opción Comenzar en modo de prueba y, luego, haz clic en Habilitar después de leer el sobre las reglas de seguridad.

El modo de prueba garantiza que puedas escribir con libertad en la base de datos durante el desarrollo. Más adelante en este codelab, haremos que nuestra base de datos sea más segura.

3. Obtén el código de muestra

Clona el repositorio de GitHub a partir de la línea de comandos:

git clone https://github.com/webrtc/FirebaseRTC

El código de muestra se debería haber clonado en el directorio FirebaseRTC. Asegúrate de que tu línea de comandos se ejecute desde este directorio a partir de ahora:

cd FirebaseRTC

Cómo importar la app de inicio

Abre los archivos de FirebaseRTC en el editor y cámbialos según las siguientes opciones: las siguientes instrucciones. Este directorio contiene el código de inicio de la codelab que consiste en una app de WebRTC que aún no funciona. Lo haremos en todo este codelab.

4. Instala la interfaz de línea de comandos de Firebase

La interfaz de línea de comandos (CLI) de Firebase te permite entregar tu app web de forma local y, luego, implementarás tu app web en Firebase Hosting.

  1. Ejecuta el siguiente comando npm para instalar la CLI: sh npm -g install firebase-tools
  1. Ejecuta el siguiente comando para verificar que la CLI se haya instalado de forma correcta. : sh firebase --version

Asegúrate de que la versión de Firebase CLI sea 6.7.1 o posterior.

  1. Ejecuta el siguiente comando para autorizar Firebase CLI: sh firebase login

Configuraste la plantilla de la aplicación web para extraer la configuración de tu app para Firebase. Hosting desde el directorio local y los archivos de tu app Pero, para hacerlo, necesitas asociar la app con el proyecto de Firebase.

  1. Ejecuta el siguiente comando para asociar tu app con tu proyecto de Firebase: : sh firebase use --add

  2. Cuando se te solicite, selecciona el ID de tu proyecto y, luego, asigna una alias.

Un alias es útil si tienes varios entornos (producción, etapa de pruebas, etcétera). Sin embargo, para este codelab, solo usaremos el alias de default.

  1. Sigue las instrucciones restantes en tu línea de comandos.

5. Ejecuta el servidor local

Estás listo para comenzar a trabajar en nuestra aplicación. Ejecutemos la app localmente.

  1. Ejecuta el siguiente comando de Firebase CLI: sh firebase serve --only hosting

  2. Tu línea de comandos debería mostrar la siguiente respuesta: hosting: Local server: http://localhost:5000

Usamos el emulador de Firebase Hosting para entregar la app de manera local. La app web ahora debería estar disponible en http://localhost:5000.

  1. Abre tu app en http://localhost:5000.

Deberías ver tu copia de FirebaseRTC que se conectó a tu proyecto de Firebase.

La app se conectó automáticamente a tu proyecto de Firebase.

6. Creando una nueva habitación

En esta aplicación, cada sesión de videochat se llama sala. Un usuario puede crear una nueva sala haciendo clic en un botón en su aplicación. Esto generará un ID que el grupo remoto pueda usar para unirse a la misma habitación. El ID se usa como clave en Cloud Firestore para cada sala.

Cada habitación contendrá la RTCSessionDescriptions de la oferta y la de la empresa, así como dos colecciones separadas con candidatos de ICE de cada parte.

Tu primera tarea es implementar el código faltante para crear una nueva habitación con la oferta inicial de la persona que llama. Abre public/app.js, busca el comentario // Add code for creating a room here y agrega el siguiente código:

const offer = await peerConnection.createOffer();
await peerConnection.setLocalDescription(offer);

const roomWithOffer = {
    offer: {
        type: offer.type,
        sdp: offer.sdp
    }
}
const roomRef = await db.collection('rooms').add(roomWithOffer);
const roomId = roomRef.id;
document.querySelector('#currentRoom').innerText = `Current room is ${roomId} - You are the caller!`

La primera línea crea un elemento RTCSessionDescription que representará la oferta. del emisor. Esto se establece como la descripción local y, por último, se escribe al nuevo objeto Room en Cloud Firestore.

A continuación, detectaremos los cambios en la base de datos y detectaremos cuando una respuesta de se agregó el destinatario.

roomRef.onSnapshot(async snapshot -> {
    console.log('Got updated room:', snapshot.data());
    const data = snapshot.data();
    if (!peerConnection.currentRemoteDescription && data.answer) {
        console.log('Set remote description: ', data.answer);
        const answer = new RTCSessionDescription(data.answer)
        await peerConnection.setRemoteDescription(answer);
    }
});

Esto esperará hasta que el destinatario escriba el RTCSessionDescription para el responder y establecer eso como la descripción remota del emisor RTCPeerConnection

7. Uniéndose a una sala

El siguiente paso es implementar la lógica para unirse a una sala existente. El usuario Para ello, debe hacer clic en el botón Unirse a la sala y escribir el ID de la sala. para unirse. Tu tarea aquí es implementar la creación del RTCSessionDescription para obtener la respuesta y actualizar la sala en la base de datos según corresponda.

const offer = roomSnapshot.data().offer;
await peerConnection.setRemoteDescription(offer);
const answer = await peerConnection.createAnswer();
await peerConnection.setLocalDescription(answer);

const roomWithAnswer = {
    answer: {
        type: answer.type,
        sdp: answer.sdp
    }
}
await roomRef.update(roomWithAnswer);

En el código anterior, comenzamos por extraer la oferta del emisor y crear Un objeto RTCSessionDescription que configuramos como la descripción remota A continuación, creamos la respuesta, establecerla como la descripción local y actualizar la base de datos. La actualización de la base de datos activará la devolución de llamada onSnapshot en el emisor, que A su vez, configurará la descripción del control remoto en función de la respuesta del destinatario. De esta manera, se completa el intercambio de los objetos RTCSessionDescription entre los llamador y el destinatario.

8. Recopilar candidatos de ICE

Antes de que el emisor y el destinatario se puedan conectar, también deben Intercambiar candidatos de ICE que le indican a WebRTC cómo conectarse al par remoto Tu próxima tarea es implementar el código que escucha a los candidatos de ICE y agrega a una colección de la base de datos. Busca la función collectIceCandidates y agrega el siguiente código:

async function collectIceCandidates(roomRef, peerConnection,
                                    localName, remoteName) {
    const candidatesCollection = roomRef.collection(localName);

    peerConnection.addEventListener('icecandidate', event -> {
        if (event.candidate) {
            const json = event.candidate.toJSON();
            candidatesCollection.add(json);
        }
    });

    roomRef.collection(remoteName).onSnapshot(snapshot -> {
        snapshot.docChanges().forEach(change -> {
            if (change.type === "added") {
                const candidate = new RTCIceCandidate(change.doc.data());
                peerConnection.addIceCandidate(candidate);
            }
        });
    })
}

Esta función realiza dos acciones. Recopila candidatos de ICE de la API de WebRTC y los agrega a la base de datos y escucha a los candidatos de ICE agregados desde el recurso remoto y los agrega a su instancia de RTCPeerConnection. Es importante y detecta los cambios en la base de datos para filtrar los cambios que no se agreguen ya que, de lo contrario, habríamos agregado el mismo conjunto de candidatos de ICE una y otra vez de nuevo.

9. Conclusión

En este codelab, aprendiste a implementar la señalización para WebRTC con Cloud Firestore, además de cómo usarlo para crear un videochat simple y mantener la integridad de su aplicación.

Para obtener más información, visita los siguientes recursos:

  1. Código fuente de FirebaseRTC
  2. Muestras de WebRTC
  3. Cloud Firestore