## 🛠️ 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 ``. ```tsx import '@livekit/components-styles'; import { LiveKitRoom, VideoConference } from '@livekit/components-react'; export default function MiSala({ token, serverUrl }) { return ( {/* Aquí van tus componentes personalizados */} ); } ``` 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 `` o `` para renderizar la vista principal de los participantes. | | **Controles (Micrófono, Cámara, etc.)** | **ControlBar / TrackToggle** | El componente `` 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 `` para iterar sobre los participantes y renderizar un `` para cada uno en la vista inferior o principal. | | **Comentarios (Derecha)** | **Chat** | El componente `` 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`).