npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

liondrm-videoplayer

v1.2.13

Published

Custom video player with automatic DRM detection based on Video.js and videojs-contrib-eme - Zero configuration, just install and use

Readme

LionDRM Videoplayer

🦁 Reproductor de video con DRM automático - Cero configuración, solo instala y usa

npm version TypeScript Vue.js

✨ Características

  • 🎯 Zero Configuration: Instala y funciona - sin archivos extra, sin configuración compleja
  • 🔒 DRM Automático: Detecta el navegador y configura el DRM correcto automáticamente
    • Widevine (Chrome, Firefox, Edge, Opera)
    • FairPlay (Safari)
    • PlayReady (Edge Legacy)
  • 🎬 Detección Inteligente: Sabe si tu video necesita DRM o no
  • 💪 TypeScript First: Tipos perfectos incluidos, cero configuración
  • Vue.js Optimizado: Funciona perfecto con Vue 3 Composition API y Vue 2
  • 📦 Todo Incluido: Video.js y videojs-contrib-eme empaquetados dentro

📦 Instalación

npm install liondrm-videoplayer

¡Eso es todo! No necesitas instalar nada más.

🚀 Uso Rápido

HTML Básico

<!DOCTYPE html>
<html>
<head>
  <link href="node_modules/liondrm-videoplayer/dist/liondrm-videoplayer.css" rel="stylesheet">
</head>
<body>
  <video id="my-video" class="video-js" controls></video>
  
  <script type="module">
    import { LionDRMPlayer } from 'liondrm-videoplayer';
    
    const player = new LionDRMPlayer('my-video', {
      sources: [{
        src: 'https://example.com/video.mp4',
        type: 'video/mp4'
      }]
    });
  </script>
</body>
</html>

Vue 3 (Composition API + TypeScript)

<template>
  <div class="video-container">
    <video ref="videoElement" class="video-js" controls></video>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount } from 'vue'
import { LionDRMPlayer } from 'liondrm-videoplayer'
import 'liondrm-videoplayer/css'

const videoElement = ref<HTMLVideoElement | null>(null)
const player = ref<LionDRMPlayer | null>(null)

onMounted(() => {
  if (!videoElement.value) return
  
  player.value = new LionDRMPlayer(videoElement.value, {
    sources: [{
      src: 'https://example.com/video.mp4',
      type: 'video/mp4'
    }],
    controls: true,
    fluid: true
  })
})

onBeforeUnmount(() => {
  player.value?.dispose()
})
</script>

Vue 3 con DRM

<template>
  <div class="video-container">
    <video ref="videoElement" class="video-js" controls></video>
    <div v-if="drmInfo">
      <p>🔒 DRM: {{ drmInfo }}</p>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount } from 'vue'
import { LionDRMPlayer } from 'liondrm-videoplayer'
import 'liondrm-videoplayer/css'

const videoElement = ref<HTMLVideoElement | null>(null)
const player = ref<LionDRMPlayer | null>(null)
const drmInfo = ref<string | null>(null)

onMounted(() => {
  if (!videoElement.value) return
  
  player.value = new LionDRMPlayer(videoElement.value, {
    sources: [{
      src: 'https://example.com/video.mpd',
      type: 'application/dash+xml'
    }],
    
    // Configuración DRM (solo si tu video está encriptado)
    drm: {
      widevine: {
        licenseUrl: 'https://example.com/license'
      },
      fairplay: {
        certificateUrl: 'https://example.com/cert',
        licenseUrl: 'https://example.com/license'
      }
    },
    
    // Callbacks opcionales
    onDRMDetected: (drmType) => {
      drmInfo.value = drmType
      console.log('🔒 DRM detectado:', drmType)
    },
    
    onUnencryptedContent: () => {
      console.log('🔓 Video sin DRM')
    }
  })
})

onBeforeUnmount(() => {
  player.value?.dispose()
})
</script>

🎯 API Simple

Constructor

const player = new LionDRMPlayer(element, options)

Opciones Principales

interface LionDRMPlayerOptions {
  // Fuentes de video
  sources: Array<{
    src: string
    type: string
  }>
  
  // Opciones de Video.js
  controls?: boolean        // default: true
  autoplay?: boolean        // default: false
  fluid?: boolean          // default: true
  poster?: string
  
  // DRM (solo si tu video está encriptado)
  drm?: {
    widevine?: {
      licenseUrl: string
      headers?: Record<string, string>
    }
    fairplay?: {
      certificateUrl: string
      licenseUrl: string
    }
    playready?: {
      licenseUrl: string
    }
  }
  
  // 🎨 Tema personalizado (NUEVO en v1.2.0)
  theme?: 'dark' | 'light' | 'red' | 'green' | 'orange' | {
    'primary-color'?: string
    'secondary-color'?: string
    'accent-color'?: string
    'text-color'?: string
    'control-bg'?: string
  }
  
  // Callbacks
  onDRMDetected?: (drmType: string) => void
  onUnencryptedContent?: () => void
  onReady?: (player: LionDRMPlayer) => void
}

Métodos

// Controles básicos
player.play()              // Reproducir
player.pause()             // Pausar
player.dispose()           // Destruir

// Información
player.getDRMType()        // Obtener tipo de DRM
player.isContentEncrypted() // ¿Está encriptado?
player.getBrowserInfo()    // Info del navegador

// Cambiar video
player.changeSource({
  src: 'new-video.mp4',
  type: 'video/mp4'
})

// 🎨 Personalización (NUEVO en v1.2.0)
player.applyTheme('red')   // Aplicar tema predefinido
player.applyTheme({        // O colores personalizados
  'primary-color': '#ff6b6b',
  'secondary-color': '#4ecdc4'
})

