import gradio as gr import subprocess import logging import os import tempfile import shlex from gradio_pdf import PDF # Configuración de logs logger = logging.getLogger(__name__) logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s") def ejecutar_comando(comando): """Ejecuta un comando de shell y maneja errores.""" try: resultado = subprocess.run(comando, shell=True, check=True, capture_output=True, text=True) logger.info(f"Comando ejecutado: {comando}\nSalida:\n{resultado.stdout}") return resultado.stdout except subprocess.CalledProcessError as e: error_message = f"Error al ejecutar el comando: {comando}\nError: {e}\nSalida de error:\n{e.stderr}" logger.error(error_message) raise RuntimeError(error_message) def reparar_pdf(input_pdf, output_pdf): """Repara un PDF usando qpdf.""" comando = f"qpdf --linearize {shlex.quote(input_pdf)} {shlex.quote(output_pdf)}" ejecutar_comando(comando) def simplificar_pdf(input_pdf, output_pdf): """Simplifica un PDF usando Ghostscript.""" comando = f"gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/screen -dNOPAUSE -dBATCH -sOutputFile={shlex.quote(output_pdf)} {shlex.quote(input_pdf)}" ejecutar_comando(comando) def crear_pdf_con_texto_incrustado(pdf_original, archivo_salida, idioma="spa"): """Procesa un PDF con OCR usando OCRmyPDF.""" comando = f"ocrmypdf -l {idioma} --force-ocr --deskew --output-type pdf {shlex.quote(pdf_original)} {shlex.quote(archivo_salida)}" try: output = ejecutar_comando(comando) logger.info(f"Salida de ocrmypdf: {output}") except RuntimeError as e: logger.error(f"Error en ocrmypdf: {e}") raise def mostrar_pdf(ruta_pdf): """ Devuelve un HTML con un iframe que usa PDF.js para mostrar un archivo PDF. """ if ruta_pdf: # Asegúrate de usar rutas correctas para los archivos procesados return f"""
""" return "No se pudo generar la vista previa del PDF.
" def flujo_principal(pdf_file, idioma="spa"): """Procesa un PDF subido con reparación, simplificación y OCR.""" if not pdf_file: raise gr.Error("No se subió ningún archivo.") with tempfile.NamedTemporaryFile(suffix=".pdf", delete=False) as temp_pdf: try: reparar_pdf(pdf_file, temp_pdf.name) simplificar_pdf(temp_pdf.name, temp_pdf.name) crear_pdf_con_texto_incrustado(temp_pdf.name, temp_pdf.name, idioma) ruta_final = temp_pdf.name # Crear vista previa para PDF.js pdf_vista_html = mostrar_pdf(ruta_final) return pdf_vista_html, gr.File(value=ruta_final, label="Descargar PDF procesado") except Exception as e: logger.exception(f"Error durante el procesamiento: {e}") raise gr.Error(f"Error al procesar el PDF: {e}") finally: if os.path.exists(temp_pdf.name): os.remove(temp_pdf.name) # Interfaz Gradio with gr.Blocks() as interfaz: gr.Markdown("## Procesador de PDFs con OCR") with gr.Row(): archivo_pdf = gr.File(label="Sube tu archivo PDF") idioma_ocr = gr.Dropdown(["spa", "eng", "fra", "deu"], label="Idioma OCR", value="spa") boton_procesar = gr.Button("Procesar OCR") with gr.Row(): pdf_vista = gr.HTML(label="Visor PDF") # Cambiado a gr.HTML pdf_descarga = gr.File(label="Descargar PDF procesado", visible=False) boton_procesar.click( fn=flujo_principal, inputs=[archivo_pdf, idioma_ocr], outputs=[pdf_vista, pdf_descarga], ) if __name__ == "__main__": interfaz.launch()