npm package: @multidrop/md-player
Description: Biblioteca npm reutilizável para reprodução de vídeo na web com legendas customizadas estilo YouTube/Netflix, suporte a múltiplos idiomas (i18n) e controles modernos
Latest version: 0.1.5

# md-player

Biblioteca npm reutilizável para reprodução de vídeo na web com legendas customizadas estilo YouTube/Netflix, suporte a múltiplos idiomas (i18n) e controles modernos.

## 🚀 Características

- ✅ Suporte a **HLS (.m3u8)** e **MP4**
- ✅ **Legendas VTT** com múltiplos idiomas
- ✅ **Múltiplas faixas de áudio** (HLS)
- ✅ **Interface multi-idioma** (i18n) - 11 idiomas suportados
- ✅ **Controles estilo Netflix/YouTube**
- ✅ **Design responsivo** (mobile-first)
- ✅ **Carregamento em chunks** (não trava com vídeos grandes)
- ✅ **Preload em background** (continua baixando mesmo quando pausado)
- ✅ **Customização de cores** (themeColor/primaryColor)
- ✅ **TypeScript** completo
- ✅ **Zero dependências** (exceto hls.js para HLS)

## 📦 Instalação

```bash
npm install md-player
```

## 🎯 Uso Básico

### HTML

```html
<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="node_modules/md-player/dist/style.css">
</head>
<body>
  <div id="player" style="width: 100%; aspect-ratio: 16/9;"></div>
  
  <script type="module">
    import { MdPlayer } from 'md-player';
    
    const player = new MdPlayer({
      container: '#player',
      src: 'https://example.com/video.m3u8',
    });
  </script>
</body>
</html>
```

### JavaScript/TypeScript

```javascript
import { MdPlayer } from 'md-player';
import 'md-player/styles'; // Importa estilos CSS

const player = new MdPlayer({
  container: '#player',
  src: 'https://example.com/video.m3u8',
  captions: {
    src: [
      'https://example.com/subtitles/pt.vtt',
      'https://example.com/subtitles/en.vtt',
    ],
  },
  language: 'pt', // Idioma da interface
  themeColor: '#e50914', // Cor personalizada
});
```

## 📚 API Completa

### MdPlayerOptions

Todas as opções disponíveis para configurar o player:

```typescript
interface MdPlayerOptions {
  // Obrigatórias
  container: string | HTMLElement;  // Seletor CSS ou elemento HTML
  src: string;                      // URL do vídeo (MP4 ou HLS .m3u8)
  
  // Opcionais
  captions?: CaptionOptions;          // Configurações de legendas
  controls?: ControlsOptions;        // Configurações de controles
  autoplay?: boolean;                // Autoplay (padrão: false)
  loop?: boolean;                    // Loop (padrão: false)
  muted?: boolean;                   // Mudo (padrão: false)
  volume?: number;                   // Volume inicial 0-1 (padrão: 1)
  playbackRate?: number;             // Velocidade inicial (padrão: 1)
  themeColor?: string;              // Cor primária hex (padrão: '#e50914')
  primaryColor?: string;            // Alias para themeColor (deprecated)
  language?: string;                 // Idioma da interface (padrão: 'en')
}
```

### CaptionOptions

Configurações para legendas:

```typescript
interface CaptionOptions {
  src: string | string[] | CaptionTrack[];  // URL(s) ou objetos de legenda
  language?: string;                        // Idioma inicial (ex: 'pt', 'en')
  style?: 'youtube' | 'tiktok' | 'netflix'; // Estilo de legenda (padrão: 'youtube')
  customStyle?: CaptionStyle;               // Estilo customizado
}
```

#### Exemplos de `src` para legendas:

**1. String única:**
```javascript
captions: {
  src: 'https://example.com/subtitles.vtt',
}
```

**2. Array de URLs (detecção automática de idioma):**
```javascript
captions: {
  src: [
    'https://example.com/subtitles/pt.vtt',
    'https://example.com/subtitles/en.vtt',
    'https://example.com/subtitles/de.vtt',
  ],
  language: 'pt', // Idioma inicial
}
```

**3. Array de objetos CaptionTrack:**
```javascript
captions: {
  src: [
    {
      src: 'https://example.com/subtitles/pt.vtt',
      srclang: 'pt',
      label: 'Português',
    },
    {
      src: 'https://example.com/subtitles/en.vtt',
      srclang: 'en',
      label: 'English',
    },
  ],
  language: 'pt',
}
```

### CaptionStyle

Customização visual das legendas:

```typescript
interface CaptionStyle {
  color?: string;              // Cor do texto (ex: '#fff')
  backgroundColor?: string;     // Cor de fundo (ex: 'rgba(0, 0, 0, 0.75)')
  fontSize?: string;            // Tamanho da fonte (ex: '18px')
  fontFamily?: string;          // Família da fonte
  position?: 'top' | 'center' | 'bottom'; // Posição (padrão: 'bottom')
  backgroundOpacity?: number;   // Opacidade do fundo 0-1
}
```

### ControlsOptions

Configurações dos controles:

```typescript
interface ControlsOptions {
  show?: boolean;    // Mostrar controles (padrão: true)
  hideDelay?: number; // Delay para ocultar controles em ms (padrão: 3000)
}
```

## 🌍 Internacionalização (i18n)

O player suporta **11 idiomas** para a interface:

- `'pt'` - Português
- `'en'` - English (padrão)
- `'de'` - Deutsch
- `'es'` - Español
- `'fr'` - Français
- `'it'` - Italiano
- `'ja'` - 日本語
- `'ko'` - 한국어
- `'zh'` - 中文
- `'ru'` - Русский
- `'ar'` - العربية

### Exemplo:

```javascript
const player = new MdPlayer({
  container: '#player',
  src: 'video.m3u8',
  language: 'en', // Interface em inglês
});
```

## 🎨 Customização

### Cor Primária

Personalize a cor de destaque do player (barra de progresso, itens selecionados, etc.):

```javascript
const player = new MdPlayer({
  container: '#player',
  src: 'video.m3u8',
  themeColor: '#1a5f1a', // Verde escuro
});
```

### Estilo de Legendas

```javascript
const player = new MdPlayer({
  container: '#player',
  src: 'video.m3u8',
  captions: {
    src: 'subtitles.vtt',
    style: 'youtube', // ou 'tiktok', 'netflix'
    customStyle: {
      color: '#fff',
      backgroundColor: 'rgba(0, 0, 0, 0.75)',
      fontSize: '18px',
      position: 'bottom',
    },
  },
});
```

## 📡 Eventos

O player emite eventos que você pode escutar:

```javascript
// Escutar eventos
player.on('play', () => {
  console.log('Vídeo iniciado');
});

player.on('pause', () => {
  console.log('Vídeo pausado');
});

player.on('timeupdate', (event, data) => {
  console.log('Tempo atual:', data.currentTime);
  console.log('Duração:', data.duration);
});

player.on('volumechange', (event, data) => {
  console.log('Volume:', data.volume);
  console.log('Mudo:', data.muted);
});

player.on('error', (event, data) => {
  console.error('Erro:', data);
});

player.on('audiotracksavailable', (event, data) => {
  console.log('Faixas de áudio disponíveis:', data.tracks);
});

player.on('captionstracksavailable', (event, data) => {
  console.log('Legendas disponíveis:', data.tracks);
});
```

### Eventos Disponíveis

- `'play'` - Vídeo iniciado
- `'pause'` - Vídeo pausado
- `'ended'` - Vídeo finalizado ⭐
- `'timeupdate'` - Tempo atualizado (com `currentTime` e `duration`)
- `'buffering'` - Estado de buffer (com `buffering: boolean`)
- `'error'` - Erro no player
- `'loadedmetadata'` - Metadados carregados
- `'canplay'` - Vídeo pode reproduzir
- `'volumechange'` - Volume alterado (com `volume` e `muted`)
- `'ratechange'` - Velocidade alterada (com `playbackRate`)
- `'audiotracksavailable'` - Faixas de áudio disponíveis
- `'audiotrackchange'` - Faixa de áudio alterada
- `'captionstracksavailable'` - Legendas disponíveis
- `'captiontrackchange'` - Legenda alterada

### Exemplos de Uso de Eventos

```javascript
import { MdPlayer } from 'md-player';

const player = new MdPlayer({
  container: '#player',
  src: 'https://example.com/video.m3u8',
});

// Evento quando o vídeo termina
player.on('ended', () => {
  console.log('Vídeo finalizado!');
  // Exemplo: redirecionar para próxima página
  // window.location.href = '/proxima-aula';
  
  // Exemplo: mostrar mensagem
  // alert('Parabéns! Você completou o vídeo.');
  
  // Exemplo: enviar analytics
  // analytics.track('video_completed', { videoId: '123' });
});

// Evento quando o vídeo inicia
player.on('play', () => {
  console.log('Vídeo iniciado');
});

// Evento quando o vídeo pausa
player.on('pause', () => {
  console.log('Vídeo pausado');
});

// Evento de atualização de tempo (útil para progresso)
player.on('timeupdate', (event, data) => {
  const { currentTime, duration } = data;
  const progress = (currentTime / duration) * 100;
  console.log(`Progresso: ${progress.toFixed(1)}%`);
});

// Evento de erro
player.on('error', (event, data) => {
  console.error('Erro no player:', data);
});

// Usar once() para escutar apenas uma vez
player.once('loadedmetadata', () => {
  console.log('Metadados carregados (apenas uma vez)');
});
```

## 🎮 Métodos da API

### Controle de Reprodução

```javascript
player.play();        // Reproduz o vídeo
player.pause();       // Pausa o vídeo
player.togglePlay();  // Alterna play/pause
```

### Navegação

```javascript
player.seek(30);      // Vai para 30 segundos
player.seekToPercent(0.5); // Vai para 50% do vídeo
```

### Volume

```javascript
player.setVolume(0.5);  // Define volume (0-1)
player.getVolume();     // Obtém volume atual
player.toggleMute();    // Alterna mudo
player.mute();          // Silencia
player.unmute();        // Remove silêncio
player.setMuted(true);  // Define mudo (boolean)
player.isMuted();       // Verifica se está mudo
```

### Velocidade

```javascript
player.setPlaybackRate(1.5); // 1.5x velocidade
player.getPlaybackRate();     // Obtém velocidade atual
```

### Legendas

```javascript
player.setCaptionTrack(0);  // Ativa legenda (índice)
player.setCaptionTrack(-1);  // Desativa legendas
player.toggleCaptions();     // Alterna legendas
player.setCaptionsVisible(true); // Define visibilidade
```

### Áudio (HLS)

```javascript
player.setAudioTrack(0);  // Seleciona faixa de áudio (índice)
player.getAudioTracks();  // Obtém faixas disponíveis
```

### Informações

```javascript
player.getCurrentTime();  // Tempo atual (segundos)
player.getDuration();     // Duração total (segundos)
player.isPaused();        // Está pausado?
player.isLoading();       // Está carregando?
```

### Tela Cheia

```javascript
player.toggleFullscreen(); // Alterna tela cheia
player.enterFullscreen();  // Entra em tela cheia
player.exitFullscreen();   // Sai de tela cheia
```

### Picture-in-Picture

```javascript
player.enterPictureInPicture(); // Entra em PiP
player.exitPictureInPicture();  // Sai de PiP
```

### Eventos

```javascript
player.on('play', callback);     // Adiciona listener
player.off('play', callback);    // Remove listener
player.once('play', callback);   // Listener único
```

### Destruição

```javascript
player.destroy(); // Remove player e limpa recursos
```

## 📝 Exemplos Completos

### Exemplo 1: Player Básico

```javascript
import { MdPlayer } from 'md-player';
import 'md-player/styles';

const player = new MdPlayer({
  container: '#player',
  src: 'https://example.com/video.mp4',
});
```

### Exemplo 2: Player com Legendas

```javascript
const player = new MdPlayer({
  container: '#player',
  src: 'https://example.com/video.m3u8',
  captions: {
    src: [
      'https://example.com/subtitles/pt.vtt',
      'https://example.com/subtitles/en.vtt',
    ],
    language: 'pt',
  },
  language: 'pt',
});
```

### Exemplo 3: Player Customizado

```javascript
const player = new MdPlayer({
  container: '#player',
  src: 'https://example.com/video.m3u8',
  autoplay: false,
  muted: false,
  volume: 0.8,
  loop: false,
  themeColor: '#1a5f1a', // Verde escuro
  language: 'en',
  captions: {
    src: [
      {
        src: 'https://example.com/subtitles/pt.vtt',
        srclang: 'pt',
        label: 'Português',
      },
      {
        src: 'https://example.com/subtitles/en.vtt',
        srclang: 'en',
        label: 'English',
      },
    ],
    language: 'pt',
    style: 'youtube',
    customStyle: {
      color: '#fff',
      backgroundColor: 'rgba(0, 0, 0, 0.75)',
      fontSize: '18px',
    },
  },
  controls: {
    show: true,
    hideDelay: 3000,
  },
});

// Eventos
player.on('play', () => console.log('Playing'));
player.on('pause', () => console.log('Paused'));
player.on('timeupdate', (event, data) => {
  console.log(`Time: ${data.currentTime}/${data.duration}`);
});
```

### Exemplo 4: Controle Programático

```javascript
const player = new MdPlayer({
  container: '#player',
  src: 'video.m3u8',
});

// Controles customizados
document.getElementById('play-btn').addEventListener('click', () => {
  player.play();
});

document.getElementById('pause-btn').addEventListener('click', () => {
  player.pause();
});

document.getElementById('volume-slider').addEventListener('input', (e) => {
  player.setVolume(e.target.value / 100);
});

// Ir para 50% do vídeo
document.getElementById('skip-btn').addEventListener('click', () => {
  player.seekToPercent(0.5);
});
```

## 🎬 Formatos Suportados

### Vídeo

- **HLS** (.m3u8) - Suporte completo via hls.js
- **MP4** - Suporte nativo do navegador

### Legendas

- **WebVTT** (.vtt) - Formato padrão

### Áudio (HLS)

- Múltiplas faixas de áudio detectadas automaticamente
- Seleção de faixa de áudio via interface

## 📱 Responsividade

O player é totalmente responsivo e otimizado para mobile:

- **Controles adaptativos** - Tamanhos e espaçamentos ajustados
- **Menu estilo Netflix** - Desliza de baixo no mobile
- **Área de toque otimizada** - Botões maiores em telas pequenas
- **Layout flexível** - Adapta-se a diferentes tamanhos de tela

## 🔧 Desenvolvimento

### Build

```bash
npm run build
```

### Desenvolvimento

```bash
npm run dev
```

### Type Check

```bash
npm run type-check
```

## 📄 Licença

MIT

## 🤝 Contribuindo

Contribuições são bem-vindas! Sinta-se à vontade para abrir issues e pull requests.

## 📞 Suporte

Para questões e suporte, abra uma issue no repositório.