🎨 Personalización de Temas (NUEVO en v1.2.0)

LionDRM Player incluye un sistema de temas completamente personalizable.

Importar CSS con Tema

<!-- CSS base -->
<link href="node_modules/liondrm-videoplayer/dist/liondrm-videoplayer.css" rel="stylesheet">
<!-- Tema personalizado -->
<link href="node_modules/liondrm-videoplayer/dist/liondrm-videoplayer-theme.css" rel="stylesheet">

O en JavaScript/TypeScript:

import 'liondrm-videoplayer/css'
import 'liondrm-videoplayer/theme'

Temas Predefinidos

// Tema oscuro (por defecto)
const player = new LionDRMPlayer('video', {
  sources: [{ src: 'video.mp4', type: 'video/mp4' }],
  theme: 'dark'
})

// Tema claro
const player = new LionDRMPlayer('video', {
  theme: 'light'
})

// Tema rojo
const player = new LionDRMPlayer('video', {
  theme: 'red'
})

// Otros temas: 'green', 'orange'

Colores Personalizados

const player = new LionDRMPlayer('video', {
  sources: [{ src: 'video.mp4', type: 'video/mp4' }],
  theme: {
    'primary-color': '#ff6b6b',      // Color principal
    'secondary-color': '#4ecdc4',    // Color secundario
    'accent-color': '#ffe66d',       // Color de acento
    'text-color': '#ffffff',         // Color de texto
    'control-bg': 'rgba(0,0,0,0.8)' // Fondo de controles
  }
})

Cambiar Tema Dinámicamente

// Cambiar a tema predefinido
player.applyTheme('green')

// Cambiar a colores personalizados
player.applyTheme({
  'primary-color': '#8e44ad',
  'secondary-color': '#9b59b6',
  'accent-color': '#bb8fce'
})

Variables CSS Disponibles

--liondrm-primary-color      /* Color principal del tema */
--liondrm-secondary-color    /* Color secundario */
--liondrm-accent-color       /* Color de acento */
--liondrm-text-color         /* Color del texto */
--liondrm-bg-color           /* Color de fondo */
--liondrm-control-bg         /* Fondo de la barra de controles */
--liondrm-hover-color        /* Color al pasar el mouse */
--liondrm-progress-color     /* Color de la barra de progreso */

Ejemplo en Vue 3

<template>
  <div>
    <select v-model="selectedTheme" @change="changeTheme">
      <option value="dark">Oscuro</option>
      <option value="light">Claro</option>
      <option value="red">Rojo</option>
      <option value="green">Verde</option>
      <option value="orange">Naranja</option>
    </select>
    
    <video ref="videoElement" class="video-js" controls></video>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { LionDRMPlayer } from 'liondrm-videoplayer'
import 'liondrm-videoplayer/css'
import 'liondrm-videoplayer/theme'

const videoElement = ref<HTMLVideoElement | null>(null)
const player = ref<LionDRMPlayer | null>(null)
const selectedTheme = ref('dark')

onMounted(() => {
  if (!videoElement.value) return
  
  player.value = new LionDRMPlayer(videoElement.value, {
    sources: [{ src: 'video.mp4', type: 'video/mp4' }],
    theme: selectedTheme.value
  })
})

const changeTheme = () => {
  player.value?.applyTheme(selectedTheme.value)
}
</script>

Demo Interactivo

Prueba el sistema de temas en: examples/theme-example.html

npm run serve
# Abre http://localhost:8080/examples/theme-example.html

📖 Ejemplos Completos

Ejemplo 1: Video Simple (Sin DRM)

import { LionDRMPlayer } from 'liondrm-videoplayer'

const player = new LionDRMPlayer('my-video', {
  sources: [{
    src: 'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4',
    type: 'video/mp4'
  }]
})

Ejemplo 2: Video con DRM (DASH + Widevine)

import { LionDRMPlayer } from 'liondrm-videoplayer'

const player = new LionDRMPlayer('my-video', {
  sources: [{
    src: 'https://example.com/protected-video.mpd',
    type: 'application/dash+xml'
  }],
  drm: {
    widevine: {
      licenseUrl: 'https://example.com/widevine/license',
      headers: {
        'Authorization': 'Bearer YOUR_TOKEN'
      }
    }
  },
  onDRMDetected: (drmType) => {
    console.log('✅ DRM configurado:', drmType)
  }
})

Ejemplo 3: Multi-DRM (Widevine + FairPlay)

const player = new LionDRMPlayer('my-video', {
  sources: [{
    src: 'https://example.com/video.mpd',
    type: 'application/dash+xml'
  }],
  drm: {
    widevine: {
      licenseUrl: 'https://your-server.com/widevine/license'
    },
    fairplay: {
      certificateUrl: 'https://your-server.com/fairplay/cert',
      licenseUrl: 'https://your-server.com/fairplay/license'
    },
    playready: {
      licenseUrl: 'https://your-server.com/playready/license'
    }
  }
})

🎨 Composable para Vue 3

Crea un composable reutilizable:

// composables/useLionDRMPlayer.ts
import { ref, onMounted, onBeforeUnmount, type Ref } from 'vue'
import { LionDRMPlayer, type LionDRMPlayerOptions } from 'liondrm-videoplayer'

