Skip to content

Repository files navigation

Lumina Reader

Lector dual: el PDF de un libro y su audiolibro, en la misma pantalla y sincronizados. Pensado para leer Mistborn: El Imperio Final mientras suena la narración, con estética de Scadrial — ceniza y bronce.

Un PDF y un MP3 no vienen sincronizados de fábrica, así que Lumina Reader resuelve esa parte con anclajes manuales: le dices en qué página empieza cada capítulo y a partir de ahí puede llevar la página al punto del audio, el audio al punto de la página, o hacer que la página avance sola mientras escuchas.

Requisitos

  • Node 22+ (probado con 22.15.1)
  • ffmpeg/ffprobe en el PATH, sólo para generar el manifest
    winget install Gyan.FFmpeg
    

Puesta en marcha

npm install

Coloca los archivos del libro con esta estructura:

public/books/mistborn-1/
├── mistborn_el_imperio_final.pdf
└── audio/
    ├── ch01.mp3
    ├── ch02.mp3
    └── ...

Un archivo de audio por capítulo. El orden sale del nombre, así que numéralos con ceros a la izquierda (ch01, no ch1). Si los nombres traen título —03 - El Superviviente.mp3— se usa como nombre del capítulo.

Genera el manifest y arranca:

npm run manifest
npm run dev

npm run manifest recorre los audios con ffprobe y escribe public/books/mistborn-1/manifest.json con la duración real de cada capítulo. Se hornean ahí en vez de leerlas en el navegador porque un MP3 VBR sin cabecera Xing/LAME reporta duración infinita hasta que se escanea entero, y porque así la lista de capítulos aparece completa en el primer render.

Volver a correrlo conserva los anclajes que ya hubieras hecho.

Cómo sincronizar el audio con el texto

  1. Pon el capítulo 1 y busca en el PDF la página donde empieza. Pulsa Anclar.
  2. Haz lo mismo con algún capítulo más adelante. No hace falta anclarlos todos: los tramos sin anclar se reparten según la duración de sus capítulos.
  3. Activa Seguir y la página irá avanzando sola con la narración, interpolando entre anclajes. Si pasas página a mano, el seguimiento se apaga solo para no pelearse contigo.

Los dos botones de flecha llevan la página al punto del audio o al revés, una sola vez, sin activar el seguimiento.

Atajos de teclado

Tecla Acción
Espacio Reproducir o pausar
J / L Retroceder / adelantar 15 s
Página anterior / siguiente
+ Capítulo anterior / siguiente
+ Acercar / alejar
0 Ajustar al ancho
A Anclar el capítulo en esta página
G Seguimiento automático
N Modo noche del PDF
C Mostrar u ocultar capítulos
F Pantalla completa
? Ayuda

Dónde se guarda qué

Todo es local, no hay backend ni cuentas.

Clave de localStorage Contenido
lumina:progress:mistborn-1 Capítulo, segundo exacto y página
lumina:checkpoints:mistborn-1 Anclajes capítulo → página
lumina:prefs Velocidad, zoom, seguimiento, modo noche, sidebar

Los anclajes viven en localStorage y no en el manifest, así que reemplazar los archivos del libro no borra el mapeo.

Notas sobre el repositorio

El PDF y los MP3 se commitean a public/books/. Con audio partido por capítulos cada archivo queda muy por debajo del límite de 100 MB de GitHub, pero el conjunto deja el repo en cientos de MB de forma permanente — git conserva todo binario en el historial. Conviene que el repositorio sea privado.

Si algún día quieres sacarlos, la app lee todo desde manifest.json con rutas relativas y nunca importa media desde src/: basta con añadirlos a .gitignore, sin tocar código.

public/pdfjs/ se genera desde node_modules (scripts/sync-pdfjs-assets.mjs, que corre solo antes de dev y build) y está en .gitignore. Contiene las fuentes estándar, los cMaps y el wasm que pdf.js pide por HTTP; sin ellos, los PDFs que no incrustan sus fuentes se renderizan sin texto.

Stack

Vite 8 (Rolldown) · React 19 con React Compiler · Tailwind CSS v4 · react-pdf 10 (pdf.js) · lucide-react · JavaScript

El audio usa el elemento <audio> nativo, sin librería: es lo único que expone preservesPitch, que es lo que evita que la voz suene aguda al subir la velocidad.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages