NanoPlayer
Reproductor web multi-stream, accesible y extensible, para plataformas de vídeo docente. Un reproductor que no te obliga a forkearlo.
En desarrollo · nada publicado todavíaEl reproductor ya funciona y se puede probar aquí abajo, pero no está publicado: no hay paquete en npm, ni CDN, ni versión etiquetada. La API puede cambiar sin aviso. Esto es un escaparate del desarrollo, no una release.
Demo
El reproductor
En construcciónLo que vería quien lo integre: dual-stream sincronizado, barra de controles accesible, menú de ajustes con velocidad y disposición, y subtítulos en dos idiomas. Se irán añadiendo aquí los plugins según se construyan.
- Mientras se ve el póster no hay ningún
<video>en el DOM ni un byte de vídeo descargado - Operable entero con el teclado, verificado en CI en Chromium y WebKit. En Safari, Tab no entra en los botones salvo que actives la navegación por teclado del sistema — los atajos funcionan igual con el foco en el reproductor
- Los subtítulos se activan solos porque el manifiesto trae pistas
- Cuatro disposiciones en el menú de ajustes: lado a lado, imagen en imagen, solo ponente y solo presentación
Banco de pruebas del núcleo
InstrumentadoEl mismo núcleo con el ciclo de vida en crudo: botones para resolver, enganchar, soltar el motor y desincronizar a propósito. Seis escenarios: mono, dual, HLS, solo audio, audio con diapositivas y un manifiesto inválido.
- Contadores de peticiones de red y de elementos
<video> - Desincronizar 400 ms a propósito y ver al lazo corregirlo por debajo de los 33 ms de un frame
- Soltar el motor libera los decodificadores y conserva la posición
- El registro de eventos es literalmente lo que ve
onAny()
Spikes de validación
S1 · Sincronización dual-stream
Resuelto
¿Se pueden mantener dos vídeos sincronizados usando solo <video>
nativo, sin biblioteca externa? Banco con gráfico de deriva en vivo y
botones para provocar cada perturbación.
- Sí: deriva mediana de 9,8 ms en Chrome — un frame a 30 fps son 33 ms
- La histéresis es obligatoria: sin ella queda un offset fijo de 28,8 ms
- La ganancia gobierna la recuperación, no el techo de velocidad
S2 · Diagnóstico de dispositivo
ResueltoMide qué puede hacer un dispositivo con vídeo: decodificación simultánea, pantalla completa, MSE, autoplay y sincronización. Un solo fichero, se abre en cualquier móvil y devuelve un informe.
| Motor | Vídeos a la vez | Deriva p95 | Fullscreen del contenedor |
|---|---|---|---|
| Blink (Chrome) | 18 | 15 ms | sí |
| WebKit (Safari, Mac) | 17 | 54 ms | sí |
| WebKit (iPhone) | 17 | 209 ms | no |
- En iPhone no existe el fullscreen de contenedor: el dual-stream a pantalla completa es imposible, y es limitación de iOS y no de WebKit
- El límite de vídeos simultáneos lo pone el motor, no el hardware
- La calibración de la sincronización no es portable entre motores
S6 · Encadenado de cabecera y cola
Falta el dato de iPhone¿Se puede pasar de la cabecera al contenido sin que se vea el salto? Sí, pero solo arrancando la pieza siguiente antes de que termine la anterior. Tres piezas de color plano: si aparece negro, hubo hueco.
- Sin anticipación el hueco es de 340–445 ms; con 600 ms de anticipación baja a cero en Chromium y en WebKit
- Un
play()sobre un elemento ya cargado tarda 250 ms en dar el primer fotograma, y hasta 430 ms en WebKit - Falta lo que decide: en iOS el permiso de reproducción es de cada elemento, no de la página. Se agradece abrirlo en un iPhone
S5 · Directo dual-stream
Resuelto
¿Se pueden sincronizar dos directos HLS independientes? Sí, pero solo con
EXT-X-PROGRAM-DATE-TIME en ambas listas. Este banco necesita
emisiones en vivo, así que no se publica aquí: las conclusiones y las
medidas están en el repositorio.
- Sin la etiqueta de hora no es que la corrección salga peor: es que no hay forma de medir si están sincronizados
- En directo
currentTimetiene su origen en cuándo empezó a cargar cada flujo, no en un instante común - Tras un corte conviene un salto duro por hora absoluta: absorber 3 s al 25 % de velocidad extra tardaría doce