export function useLionDRMPlayer(
  elementRef: Ref<HTMLVideoElement | null>,
  options: LionDRMPlayerOptions
) {
  const player = ref<LionDRMPlayer | null>(null)
  const isReady = ref(false)
  const isEncrypted = ref(false)
  const drmType = ref<string | null>(null)
  
  onMounted(() => {
    if (!elementRef.value) return
    
    player.value = new LionDRMPlayer(elementRef.value, {
      ...options,
      onReady: (p) => {
        isReady.value = true
        isEncrypted.value = p.isContentEncrypted()
        drmType.value = p.getDRMType()
        options.onReady?.(p)
      }
    })
  })
  
  onBeforeUnmount(() => {
    player.value?.dispose()
  })
  
  return {
    player,
    isReady,
    isEncrypted,
    drmType
  }
}

Uso del composable:

<template>
  <div>
    <video ref="videoEl" class="video-js" controls></video>
    <p v-if="isEncrypted">🔒 Protegido con {{ drmType }}</p>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { useLionDRMPlayer } from '@/composables/useLionDRMPlayer'
import 'liondrm-videoplayer/css'

const videoEl = ref<HTMLVideoElement | null>(null)

const { isReady, isEncrypted, drmType } = useLionDRMPlayer(videoEl, {
  sources: [{
    src: 'https://example.com/video.mp4',
    type: 'video/mp4'
  }]
})
</script>

🔍 ¿Cómo Funciona la Detección Automática?

El reproductor detecta automáticamente:

  1. Navegador: Chrome, Firefox, Safari, Edge, Opera
  2. DRM Compatible: Widevine, FairPlay, PlayReady
  3. Contenido Encriptado: Analiza el formato, tipo MIME, y configuración
  4. Optimización: Si no hay DRM, reproduce directo sin overhead

📝 TypeScript

Los tipos están completamente incluidos y funcionan automáticamente:

import { LionDRMPlayer, type LionDRMPlayerOptions, type BrowserDetectionResult } from 'liondrm-videoplayer'

// ✅ Autocompletado perfecto
const options: LionDRMPlayerOptions = {
  sources: [{ src: '...', type: 'video/mp4' }],
  controls: true,
  fluid: true
}

const player = new LionDRMPlayer('video', options)

// ✅ Métodos tipados
const drmType: string | null = player.getDRMType()
const browserInfo: BrowserDetectionResult = player.getBrowserInfo()

No necesitas:

  • ❌ Crear archivos global.d.ts
  • ❌ Crear archivos shims-vue.d.ts
  • ❌ Importar video.js manualmente
  • ❌ Configurar tsconfig.json especial

🌐 Navegadores Soportados

| Navegador | DRM | Soporte | |-----------|-----|---------| | Chrome 95+ | Widevine | ✅ | | Firefox 94+ | Widevine | ✅ | | Safari 14+ | FairPlay | ✅ | | Edge 95+ | Widevine | ✅ | | Opera 81+ | Widevine | ✅ |

🛠️ Desarrollo

# Clonar repositorio
git clone https://github.com/tu-usuario/liondrm-videoplayer.git
cd liondrm-videoplayer

# Instalar dependencias
npm install

# Desarrollo (watch mode)
npm run dev

# Build
npm run build

# Servidor de pruebas
npm run serve

📄 Licencia

MIT © DevLeon


❓ FAQ

¿Necesito instalar video.js por separado?

No. Todo está incluido en el paquete.

¿Funciona con TypeScript sin configuración?

Sí. Los tipos están incluidos y funcionan automáticamente.

¿Funciona con Vue 3?

Sí. Optimizado para Vue 3 Composition API y totalmente compatible con Vue 2.

¿Puedo usar videos sin DRM?

Sí. El reproductor detecta automáticamente si el video necesita DRM o no.

¿Necesito crear archivos global.d.ts?

No. La librería maneja todo internamente.


¿Problemas? Abre un issue en GitHub

Características

  • 🦁 Detección Automática de DRM: Detecta automáticamente el navegador y selecciona el sistema DRM apropiado
  • Detección de Contenido Encriptado: Identifica automáticamente si el contenido requiere DRM o no
  • �📺 Múltiples DRM Soportados:
    • Widevine (Chrome, Firefox, Edge, Opera)
    • FairPlay (Safari en macOS y iOS)
    • PlayReady (Edge Legacy, IE11)
    • ClearKey (Fallback para testing)
  • 🎨 Fácil de Usar: API simple y clara basada en Video.js
  • 🔧 Altamente Configurable: Personaliza configuraciones DRM por navegador
  • 📱 Responsive: Funciona en desktop, móvil y tablets
  • 🎯 Optimizado: Solo aplica DRM cuando el contenido lo requiere

¿Cómo Detecta si el Contenido Está Encriptado?

El reproductor analiza automáticamente:

  1. Configuración DRM: Si proporcionas configuración DRM
  2. Formato de archivo: Extensiones como .mpd, .ism, .m3u8
  3. Tipo MIME: application/dash+xml, application/x-mpegURL, etc.
  4. Parámetros URL: Busca drm=, token=, license, encryption
  5. keySystems: Verifica si las fuentes tienen keySystems definidos

Si detecta que el contenido NO está encriptado, reproduce directamente sin configurar DRM, optimizando el rendimiento.

Navegadores Soportados

| Navegador | DRM | Soporte | |-----------|-----|---------| | Chrome | Widevine | ✅ | | Firefox | Widevine | ✅ | | Safari | FairPlay | ✅ | | Edge (Chromium) | Widevine | ✅ | | Edge (Legacy) | PlayReady | ✅ | | Opera | Widevine | ✅ |

Instalación

NPM

npm install liondrm-videoplayer

Desde el Repositorio (GitHub)

# Clonar el repositorio
git clone https://github.com/tu-usuario/liondrm-videoplayer.git
cd liondrm-videoplayer

