AvanzaCast/docs/portal_livekit.md

216 lines
10 KiB
Markdown

## 🛠️ Integración de LiveKit en Next.js con Componentes y Estilo Similar a StreamYard
Para lograr una interfaz similar a la captura de StreamYard en tu proyecto **Next.js** con **Vite** (aunque Next.js ya tiene su propio *bundler*, si usas Vite para otras partes o pruebas, los componentes de LiveKit para React son la clave), la mejor estrategia es utilizar la librería oficial de **LiveKit React Components** y luego aplicar estilos para simular la disposición.
### 1\. ⚙️ Configuración e Instalación
Aunque Next.js no usa Vite para el *bundling* principal, la integración de las librerías sigue los mismos pasos que cualquier aplicación React:
* **Instala el SDK y los Componentes de React:**
```bash
npm install livekit-client @livekit/components-react @livekit/components-styles livekit-server-sdk
# O usa yarn/pnpm:
# yarn add livekit-client @livekit/components-react @livekit/components-styles livekit-server-sdk
```
* `livekit-client`: El SDK principal para la conectividad WebRTC.
* `@livekit/components-react`: Componentes de UI preconstruidos (la base para la interfaz).
* `@livekit/components-styles`: Estilos base para los componentes.
* `livekit-server-sdk`: Necesario para generar los **tokens de acceso** en tu API de Next.js.
* **Generación de Tokens (Backend):**
Crea una **API Route** en Next.js (por ejemplo, en `/app/api/token/route.ts` para Next.js 13+) que use `livekit-server-sdk` para generar un token de acceso (JWT). Este token es necesario para que el cliente se conecte a la sala.
> **Nota:** Necesitarás tu `LIVEKIT_API_KEY`, `LIVEKIT_API_SECRET` y `LIVEKIT_URL` configurados en tu archivo `.env.local`.
### 2\. 🏗️ Estructura de Componentes de LiveKit
La interfaz de StreamYard que muestras se puede replicar usando una combinación de componentes de LiveKit y **estilos CSS/Tailwind** para el diseño de la cuadrícula.
1. **Contenedor Principal de la Sala:**
Envuelve tu aplicación de video en el componente `<LiveKitRoom>`.
```tsx
import '@livekit/components-styles';
import { LiveKitRoom, VideoConference } from '@livekit/components-react';
export default function MiSala({ token, serverUrl }) {
return (
<LiveKitRoom
token={token}
serverUrl={serverUrl}
connect={true}
data-lk-theme="default" // Aplica el tema base
>
{/* Aquí van tus componentes personalizados */}
<VideoConference />
</LiveKitRoom>
);
}
```
2. **Paneles y Diseño (Simulación de la Interfaz):**
La clave para simular la interfaz es usar CSS Grid o Flexbox en tu página de Next.js para colocar los componentes en las áreas que se ven en la captura:
| Área en StreamYard (Captura) | Componente de LiveKit o Custom | Descripción |
| :--- | :--- | :--- |
| **Escenas/Mis Escenas (Izquierda)** | **Custom React Component** | Un componente personalizado de Next.js para gestionar escenas, **fuera** de LiveKitRoom, pero que interactúa con el estado de la sala (por ejemplo, publicando/despublicando pistas o cambiando el *layout*). |
| **Vídeo Central (720p)** | **GridLayout / FocusLayout** | Usa componentes de *Layout* de LiveKit, como `<GridLayout>` o `<FocusLayout>` para renderizar la vista principal de los participantes. |
| **Controles (Micrófono, Cámara, etc.)** | **ControlBar / TrackToggle** | El componente `<ControlBar>` de LiveKit es ideal para la barra de control inferior, ya que incluye botones listos para Mute/Cámara/Pantalla Compartida. |
| **Participantes (Cesar Mendivil)** | **ParticipantTile** | Puedes usar `<ParticipantLoop>` para iterar sobre los participantes y renderizar un `<ParticipantTile>` para cada uno en la vista inferior o principal. |
| **Comentarios (Derecha)** | **Chat** | El componente `<Chat>` de LiveKit proporciona una funcionalidad de chat lista para usar que se ajusta a la sección de "Comentarios". |
### 3\. ✨ Estilizado y Componentes Personalizados
* **Estilos:** Importa los estilos base de LiveKit (`import '@livekit/components-styles';`) y utiliza **CSS Modules** o **Tailwind CSS** (muy común en Next.js) para crear el diseño de cuadrícula principal y los estilos específicos (bordes, fondos, etc.) que se asemejan a StreamYard. Utiliza *slots* o envoltorios personalizados alrededor de los componentes de LiveKit si necesitas un estilo muy específico que no se puede lograr con la personalización de LiveKit.
* **Vite:** Si estás usando Vite en paralelo para el frontend, la instalación y el uso de los componentes de React son idénticos.
Aquí tienes un video que muestra cómo hacer una aplicación de videollamadas con Next.js y LiveKit.
[Video Call Application with Next js and LiveKit | 2024](https://www.youtube.com/watch?v=-dfLbXOAoa8) es un tutorial que te guiará a través de la creación de una aplicación de videollamadas con Next.js y LiveKit.
http://googleusercontent.com/youtube_content/0
## 🔑 Generación de Tokens con `livekit-server-sdk`
Para generar un token de acceso con `livekit-server-sdk` en tu backend (como en una API Route de Next.js), necesitas seguir tres pasos clave: configurar el SDK, definir la identidad del usuario y generar el token con los permisos (roles) adecuados.
Aquí te muestro un ejemplo completo en TypeScript/JavaScript:
### 1\. 🛠️ Instalación y Configuración
Asegúrate de tener el SDK instalado:
```bash
npm install livekit-server-sdk
```
Y que tus credenciales estén configuradas (usualmente en variables de entorno):
* **`LIVEKIT_API_KEY`**
* **`LIVEKIT_API_SECRET`**
* **`LIVEKIT_URL`** (la URL de tu servidor LiveKit, e.g., `wss://misuperapp.livekit.cloud`)
-----
### 2\. 📝 Ejemplo de Código para Generar un Token
Utiliza la clase **`AccessToken`** para crear un nuevo token, incluyendo los permisos para la sala.
```typescript
import { AccessToken, RoomServiceClient } from 'livekit-server-sdk';
import type { VideoGrant } from 'livekit-server-sdk';
// ----------------------------------------------------
// 1. Obtén las credenciales de tus variables de entorno
// ----------------------------------------------------
const apiKey = process.env.LIVEKIT_API_KEY;
const apiSecret = process.env.LIVEKIT_API_SECRET;
// const livekitUrl = process.env.LIVEKIT_URL; // Solo es necesaria si usas RoomServiceClient
if (!apiKey || !apiSecret) {
throw new Error('LIVEKIT_API_KEY y LIVEKIT_API_SECRET deben estar configuradas.');
}
/**
* Genera un token de acceso para un usuario específico en una sala.
* @param roomName El nombre de la sala a la que se conectará el usuario.
* @param identity La identidad única del usuario (e.g., ID de usuario o nombre de usuario).
* @param canPublish Permiso para publicar video/audio/pantalla (típico de un participante).
* @param canSubscribe Permiso para ver/escuchar a otros participantes (siempre debe ser true).
* @param roomJoin Permiso para unirse a la sala.
* @returns El token JWT generado (string).
*/
export function generateLiveKitToken(
roomName: string,
identity: string,
canPublish: boolean,
isModerator: boolean = false,
): string {
// ----------------------------------------------------
// 2. Crea una instancia de AccessToken
// ----------------------------------------------------
const at = new AccessToken(apiKey!, apiSecret!, {
identity: identity,
// (Opcional) Nombre del usuario que se mostrará en la UI
name: identity,
// (Opcional) Define un tiempo de expiración
ttl: '10m',
});
// ----------------------------------------------------
// 3. Define los permisos (VideoGrant)
// ----------------------------------------------------
const grant: VideoGrant = {
roomJoin: true, // Permitir unirse a la sala
room: roomName, // El nombre de la sala específica
// Permisos de publicación/suscripción
canPublish: canPublish, // Permite publicar audio/video/pantalla
canSubscribe: true, // Permite recibir pistas de otros
// (Opcional) Permisos avanzados para moderadores
canUpdate: isModerator, // Permite actualizar la sala (mutear a otros, etc.)
roomAdmin: isModerator, // Permisos de administrador de sala
canPublishSources: ['camera', 'microphone', 'screen'], // Fuentes permitidas
};
at.addGrant(grant);
// ----------------------------------------------------
// 4. To string: genera el token JWT
// ----------------------------------------------------
const token = at.toJwt();
console.log(`Token generado para ${identity} en sala ${roomName}:`, token);
return token;
}
```
-----
### 3\. 🌐 Uso Típico en Next.js (API Route)
En una API Route de Next.js (`/api/livekit/token`):
```typescript
import { NextRequest, NextResponse } from 'next/server';
import { generateLiveKitToken } from './utils'; // Asume que el código anterior está en 'utils'
export async function POST(req: NextRequest) {
try {
const { roomName, identity, isPublisher } = await req.json();
if (!roomName || !identity) {
return NextResponse.json({ error: 'Faltan parámetros: roomName e identity' }, { status: 400 });
}
// Un publicador tiene 'canPublish: true', un espectador tendría 'canPublish: false'
const token = generateLiveKitToken(roomName, identity, isPublisher);
return NextResponse.json({ token }, { status: 200 });
} catch (error) {
console.error('Error generando token:', error);
return NextResponse.json({ error: 'Error interno del servidor' }, { status: 500 });
}
}
```
### Variables de entorno útiles
Además de las variables necesarias para la generación de tokens (`LIVEKIT_API_KEY`, `LIVEKIT_API_SECRET`, `LIVEKIT_URL`), el paquete del Broadcast Panel expone una variable específica para controlar un "preflight" que provoca el prompt de permisos de cámara/micrófono antes de intentar conectar al estudio.
- `VITE_STUDIO_PREFLIGHT` (opcional): controla si se ejecuta un preflight que llama a `navigator.mediaDevices.getUserMedia` para forzar el prompt de permisos antes de la negociación WebRTC.
- Valores válidos: `1` / `true` (habilitado por defecto), `0` / `false` (deshabilitado).
- Uso típico: en desarrollo puedes dejarlo habilitado para asegurar que el navegador solicite permisos al entrar al estudio; en entornos de pruebas automáticas o cuando no quieres el prompt automático, pon `VITE_STUDIO_PREFLIGHT=0`.
Hemos añadido un ejemplo de archivo de entorno en:
- `packages/broadcast-panel/.env.example`
que incluye `VITE_STUDIO_PREFLIGHT=1` y otras variables de ejemplo que el paquete puede leer (p. ej. `VITE_BACKEND_API_URL`, `VITE_BACKEND_TOKENS_URL`, `VITE_BROADCASTPANEL_URL`, `VITE_LIVEKIT_WS_URL`).