npm package: @raqemi/video-drm
Description: A secure DRM solution for Next.js LMS video content protection
Latest version: 1.0.0

# Raqemi Video DRM

A comprehensive Digital Rights Management (DRM) solution for Next.js applications, specifically designed to protect video content in Learning Management Systems and similar platforms.

## Features

- **Strong Encryption**: AES-256 encryption for video content
- **Secure Streaming**: HLS/DASH streaming with encryption
- **Multiple Storage Options**: Local storage, Amazon S3, and Cloudinary
- **Anti-Piracy Protection**: 
  - Prevents screen capture and recording
  - Blocks browser developer tools
  - Applies dynamic watermarks
  - Prevents right-click downloading
- **Session Management**: Controls concurrent user sessions
- **Device Fingerprinting**: Identifies and restricts suspicious devices
- **License Management**: Token-based access control for videos
- **Easy Integration**: React components for seamless integration

## Installation

```bash
npm install @raqemi/video-drm
# or
yarn add @raqemi/video-drm
```

## Quick Start

### 1. Initialize the DRM System

```typescript
// _app.tsx or similar entry point
import { initializeRaqemiDRM } from '@raqemi/video-drm';

initializeRaqemiDRM({
  storage: {
    type: 'local',
    path: './videos'
    // For S3:
    // type: 's3',
    // s3: {
    //   region: 'us-east-1',
    //   bucket: 'your-bucket',
    //   accessKeyId: process.env.AWS_ACCESS_KEY_ID,
    //   secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
    // }
  },
  encryption: {
    algorithm: 'aes-256-gcm',
    keySize: 256,
    secretKey: process.env.ENCRYPTION_SECRET_KEY,
    enableSegmentEncryption: true
  },
  license: {
    tokenExpiryTime: 3600, // 1 hour
    jwtSecret: process.env.JWT_SECRET,
    allowedDomains: ['yourdomain.com'],
    maxConcurrentSessions: 2
  },
  protection: {
    preventScreenCapture: true,
    preventRightClick: true,
    applyWatermark: true,
    watermarkText: 'Confidential Content',
    watermarkOpacity: 0.3,
    detectVirtualMachines: true,
    blockDevTools: true
  }
});
```

### 2. Create API Routes for Video Access

```typescript
// pages/api/videos/[id]/stream.ts
import { NextApiRequest, NextApiResponse } from 'next';
import { validateToken, getVideoMetadata } from '@raqemi/video-drm';
import fs from 'fs';
import path from 'path';

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  const { id } = req.query;
  const token = req.headers.authorization?.replace('Bearer ', '') || req.query.token as string;
  
  try {
    // Validate token
    const decodedToken = await validateToken(token);
    
    // Check if token is for the requested video
    if (decodedToken.videoId !== id) {
      return res.status(403).json({ error: 'Invalid token for this video' });
    }
    
    // Get video metadata
    const metadata = await getVideoMetadata(id as string);
    if (!metadata) {
      return res.status(404).json({ error: 'Video not found' });
    }
    
    // Set headers for video streaming
    res.setHeader('Content-Type', 'application/x-mpegURL');
    res.setHeader('Access-Control-Allow-Origin', '*');
    
    // Stream the video
    const videoPath = path.join(process.cwd(), 'videos', metadata.fileName);
    const videoStream = fs.createReadStream(videoPath);
    
    videoStream.pipe(res);
  } catch (error) {
    console.error('Error streaming video:', error);
    res.status(500).json({ error: 'Error streaming video' });
  }
}
```

```typescript
// pages/api/license/index.ts
import { NextApiRequest, NextApiResponse } from 'next';
import { getLicenseToken } from '@raqemi/video-drm';

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  if (req.method !== 'POST') {
    return res.status(405).json({ error: 'Method not allowed' });
  }
  
  const { videoId, userId } = req.body;
  
  try {
    // Get JWT token for video access
    const token = await getLicenseToken(videoId, userId);
    
    res.status(200).json({ token });
  } catch (error) {
    console.error('Error generating license token:', error);
    res.status(500).json({ error: 'Error generating license token' });
  }
}
```

### 3. Use the Secure Video Player Component

```tsx
// pages/courses/[id].tsx
import { SecurePlayer } from '@raqemi/video-drm';
import { useEffect, useState } from 'react';

export default function CoursePage({ courseId, videoId }) {
  const [token, setToken] = useState('');
  
  useEffect(() => {
    // Get license token
    const fetchToken = async () => {
      const response = await fetch('/api/license', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          videoId,
          userId: 'user-123',
        }),
      });
      
      const data = await response.json();
      setToken(data.token);
    };
    
    if (videoId) {
      fetchToken();
    }
  }, [videoId]);
  
  if (!token) {
    return <div>Loading...</div>;
  }
  
  return (
    <div>
      <h1>Course Video</h1>
      <SecurePlayer
        videoId={videoId}
        width="100%"
        height="auto"
        autoPlay={false}
        controls={true}
        watermarkText={`User: user-123 - Course: ${courseId}`}
      />
    </div>
  );
}
```