# Instalar dependencias (el build se ejecuta automáticamente)
npm install

# ¡Listo! Los archivos ya están en dist/ y puedes usar el reproductor

Nota: El script postinstall ejecuta automáticamente el build después de instalar las dependencias, por lo que no necesitas ejecutar npm run build manualmente.

CDN (próximamente)

<link href="https://unpkg.com/liondrm-videoplayer/dist/liondrm-videoplayer.css" rel="stylesheet">
<script src="https://unpkg.com/liondrm-videoplayer/dist/liondrm-videoplayer.min.js"></script>

Uso Básico

Contenido Encriptado (con DRM)

<!DOCTYPE html>
<html>
<head>
  <link href="https://unpkg.com/[email protected]/dist/video-js.min.css" rel="stylesheet">
</head>
<body>
  <video id="my-video" class="video-js vjs-default-skin" controls></video>
  
  <!-- Dependencias -->
  <script src="https://unpkg.com/[email protected]/dist/video.min.js"></script>
  <script src="https://unpkg.com/[email protected]/dist/videojs-contrib-eme.min.js"></script>
  
  <!-- LionDRM Player -->
  <script src="dist/liondrm-videoplayer.js"></script>
  
  <script>
    // Acceder a la clase desde el namespace exportado
    const player = new LionDRMPlayer.LionDRMPlayer('my-video', {
      sources: [{
        src: 'https://example.com/video.mpd',  // Contenido DASH encriptado
        type: 'application/dash+xml'
      }],
      drm: {
        widevine: {
          licenseUrl: 'https://example.com/widevine/license'
        },
        fairplay: {
          certificateUrl: 'https://example.com/fairplay/cert',
          licenseUrl: 'https://example.com/fairplay/license'
        }
      },
      onDRMDetected: (drmType) => {
        console.log('🔒 DRM detectado:', drmType);
      }
    });
  </script>
</body>
</html>

Contenido Sin Encriptar (sin DRM)

<!DOCTYPE html>
<html>
<head>
  <link href="https://unpkg.com/[email protected]/dist/video-js.min.css" rel="stylesheet">
</head>
<body>
  <video id="my-video" class="video-js vjs-default-skin" controls></video>
  
  <!-- Dependencias -->
  <script src="https://unpkg.com/[email protected]/dist/video.min.js"></script>
  <script src="https://unpkg.com/[email protected]/dist/videojs-contrib-eme.min.js"></script>
  
  <!-- LionDRM Player -->
  <script src="dist/liondrm-videoplayer.js"></script>
  
  <script>
    const player = new LionDRMPlayer.LionDRMPlayer('my-video', {
      sources: [{
        src: 'https://example.com/video.mp4',  // Video MP4 estándar
        type: 'video/mp4'
      }],
      onUnencryptedContent: () => {
        console.log('🔓 Reproduciendo contenido sin encriptar');
      }
    });
    // No necesitas configurar DRM, el reproductor lo detecta automáticamente
  </script>
</body>
</html>

Configuración Avanzada

const player = new LionDRMPlayer('my-video', {
  sources: [{
    src: 'https://example.com/video.mpd',
    type: 'application/dash+xml'
  }],
  
  // Opciones de Video.js
  controls: true,
  autoplay: false,
  preload: 'auto',
  poster: 'https://example.com/poster.jpg',
  
  // Configuración DRM
  drm: {
    // Widevine (Chrome, Firefox, Edge, Opera)
    widevine: {
      licenseUrl: 'https://example.com/widevine/license',
      headers: {
        'X-Custom-Header': 'value'
      },
      videoRobustness: 'SW_SECURE_CRYPTO',
      audioRobustness: 'SW_SECURE_CRYPTO'
    },
    
    // FairPlay (Safari)
    fairplay: {
      certificateUrl: 'https://example.com/fairplay/cert',
      licenseUrl: 'https://example.com/fairplay/license',
      headers: {
        'X-Custom-Header': 'value'
      }
    },
    
    // PlayReady (Edge Legacy, IE11)
    playready: {
      licenseUrl: 'https://example.com/playready/license',
      headers: {
        'X-Custom-Header': 'value'
      }
    },
    
    // ClearKey (para testing)
    clearkey: {
      licenseUrl: 'https://example.com/clearkey/license'
    }
  },
  
  // Callbacks
  onDRMDetected: (drmType) => {
    console.log('🔒 Contenido encriptado - DRM:', drmType);
  },
  
  onUnencryptedContent: () => {
    console.log('🔓 Contenido sin encriptar - Reproducción directa');
  },
  
  onLicenseError: (error) => {
    console.error('Error de licencia:', error);
  }
});

API del Reproductor

Métodos

  • play() - Iniciar reproducción
  • pause() - Pausar reproducción
  • getDRMType() - Obtener el tipo de DRM detectado
  • getBrowserInfo() - Obtener información del navegador
  • isContentEncrypted() - NUEVO: Verificar si el contenido está encriptado
  • getEncryptionInfo() - NUEVO: Obtener información detallada de encriptación
  • changeSource(source) - Cambiar la fuente de video (re-detecta automáticamente si está encriptado)
  • dispose() - Limpiar y destruir el reproductor

Ejemplos de Nuevos Métodos

// Verificar si el contenido está encriptado
if (player.isContentEncrypted()) {
  console.log('🔒 Este contenido requiere DRM');
} else {
  console.log('🔓 Este contenido es libre');
}

// Obtener información detallada
const info = player.getEncryptionInfo();
console.log(info);
// {
//   isEncrypted: true,
//   drmType: 'widevine',
//   hasDRMConfig: true,
//   browserInfo: {...}
// }

Eventos

