import gradio as gr import subprocess import logging import tempfile import os import shutil # Configurar logging logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') def ejecutar_comando(comando, mensaje_exito="", mensaje_error=""): """Ejecuta un comando de shell y maneja errores.""" try: resultado = subprocess.run(comando, shell=True, check=True, capture_output=True, text=True) if mensaje_exito: logging.info(f"{mensaje_exito}. Salida:\n{resultado.stdout}") return resultado.stdout except subprocess.CalledProcessError as e: error_message = f"{mensaje_error}. Error: {e}\nSalida de error:\n{e.stderr}" logging.error(error_message) raise RuntimeError(error_message) def reparar_pdf(input_pdf, output_pdf): """Repara un PDF usando qpdf.""" comando = f"qpdf --linearize '{input_pdf}' '{output_pdf}'" ejecutar_comando( comando, mensaje_exito="PDF reparado correctamente.", mensaje_error="Error al reparar el PDF." ) def convertir_pdf_a_compatible(input_pdf, output_pdf): """Convierte el PDF a un formato compatible usando pdftocairo.""" comando = f"pdftocairo -pdf '{input_pdf}' '{output_pdf}'" ejecutar_comando( comando, mensaje_exito="PDF convertido a un formato compatible.", mensaje_error="Error al convertir el PDF a un formato compatible." ) def procesar_pdf_con_ocr(pdf_subido, idioma="spa"): """Procesa un PDF subido con OCR y devuelve la ruta del archivo procesado.""" if not pdf_subido: raise gr.Error("No se subió ningún archivo.") try: # Copiar el archivo subido a un nombre seguro safe_input_pdf = tempfile.NamedTemporaryFile(delete=False, suffix=".pdf").name shutil.copy(pdf_subido.name, safe_input_pdf) reparado_pdf = tempfile.NamedTemporaryFile(delete=False, suffix=".pdf").name convertido_pdf = tempfile.NamedTemporaryFile(delete=False, suffix=".pdf").name output_pdf = tempfile.NamedTemporaryFile(delete=False, suffix=".pdf").name # Reparar el PDF reparar_pdf(safe_input_pdf, reparado_pdf) # Convertir el PDF a un formato compatible convertir_pdf_a_compatible(reparado_pdf, convertido_pdf) # Ejecutar OCR en el PDF convertido comando = f"ocrmypdf -l {idioma} --force-ocr --deskew --output-type pdf '{convertido_pdf}' '{output_pdf}'" logging.info(f"Ejecutando comando: {comando}") ejecutar_comando( comando, mensaje_exito="OCR completado correctamente.", mensaje_error="Error al ejecutar el OCR." ) # Verificar que el archivo de salida se haya creado if not os.path.exists(output_pdf): raise gr.Error("El archivo procesado no se generó correctamente.") return output_pdf # Ruta del archivo procesado except Exception as e: logging.error(f"Error al procesar el PDF: {e}") raise gr.Error(f"Ocurrió un error al procesar el archivo: {e}") def interfaz_ocr(): """Crea la interfaz Gradio para el flujo de OCR.""" with gr.Blocks() as app: gr.Markdown("## Procesador de PDFs con OCR") 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") salida_descarga = gr.File(label="Descargar PDF Procesado") def procesar_y_descargar(pdf_file, idioma): """Procesa el PDF subido y lo devuelve para descarga.""" return procesar_pdf_con_ocr(pdf_file, idioma) boton_procesar.click( fn=procesar_y_descargar, inputs=[archivo_pdf, idioma_ocr], outputs=[salida_descarga], ) return app if __name__ == "__main__": interfaz_ocr().launch()