### 4. Add the Upload Component

```tsx
// pages/admin/upload.tsx
import { UploadComponent } from '@raqemi/video-drm';
import { useState } from 'react';

export default function UploadPage() {
  const [uploadedVideo, setUploadedVideo] = useState(null);
  
  const handleUploadComplete = (metadata) => {
    setUploadedVideo(metadata);
    // Notify server or update database
  };
  
  return (
    <div>
      <h1>Upload Course Video</h1>
      
      <UploadComponent
        userId="admin-user"
        onUploadComplete={handleUploadComplete}
        onUploadError={(error) => console.error('Upload error:', error)}
        onUploadProgress={(progress) => console.log('Upload progress:', progress)}
        acceptedFileTypes="video/mp4,video/webm,video/ogg"
        maxFileSize={1024 * 1024 * 500} // 500MB
        metadata={{
          title: 'Introduction to Course',
          allowedRoles: ['subscriber', 'premium']
        }}
      />
      
      {uploadedVideo && (
        <div>
          <h2>Upload Successful!</h2>
          <p>Video ID: {uploadedVideo.id}</p>
          <p>Title: {uploadedVideo.title}</p>
        </div>
      )}
    </div>
  );
}
```

## Configuration Options

### Storage Configuration

| Option | Type | Description |
|--------|------|-------------|
| `type` | `'local' \| 's3' \| 'cloudinary'` | Storage provider type |
| `path` | `string` | Local storage path (for type 'local') |
| `s3` | `object` | S3 configuration object (for type 's3') |
| `cloudinary` | `object` | Cloudinary configuration (for type 'cloudinary') |

### Encryption Configuration

| Option | Type | Description |
|--------|------|-------------|
| `algorithm` | `'aes-256-cbc' \| 'aes-256-ctr' \| 'aes-256-gcm'` | Encryption algorithm |
| `keySize` | `256 \| 128` | Key size in bits |
| `enableSegmentEncryption` | `boolean` | Enable per-segment encryption for HLS |
| `secretKey` | `string` | Master encryption key |
| `ivSize` | `number` | Initialization vector size |

### License Management

| Option | Type | Description |
|--------|------|-------------|
| `tokenExpiryTime` | `number` | Token expiry time in seconds |
| `jwtSecret` | `string` | Secret for JWT signing |
| `allowedDomains` | `string[]` | List of domains allowed to play videos |
| `maxConcurrentSessions` | `number` | Maximum number of concurrent user sessions |

### Protection Features

| Option | Type | Description |
|--------|------|-------------|
| `preventScreenCapture` | `boolean` | Enable screen capture prevention |
| `preventRightClick` | `boolean` | Disable right-click menu |
| `applyWatermark` | `boolean` | Apply watermark to videos |
| `watermarkText` | `string` | Custom watermark text |
| `watermarkOpacity` | `number` | Watermark opacity (0-1) |
| `detectVirtualMachines` | `boolean` | Detect and block virtual machines |
| `blockDevTools` | `boolean` | Block browser developer tools |

## API Reference

### Components

- `SecurePlayer` - Protected video player component
- `UploadComponent` - Video upload component with encryption

### Services

- `CryptoService` - Handles encryption and decryption
- `getLicenseToken` - Generates a license token for video access
- `validateToken` - Validates a license token
- `uploadVideo` - Uploads and encrypts a video file
- `prepareVideoForStreaming` - Prepares a video for HLS streaming

### Utilities

- `getFingerprint` - Generates a unique device fingerprint
- `applyClientSideProtection` - Applies protection measures to a video player

## Security Considerations

- **Secret Keys**: Store encryption keys and JWT secrets securely and never expose them to the client
- **Server-Side Validation**: Always validate license tokens on the server-side
- **HTTPS**: Use HTTPS to prevent man-in-the-middle attacks
- **Environment Variables**: Store sensitive configuration in environment variables
- **Regular Key Rotation**: Rotate encryption keys and JWT secrets regularly

## Limitations

- No DRM solution is 100% effective against determined attackers
- Some protection features may be circumvented by sophisticated tools
- Client-side protection works best when combined with server-side measures
- Screen recording protection has limitations due to browser security models

## License

MIT