player.on('drmdetected', (event) => {
  console.log('DRM detectado:', event.drmType);
});

player.on('licenserequested', (event) => {
  console.log('Licencia solicitada');
});

player.on('licensereceived', (event) => {
  console.log('Licencia recibida');
});

Ejemplos de Uso

Ejemplos de Uso

Ejemplo 1: Mix de Contenido (Encriptado y No Encriptado)

const player = new LionDRMPlayer.LionDRMPlayer('my-video', {
  sources: [{
    src: 'https://example.com/free-video.mp4',
    type: 'video/mp4'
  }],
  
  onUnencryptedContent: () => {
    console.log('Reproduciendo contenido gratuito');
  }
});

// Luego cambiar a contenido premium encriptado
setTimeout(() => {
  player.changeSource({
    src: 'https://example.com/premium-video.mpd',
    type: 'application/dash+xml'
  });
  
  // El reproductor detecta automáticamente que ahora necesita DRM
  if (player.isContentEncrypted()) {
    console.log('Cambiado a contenido premium con DRM');
  }
}, 60000);

Ejemplo 2: Detección Antes de Cargar

const player = new LionDRMPlayer.LionDRMPlayer('my-video', {
  sources: [{
    src: 'https://example.com/video.mpd',
    type: 'application/dash+xml'
  }],
  drm: {
    widevine: { licenseUrl: 'https://example.com/license' }
  }
});

const encInfo = player.getEncryptionInfo();

if (encInfo.isEncrypted && !encInfo.hasDRMConfig) {
  alert('⚠️ Este contenido requiere licencia DRM');
}

🎨 Uso en Vue.js

Nota Importante: Cuando instalas liondrm-videoplayer desde npm, las dependencias video.js y videojs-contrib-eme se instalan automáticamente. No necesitas instalarlas por separado.

Instalación en Proyecto Vue

# ✅ CORRECTO: Solo instala liondrm-videoplayer
npm install liondrm-videoplayer

# ❌ INCORRECTO: No necesitas instalar las dependencias manualmente
# npm install video.js videojs-contrib-eme  # Ya vienen incluidas

¿Qué se instala automáticamente?

  • liondrm-videoplayer (el reproductor)
  • video.js (dependencia, se instala automáticamente)
  • videojs-contrib-eme (dependencia, se instala automáticamente)

Video Sin DRM en Vue 3 (Composition API)

Nota para TypeScript: Si usas TypeScript, crea primero estos archivos:

  • src/types/global.d.ts - Declaraciones globales para window.videojs
  • src/types/shims-vue.d.ts - Declaraciones para módulos .vue

Ver ejemplos completos más abajo.

VideoPlayer.vue

<template>
  <div class="video-player-container">
    <h2>{{ title }}</h2>
    <video
      ref="videoElement"
      class="video-js vjs-default-skin"
      controls
      playsinline
    ></video>
    
    <div v-if="playerInfo" class="player-info">
      <p><strong>Navegador:</strong> {{ playerInfo.browser.name }}</p>
      <p><strong>DRM:</strong> {{ playerInfo.drm.type }}</p>
      <p><strong>Encriptado:</strong> {{ isEncrypted ? '🔒 Sí' : '🔓 No' }}</p>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount } from 'vue';
import videojs from 'video.js';
import 'video.js/dist/video-js.css';
import 'videojs-contrib-eme';
import { LionDRMPlayer, type BrowserDetectionResult } from 'liondrm-videoplayer';

// ✅ CRÍTICO: Registrar Video.js globalmente
if (typeof window !== 'undefined' && !window.videojs) {
  window.videojs = videojs;
}

const props = defineProps({
  title: {
    type: String,
    default: 'Video Player'
  },
  videoUrl: {
    type: String,
    required: true
  },
  videoType: {
    type: String,
    default: 'video/mp4'
  }
});

const emit = defineEmits(['ready', 'error', 'play', 'pause']);

const videoElement = ref(null);
const player = ref(null);
const playerInfo = ref(null);
const isEncrypted = ref(false);

onMounted(() => {
  initPlayer();
});

onBeforeUnmount(() => {
  if (player.value) {
    player.value.dispose();
  }
});

const initPlayer = () => {
  if (!videoElement.value) return;

  try {
    player.value = new LionDRMPlayer(videoElement.value, {
      sources: [{
        src: props.videoUrl,
        type: props.videoType
      }],
      controls: true,
      autoplay: false,
      preload: 'auto',
      fluid: true,
      
      onUnencryptedContent: () => {
        console.log('🔓 Contenido sin DRM');
        isEncrypted.value = false;
      },
      
      onReady: (playerInstance) => {
        playerInfo.value = playerInstance.getBrowserInfo();
        isEncrypted.value = playerInstance.isContentEncrypted();
        emit('ready', playerInstance);
      }
    });

    // Eventos
    player.value.on('play', () => emit('play'));
    player.value.on('pause', () => emit('pause'));
    player.value.on('error', (error) => emit('error', error));
    
  } catch (error) {
    console.error('Error inicializando player:', error);
    emit('error', error);
  }
};
</script>

<style scoped>
.video-player-container {
  max-width: 800px;
  margin: 0 auto;
}

.player-info {
  margin-top: 1rem;
  padding: 1rem;
  background: #f5f5f5;
  border-radius: 8px;
}

.player-info p {
  margin: 0.5rem 0;
}
</style>

Uso del componente (App.vue):

<template>
  <div id="app">
    <h1>🦁 LionDRM Player en Vue</h1>
    
    <VideoPlayer
      title="Video de Prueba"
      video-url="https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"
      video-type="video/mp4"
      @ready="onPlayerReady"
      @play="onPlay"
      @pause="onPause"
    />
  </div>
