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
Maintainers
Readme
LionDRM Videoplayer
🦁 Reproductor de video con DRM automático - Cero configuración, solo instala y usa
✨ 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:
- ✅ Navegador: Chrome, Firefox, Safari, Edge, Opera
- ✅ DRM Compatible: Widevine, FairPlay, PlayReady
- ✅ Contenido Encriptado: Analiza el formato, tipo MIME, y configuración
- ✅ 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.jsmanualmente - ❌ Configurar
tsconfig.jsonespecial
🌐 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:
- ✅ Configuración DRM: Si proporcionas configuración DRM
- ✅ Formato de archivo: Extensiones como
.mpd,.ism,.m3u8 - ✅ Tipo MIME:
application/dash+xml,application/x-mpegURL, etc. - ✅ Parámetros URL: Busca
drm=,token=,license,encryption - ✅ 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-videoplayerDesde 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 reproductorNota: 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ónpause()- Pausar reproduccióngetDRMType()- Obtener el tipo de DRM detectadogetBrowserInfo()- Obtener información del navegadorisContentEncrypted()- NUEVO: Verificar si el contenido está encriptadogetEncryptionInfo()- NUEVO: Obtener información detallada de encriptaciónchangeSource(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-videoplayerdesde npm, las dependenciasvideo.jsyvideojs-contrib-emese 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 parawindow.videojssrc/types/shims-vue.d.ts- Declaraciones para módulos.vueVer 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áticamentenpm run dev- Modo desarrollo con watch (reconstruye al guardar)npm run build- Build manual del proyectonpm 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.mdLicencia
MIT © DevLeon
Créditos
Basado en:
