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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@multidrop/md-player

v0.1.5

Published

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

Readme

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

npm install md-player

🎯 Uso Básico

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

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:

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:

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:

captions: {
  src: 'https://example.com/subtitles.vtt',
}

2. Array de URLs (detecção automática de idioma):

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:

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:

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:

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:

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

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

Estilo de Legendas

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:

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

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

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

Navegação

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

Volume

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

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

Legendas

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

Áudio (HLS)

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

Informações

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

Tela Cheia

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

Picture-in-Picture

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

Eventos

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

Destruição

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

📝 Exemplos Completos

Exemplo 1: Player Básico

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

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

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

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

npm run build

Desenvolvimento

npm run dev

Type Check

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.