</template>

<script setup>
import VideoPlayer from './components/VideoPlayer.vue';

const onPlayerReady = (player) => {
  console.log('Player listo:', player);
};

const onPlay = () => {
  console.log('Video reproduciendo');
};

const onPause = () => {
  console.log('Video pausado');
};
</script>

Video Con DRM en Vue 3 (Composition API)

DRMVideoPlayer.vue

<template>
  <div class="drm-video-player">
    <h2>{{ title }}</h2>
    
    <div v-if="loading" class="loading">
      ⏳ Cargando reproductor...
    </div>
    
    <video
      ref="videoElement"
      class="video-js vjs-default-skin vjs-big-play-centered"
      controls
      playsinline
    ></video>
    
    <div v-if="drmInfo" class="drm-info">
      <h3>Información DRM</h3>
      <p><strong>DRM Detectado:</strong> {{ drmInfo.type }}</p>
      <p><strong>Key System:</strong> {{ drmInfo.keySystem }}</p>
      <p><strong>Estado:</strong> {{ licenseStatus }}</p>
    </div>
    
    <div v-if="error" class="error">
      ❌ {{ error }}
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';
import 'video.js/dist/video-js.css';

// Importar desde npm
import { LionDRMPlayer } from 'liondrm-videoplayer';

// O si usas CDN: const LionDRMPlayer = window.LionDRMPlayer?.LionDRMPlayer;

const props = defineProps({
  title: {
    type: String,
    default: 'Video DRM'
  },
  videoUrl: {
    type: String,
    required: true
  },
  videoType: {
    type: String,
    default: 'application/dash+xml'
  },
  drmConfig: {
    type: Object,
    required: true
    // Ejemplo:
    // {
    //   widevine: { licenseUrl: 'https://...' },
    //   fairplay: { certificateUrl: '...', licenseUrl: '...' }
    // }
  }
});

const emit = defineEmits(['ready', 'drmDetected', 'licenseError', 'licenseSuccess']);

const videoElement = ref(null);
const player = ref(null);
const loading = ref(true);
const drmInfo = ref(null);
const licenseStatus = ref('Inicializando...');
const error = ref(null);

onMounted(() => {
  initDRMPlayer();
});

onBeforeUnmount(() => {
  if (player.value) {
    player.value.dispose();
  }
});

const initDRMPlayer = () => {
  if (!videoElement.value) return;

  try {
    player.value = new LionDRMPlayer(videoElement.value, {
      sources: [{
        src: props.videoUrl,
        type: props.videoType
      }],
      controls: true,
      autoplay: false,
      preload: 'auto',
      fluid: true,
      
      // Configuración DRM
      drm: props.drmConfig,
      
      // Callbacks
      onDRMDetected: (drmType, browserInfo) => {
        console.log('🔒 DRM detectado:', drmType);
        drmInfo.value = browserInfo.drm;
        licenseStatus.value = 'DRM detectado';
        emit('drmDetected', { drmType, browserInfo });
      },
      
      onLicenseSuccess: () => {
        console.log('✅ Licencia obtenida');
        licenseStatus.value = '✅ Licencia activa';
        emit('licenseSuccess');
      },
      
      onLicenseError: (err) => {
        console.error('❌ Error de licencia:', err);
        error.value = `Error de licencia: ${err.type || 'desconocido'}`;
        licenseStatus.value = '❌ Error de licencia';
        emit('licenseError', err);
      },
      
      onReady: (playerInstance) => {
        console.log('✅ Player DRM listo');
        loading.value = false;
        emit('ready', playerInstance);
      }
    });
    
  } catch (err) {
    console.error('Error inicializando player DRM:', err);
    error.value = err.message;
    loading.value = false;
  }
};

// Métodos expuestos
defineExpose({
  play: () => player.value?.play(),
  pause: () => player.value?.pause(),
  getPlayer: () => player.value
});
</script>

<style scoped>
.drm-video-player {
  max-width: 900px;
  margin: 0 auto;
  padding: 1rem;
}

.loading {
  text-align: center;
  padding: 2rem;
  font-size: 1.2em;
  color: #667eea;
}

.drm-info {
  margin-top: 1rem;
  padding: 1rem;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: white;
  border-radius: 8px;
}

.drm-info h3 {
  margin-top: 0;
  margin-bottom: 0.5rem;
}

.drm-info p {
  margin: 0.5rem 0;
}

.error {
  margin-top: 1rem;
  padding: 1rem;
  background: #ff4757;
  color: white;
  border-radius: 8px;
}
</style>

Uso con DRM (App.vue):

<template>
  <div id="app">
    <h1>🔒 Reproducción con DRM</h1>
    
    <DRMVideoPlayer
      ref="playerRef"
      title="Video Premium con DRM"
      :video-url="videoConfig.url"
      :video-type="videoConfig.type"
      :drm-config="drmConfig"
      @ready="onPlayerReady"
      @drm-detected="onDRMDetected"
      @license-success="onLicenseSuccess"
      @license-error="onLicenseError"
    />
    
    <div class="controls">
      <button @click="playVideo">▶️ Reproducir</button>
      <button @click="pauseVideo">⏸️ Pausar</button>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import DRMVideoPlayer from './components/DRMVideoPlayer.vue';

const playerRef = ref(null);

const videoConfig = {
  url: 'https://tu-cdn.com/video-protegido.mpd',
  type: 'application/dash+xml'
};

