Cinco segundos de silencio
Una lectora de Chile se registró, subió un PDF de 74 páginas de una novela infantil — "¿Quién le tiene miedo a Demetrio Latov?" de Ángeles Durini — y pulsó Generar audiolibro. Quince segundos después, le llegó un correo: "Tu audiolibro está listo."
No lo estaba. El archivo duraba 5,6 segundos. No contenía nada.
Es la clase de error que solo se detecta en producción, porque los PDF de prueba que veníamos usando tenían texto incrustado. El suyo no. El libro había sido escaneado, página a página, en 2012 con Adobe Acrobat Pro, y cada página estaba guardada como una imagen. Para nuestro pipeline, el PDF eran 74 páginas en blanco.
Por qué los PDF escaneados rompen los pipelines de audiolibros
Un PDF puede llevar el texto de dos maneras totalmente distintas:
- PDF de texto: las palabras se guardan como caracteres reales, con tipografía y posición. Cualquier librería (pypdf, pdfminer, pypdfium2) puede extraerlos en milisegundos.
- PDF de imagen (escaneos): las páginas son fotos en JPEG o TIFF incrustadas dentro del envoltorio PDF. Para una librería de extracción de texto, esas páginas contienen cero caracteres.
Todo lo que sale de un escáner plano, de la cámara del móvil o de un proyecto antiguo de digitalización (piensa en Google Books, archive.org, reediciones de dominio público, libros infantiles de segunda mano) suele ser del segundo tipo. A simple vista son idénticos. Para el software, son radicalmente distintos.
Cuando examinamos la carga fallida, nuestro parser de PDF había devuelto exactamente 17 caracteres de basura — bytes de control, no letras — para el libro entero de 74 páginas. Nuestro pipeline, obediente, le pasó esos 17 bytes al motor de texto a voz y produjo 5 segundos de murmullos. Después le mandó un correo a la lectora diciendo que su audiolibro estaba listo.
Lo que construimos
La solución es sencilla en concepto: detectar cuándo un PDF no tiene texto utilizable y entonces hacer OCR a cada página. La implementación tiene varias piezas que vale la pena describir.
1. Un detector de texto escaso
Antes de lanzar OCR para cada carga, comprobamos el resultado de la extracción nativa. Si todo el PDF devolvió menos de 200 caracteres, o si el promedio es inferior a 30 caracteres por página en 4 o más páginas, lo tratamos como un escaneo y pasamos al OCR. Los PDF de texto normales — más del 90% de los casos — nunca activan el camino lento.
2. pypdfium2 + tesseract (Apache 2.0 de principio a fin)
Renderizamos cada página con pypdfium2 (un wrapper de Python sobre el motor PDFium de Google, Apache 2.0) a una escala de 2,5×: unos 180 DPI, suficiente para un reconocimiento de caracteres fiable. Cada imagen pasa por tesseract con un modelo multilingüe cargado: eng+spa+por+fra+deu+pol+ita+tur. Tesseract deduce el idioma real a partir de la forma de los glifos.
Nos alejamos a propósito de PyMuPDF — la librería de PDF más popular en Python — porque su licencia AGPL resulta incómoda para un servicio alojado. Cambiar a pypdfium2 nos llevó una tarde y eliminó por completo el riesgo legal. Vale la pena tenerlo en cuenta si estás creando algo con PDF para un producto comercial.
3. Detección automática de idioma
El libro de la lectora estaba en español, pero su idioma de interfaz era inglés. Así que, antes de la solución, incluso si el OCR hubiera funcionado, el pipeline habría sintetizado el texto en español con una voz inglesa (robótica, mal pronunciada). Ahora la propia detección de idioma usa el texto extraído por OCR. Tras 3 páginas de muestra, langdetect clasifica el contenido y elige la voz correcta: en este caso, español latinoamericano.
4. Un camino de error honesto
Si el OCR aun así recupera menos de 100 caracteres (PDF solo decorativos, archivos corruptos), ahora lanzamos un error claro en lugar de generar silencio: "Este PDF no tiene texto extraíble. Sube un EPUB, un TXT o un PDF con texto." El trabajo de audiolibro queda marcado como fallido, no se envía correo y no se cobran créditos.
¿Tienes un PDF escaneado? Pruébalo ya.
MimicReader es gratis la primera hora de audio cada mes. Sin tarjeta. Suelta cualquier PDF — con texto o escaneado — y nosotros nos encargamos del resto.
Empezar gratisEl resultado
Pasamos otra vez el PDF de la lectora por el pipeline reconstruido. Cinco minutos de OCR extrajeron 144.710 caracteres de español limpio de sus 74 páginas escaneadas. Después, el pipeline lo dividió en 1.127 segmentos y produjo un audiolibro de 2 horas y 43 minutos con sincronización para seguir la lectura: resaltado palabra por palabra atado al audio. Le escribimos en español, invitándola por la casa, y le pedimos disculpas por el primer intento.
La regeneración completa tomó unos 90 minutos de tiempo real: aproximadamente 5 minutos de OCR, 80 minutos de texto a voz y unos cuantos minutos para normalizar el audio (EBU R128) y empaquetarlo en M4A. Es más lento que un PDF de texto, pero funciona. Antes, simplemente no funcionaba.
Qué significa esto si tienes una estantería llena de escaneos
Si has estado guardando libros escaneados — reediciones antiguas, novelas descatalogadas, digitalizaciones de dominio público de archive.org, tus propios escaneos del recetario de la abuela — ya no se quedan atrapados en el papel. Súbelos. Nosotros nos ocupamos del OCR.
Por ahora hacemos OCR en 12 idiomas: inglés, español, portugués, francés, alemán, polaco, italiano, turco, árabe, japonés, coreano e hindi. El audiolibro en sí puede generarse en cualquiera de los 23 idiomas de voz. Si tu libro escaneado está en un idioma que aún no procesamos por OCR, escríbenos: añadir un paquete de idioma a tesseract lleva unos minutos.
Nota sobre licencias comerciales
Todo el stack de OCR que usamos — tesseract, pypdfium2, pytesseract — es Apache 2.0. Esto importa si estás construyendo algo parecido: PyMuPDF es la opción fácil para renderizar PDF en Python, pero su licencia AGPL te obliga a publicar como código abierto todo tu SaaS si lo usas en producción. pypdfium2 + tesseract te da las mismas capacidades sin esa resaca legal.
El bug que nos hizo mejores
La mayoría de los bugs de producción se atrapan en los tests. Este no, porque la suposición — "los PDF contienen texto" — se cumplía en todos los archivos de desarrollo que habíamos usado. Hizo falta una lectora real de Chile, en su primera hora en la plataforma, para sacarlo a la luz.
Así que gracias, lectores y lectoras de verdad. Encontráis los bugs que nosotros no podemos.