AvanzaCast/docs/portal_livekit.md

10 KiB

🛠️ 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:

    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>.

    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 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:

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.

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):

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).