const drmConfig = {
  // Configuración Widevine (Chrome, Firefox, Edge)
  widevine: {
    licenseUrl: 'https://tu-servidor-drm.com/widevine/license',
    headers: {
      'Authorization': 'Bearer tu-token-aqui'
    },
    videoRobustness: 'SW_SECURE_CRYPTO',
    audioRobustness: 'SW_SECURE_CRYPTO'
  },
  
  // Configuración FairPlay (Safari)
  fairplay: {
    certificateUrl: 'https://tu-servidor-drm.com/fairplay/cert',
    licenseUrl: 'https://tu-servidor-drm.com/fairplay/license',
    headers: {
      'Authorization': 'Bearer tu-token-aqui'
    }
  },
  
  // Configuración PlayReady (Edge Legacy)
  playready: {
    licenseUrl: 'https://tu-servidor-drm.com/playready/license'
  }
};

const onPlayerReady = (player) => {
  console.log('✅ Player DRM inicializado:', player);
};

const onDRMDetected = ({ drmType, browserInfo }) => {
  console.log(`🔒 Usando DRM: ${drmType}`);
  console.log('Navegador:', browserInfo.browser.name);
};

const onLicenseSuccess = () => {
  console.log('✅ Licencia DRM obtenida correctamente');
};

const onLicenseError = (error) => {
  console.error('❌ Error obteniendo licencia:', error);
  alert('No se pudo obtener la licencia DRM. Verifica tu configuración.');
};

const playVideo = () => {
  playerRef.value?.play();
};

const pauseVideo = () => {
  playerRef.value?.pause();
};
</script>

<style>
.controls {
  margin-top: 1rem;
  text-align: center;
}

.controls button {
  padding: 0.75rem 1.5rem;
  margin: 0 0.5rem;
  font-size: 1rem;
  border: none;
  border-radius: 8px;
  background: #667eea;
  color: white;
  cursor: pointer;
  transition: all 0.3s;
}

.controls button:hover {
  background: #5568d3;
  transform: translateY(-2px);
}
</style>

Vue 2 (Options API)

VideoPlayer.vue (Vue 2)

<template>
  <div class="video-player">
    <video
      ref="videoElement"
      class="video-js vjs-default-skin"
      controls
    ></video>
  </div>
</template>

<script>
export default {
  name: 'VideoPlayer',
  props: {
    videoUrl: {
      type: String,
      required: true
    },
    videoType: {
      type: String,
      default: 'video/mp4'
    },
    drmConfig: {
      type: Object,
      default: null
    }
  },
  data() {
    return {
      player: null
    };
  },
  mounted() {
    this.initPlayer();
  },
  beforeDestroy() {
    if (this.player) {
      this.player.dispose();
    }
  },
  methods: {
    initPlayer() {
      const LionDRMPlayer = window.LionDRMPlayer?.LionDRMPlayer;
      
      const config = {
        sources: [{
          src: this.videoUrl,
          type: this.videoType
        }],
        controls: true,
        fluid: true,
        
        onReady: (player) => {
          this.$emit('ready', player);
        }
      };
      
      // Agregar config DRM si existe
      if (this.drmConfig) {
        config.drm = this.drmConfig;
        config.onDRMDetected = (drmType) => {
          this.$emit('drm-detected', drmType);
        };
        config.onLicenseSuccess = () => {
          this.$emit('license-success');
        };
        config.onLicenseError = (error) => {
          this.$emit('license-error', error);
        };
      }
      
      this.player = new LionDRMPlayer(this.$refs.videoElement, config);
    }
  }
};
</script>

Configuración en main.js (Vue 3)

Opción 1: Importar desde npm (Recomendado)

// main.js
import { createApp } from 'vue';
import App from './App.vue';

// Importar CSS de Video.js
import 'video.js/dist/video-js.css';

// Importar LionDRM Player (las dependencias se cargan automáticamente)
import { LionDRMPlayer } from 'liondrm-videoplayer';

// Hacer disponible globalmente si lo necesitas
window.LionDRMPlayer = { LionDRMPlayer };

createApp(App).mount('#app');

Opción 2: Usar con CDN en index.html

// main.js
import { createApp } from 'vue';
import App from './App.vue';

// El CSS y los scripts se cargan desde index.html
// LionDRMPlayer estará disponible en window.LionDRMPlayer

createApp(App).mount('#app');

index.html (Uso con CDN)

<!DOCTYPE html>
<html lang="es">
<head>
  <meta charset="UTF-8">
  <link rel="icon" href="/favicon.ico">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>LionDRM Player - Vue App</title>
  
  <!-- Video.js CSS -->
  <link href="https://unpkg.com/[email protected]/dist/video-js.min.css" rel="stylesheet">
</head>
<body>
  <div id="app"></div>
  
  <!-- Video.js -->
  <script src="https://unpkg.com/[email protected]/dist/video.min.js"></script>
  
  <!-- videojs-contrib-eme -->
  <script src="https://unpkg.com/[email protected]/dist/videojs-contrib-eme.min.js"></script>
  
  <!-- LionDRM Player (local o CDN) -->
  <script src="/dist/liondrm-videoplayer.min.js"></script>
  
  <script type="module" src="/src/main.js"></script>
</body>
</html>

Composable Reutilizable (Vue 3)

useLionDRMPlayer.js

import { ref, onMounted, onBeforeUnmount } from 'vue';

export function useLionDRMPlayer(elementRef, options = {}) {
  const player = ref(null);
  const isReady = ref(false);
  const isEncrypted = ref(false);
  const drmType = ref(null);
  const error = ref(null);
  
  // Importar desde npm
  import { LionDRMPlayer } from 'liondrm-videoplayer';
  
  // O si usas CDN: const LionDRMPlayer = window.LionDRMPlayer?.LionDRMPlayer;
  
  const initPlayer = () => {
    if (!elementRef.value || !LionDRMPlayer) {
      error.value = 'Element o LionDRMPlayer no disponible';
      return;
    }
    
    try {
      const config = {
        ...options,
        onReady: (p) => {
          isReady.value = true;
          isEncrypted.value = p.isContentEncrypted();
          drmType.value = p.getDRMType();
          options.onReady?.(p);
        },
        onDRMDetected: (type) => {
          drmType.value = type;
          options.onDRMDetected?.(type);
        },
        onUnencryptedContent: () => {
          isEncrypted.value = false;
          options.onUnencryptedContent?.();
        }
      };
      
      player.value = new LionDRMPlayer(elementRef.value, config);
    } catch (err) {
      error.value = err.message;
      console.error('Error inicializando player:', err);
    }
  };
  
  const dispose = () => {
    if (player.value) {
      player.value.dispose();
      player.value = null;
      isReady.value = false;
    }
  };
  
  onMounted(() => {
    initPlayer();
  });
  
  onBeforeUnmount(() => {
    dispose();
  });
  
  return {
    player,
    isReady,
    isEncrypted,
    drmType,
    error,
    dispose
  };
}

Uso del composable:

<template>
  <div>
    <video ref="videoEl" class="video-js" controls></video>
    <p v-if="isEncrypted">🔒 Contenido encriptado con {{ drmType }}</p>
    <p v-else>🔓 Contenido sin encriptar</p>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import { useLionDRMPlayer } from '@/composables/useLionDRMPlayer';

const videoEl = ref(null);

const { player, isReady, isEncrypted, drmType } = useLionDRMPlayer(videoEl, {
  sources: [{
    src: 'https://example.com/video.mp4',
    type: 'video/mp4'
  }]
});
</script>

🔷 Configuración TypeScript para Vue

Si tu proyecto Vue usa TypeScript, necesitas crear archivos de declaración de tipos:

1. src/types/global.d.ts

// src/types/global.d.ts
import type videojs from 'video.js';

declare global {
  interface Window {
    videojs: typeof videojs;
  }
}

export {};

2. src/types/shims-vue.d.ts

// src/types/shims-vue.d.ts
declare module '*.vue' {
  import type { DefineComponent } from 'vue'
  const component: DefineComponent<{}, {}, any>
  export default component
}

3. Actualiza tsconfig.json

{
  "compilerOptions": {
    // ... otras opciones
    "types": ["vite/client"],
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.d.ts",
    "src/**/*.tsx",
    "src/**/*.vue",
    "src/types/**/*.d.ts"
  ]
}

4. Componente con TypeScript

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount } from 'vue'
import videojs from 'video.js'
import 'video.js/dist/video-js.css'
import 'videojs-contrib-eme'
import { LionDRMPlayer, type BrowserDetectionResult } from 'liondrm-videoplayer'

// ✅ Registrar Video.js globalmente
if (typeof window !== 'undefined' && !window.videojs) {
  window.videojs = videojs
}

interface Props {
  title?: string
  videoUrl: string
  videoType?: string
}

const props = withDefaults(defineProps<Props>(), {
  title: 'Video Player',
  videoType: 'video/mp4'
})

const videoElement = ref<HTMLVideoElement | null>(null)
const player = ref<LionDRMPlayer | null>(null)
const playerInfo = ref<BrowserDetectionResult | null>(null)
const isEncrypted = ref(false)

onMounted(() => {
  if (!videoElement.value) return
  
  player.value = new LionDRMPlayer(videoElement.value, {
    sources: [{ src: props.videoUrl, type: props.videoType }],
    controls: true,
    onReady: (p: LionDRMPlayer) => {
      playerInfo.value = p.getBrowserInfo()
      isEncrypted.value = p.isContentEncrypted()
    }
  })
})

onBeforeUnmount(() => {
  player.value?.dispose()
})
</script>

Ejemplo 2: Detección Antes de Cargar

const player = new LionDRMPlayer('my-video', {
  sources: [{
    src: 'https://example.com/video.mpd',
    type: 'application/dash+xml'
  }],
  drm: {
    widevine: { licenseUrl: 'https://example.com/license' }
  }
});

const encInfo = player.getEncryptionInfo();

if (encInfo.isEncrypted && !encInfo.hasDRMConfig) {
  alert('⚠️ Este contenido requiere licencia DRM');
}

Desarrollo

# Clonar e instalar (build automático con postinstall)
git clone https://github.com/tu-usuario/liondrm-videoplayer.git
cd liondrm-videoplayer
npm install

# Desarrollo con watch mode (reconstruye automáticamente al guardar cambios)
npm run dev

# Build manual (si lo necesitas)
npm run build

# Servidor de desarrollo
npm run serve
# Abre http://localhost:8080/examples/

Scripts Disponibles

  • npm install - Instala dependencias y ejecuta build automáticamente
  • npm run dev - Modo desarrollo con watch (reconstruye al guardar)
  • npm run build - Build manual del proyecto
  • npm run serve - Inicia servidor en http://localhost:8080

Estructura del Proyecto

liondrm-videoplayer/
├── src/
│   ├── liondrm-player.js      # Clase principal del reproductor
│   ├── browser-detector.js     # Detección de navegador y DRM
│   ├── drm-config.js          # Configuraciones DRM
│   └── index.js               # Punto de entrada
├── dist/                       # Archivos compilados
├── examples/                   # Ejemplos de uso
├── package.json
├── rollup.config.js
└── README.md

Licencia

MIT © DevLeon

Créditos

Basado en: