Spaces:
Sleeping
Sleeping
jersonalvr
commited on
Update app.py
Browse files
app.py
CHANGED
@@ -129,7 +129,7 @@ def cargar_modelo_traduccion(origen, destino):
|
|
129 |
|
130 |
def traducir_texto(tokenizer, model, textos, dispositivo, batch_size=8):
|
131 |
"""
|
132 |
-
|
133 |
"""
|
134 |
if not textos: # Add a check for empty text list
|
135 |
logger.warning("Lista de textos vacía. Saltando traducción.")
|
@@ -279,9 +279,10 @@ def ajustar_tamano_fuente(texto, bbox, c, max_width, tamaño_fuente_original):
|
|
279 |
logger.warning(f"Error al ajustar tamaño de fuente: {e}")
|
280 |
return tamaño_fuente_original
|
281 |
|
282 |
-
def
|
283 |
"""
|
284 |
Extrae el contenido del PDF, traduce el texto y crea un nuevo PDF traducido.
|
|
|
285 |
"""
|
286 |
try:
|
287 |
documento = fitz.open(archivo_pdf.name)
|
@@ -317,7 +318,8 @@ def extraer_y_traducir_pdf(archivo_pdf, tokenizer, model, dispositivo, idioma_de
|
|
317 |
if not textos:
|
318 |
logger.warning("No se encontraron textos válidos para traducir en el PDF.")
|
319 |
documento.close()
|
320 |
-
|
|
|
321 |
|
322 |
# Traducir texto
|
323 |
try:
|
@@ -339,14 +341,14 @@ def extraer_y_traducir_pdf(archivo_pdf, tokenizer, model, dispositivo, idioma_de
|
|
339 |
for numero_pagina in range(total_paginas):
|
340 |
pagina = documento.load_page(numero_pagina)
|
341 |
rect = pagina.rect
|
342 |
-
|
343 |
|
344 |
# Ajustar el tamaño de página al tamaño original del PDF
|
345 |
-
c.setPageSize((
|
346 |
|
347 |
# Definir márgenes dinámicos en base al tamaño de la página, ej: 5% de ancho y alto
|
348 |
-
margen_x =
|
349 |
-
margen_y =
|
350 |
|
351 |
# Procesar texto de esta página
|
352 |
pagina_bloques = pagina.get_text("dict")["blocks"]
|
@@ -375,7 +377,7 @@ def extraer_y_traducir_pdf(archivo_pdf, tokenizer, model, dispositivo, idioma_de
|
|
375 |
|
376 |
# Ajustar coordenadas al sistema de ReportLab (y invertida)
|
377 |
x = x0
|
378 |
-
y =
|
379 |
|
380 |
# Buscar fuente similar
|
381 |
fuente_encontrada = buscar_fuente_similar(font, fuentes_sistema)
|
@@ -389,7 +391,7 @@ def extraer_y_traducir_pdf(archivo_pdf, tokenizer, model, dispositivo, idioma_de
|
|
389 |
c.setFont(fuente_encontrada, size)
|
390 |
|
391 |
# Ajustar el tamaño del texto si excede el ancho disponible
|
392 |
-
max_width = (x1 - x0) - margen_x if (x1 - x0) > 0 else (
|
393 |
nuevo_tamaño = ajustar_tamano_fuente(texto_traducido, bbox, c, max_width, size)
|
394 |
|
395 |
# Establecer el nuevo tamaño de fuente
|
@@ -425,29 +427,33 @@ def extraer_y_traducir_pdf(archivo_pdf, tokenizer, model, dispositivo, idioma_de
|
|
425 |
imagen_path = os.path.join(tempfile.gettempdir(), f"imagen_{numero_pagina}.png")
|
426 |
img.save(imagen_path)
|
427 |
img.close()
|
428 |
-
c.drawImage(imagen_path, x0,
|
429 |
|
430 |
except Exception as e:
|
431 |
logger.error(f"Error al procesar imagen: {e}")
|
432 |
continue
|
433 |
-
|
|
|
|
|
|
|
434 |
c.showPage()
|
435 |
|
436 |
c.save()
|
437 |
documento.close()
|
|
|
438 |
return pdf_traducido_path
|
439 |
-
|
440 |
except Exception as e:
|
441 |
-
logger.error(f"Error
|
442 |
-
return archivo_pdf.name
|
443 |
|
444 |
-
def pdf_preview(
|
445 |
"""
|
446 |
-
Previsualiza
|
447 |
"""
|
448 |
try:
|
449 |
-
doc = fitz.open(
|
450 |
-
|
|
|
|
|
451 |
pix = page.get_pixmap()
|
452 |
image = np.frombuffer(pix.samples, np.uint8).reshape(pix.height, pix.width, pix.n)
|
453 |
if pix.n == 4:
|
@@ -510,11 +516,16 @@ def boton_actualizar_fuentes(files):
|
|
510 |
|
511 |
def procesar_pdf(archivo_pdf, fuentes_subidas):
|
512 |
"""
|
513 |
-
Función
|
|
|
514 |
"""
|
515 |
try:
|
516 |
if not archivo_pdf:
|
517 |
-
|
|
|
|
|
|
|
|
|
518 |
|
519 |
# Extraer texto para detectar el idioma
|
520 |
documento = fitz.open(archivo_pdf.name)
|
@@ -528,29 +539,27 @@ def procesar_pdf(archivo_pdf, fuentes_subidas):
|
|
528 |
# Si el idioma de origen y destino son iguales, no realizar traducción
|
529 |
if idioma_origen == idioma_sistema:
|
530 |
logger.info("El idioma de origen y destino son iguales. No se realizará la traducción.")
|
531 |
-
|
|
|
532 |
|
533 |
# Cargar el modelo de traducción automáticamente
|
534 |
tokenizer, model, dispositivo = cargar_modelo_traduccion(idioma_origen, idioma_sistema)
|
535 |
|
536 |
-
#
|
537 |
-
|
|
|
|
|
|
|
|
|
|
|
538 |
|
539 |
-
|
|
|
|
|
|
|
540 |
except Exception as e:
|
541 |
logger.error(f"Error en procesar_pdf: {e}")
|
542 |
-
|
543 |
-
|
544 |
-
def actualizar_fuentes_cache():
|
545 |
-
"""
|
546 |
-
Función para actualizar el caché de fuentes.
|
547 |
-
"""
|
548 |
-
try:
|
549 |
-
cachear_fuentes()
|
550 |
-
return "Fuentes cacheadas exitosamente."
|
551 |
-
except Exception as e:
|
552 |
-
logger.error(f"Error al cachear fuentes: {e}")
|
553 |
-
return f"Error al cachear fuentes: {e}"
|
554 |
|
555 |
# Interfaz de usuario con Gradio
|
556 |
with gr.Blocks(
|
@@ -577,17 +586,24 @@ with gr.Blocks(
|
|
577 |
with gr.Column(scale=1):
|
578 |
gr.Markdown("## Vista Previa")
|
579 |
preview = gr.Image(label="Vista Previa", visible=True)
|
|
|
580 |
traducir_btn = gr.Button("Traducir PDF")
|
581 |
-
|
|
|
|
|
582 |
traducir_btn.click(
|
583 |
fn=procesar_pdf,
|
584 |
inputs=[pdf_input, fuentes_subidas],
|
585 |
-
outputs=[
|
|
|
586 |
)
|
587 |
|
588 |
# Vista previa del PDF
|
|
|
|
|
|
|
589 |
pdf_input.change(
|
590 |
-
fn=
|
591 |
inputs=pdf_input,
|
592 |
outputs=preview
|
593 |
)
|
|
|
129 |
|
130 |
def traducir_texto(tokenizer, model, textos, dispositivo, batch_size=8):
|
131 |
"""
|
132 |
+
Traduce una lista de textos utilizando el modelo y tokenizer proporcionados.
|
133 |
"""
|
134 |
if not textos: # Add a check for empty text list
|
135 |
logger.warning("Lista de textos vacía. Saltando traducción.")
|
|
|
279 |
logger.warning(f"Error al ajustar tamaño de fuente: {e}")
|
280 |
return tamaño_fuente_original
|
281 |
|
282 |
+
def extraer_y_traducir_pdf_generador(archivo_pdf, tokenizer, model, dispositivo, idioma_destino):
|
283 |
"""
|
284 |
Extrae el contenido del PDF, traduce el texto y crea un nuevo PDF traducido.
|
285 |
+
Esta versión utiliza 'yield' para emitir actualizaciones.
|
286 |
"""
|
287 |
try:
|
288 |
documento = fitz.open(archivo_pdf.name)
|
|
|
318 |
if not textos:
|
319 |
logger.warning("No se encontraron textos válidos para traducir en el PDF.")
|
320 |
documento.close()
|
321 |
+
yield ("No se encontraron textos para traducir.", None)
|
322 |
+
return pdf_traducido_path
|
323 |
|
324 |
# Traducir texto
|
325 |
try:
|
|
|
341 |
for numero_pagina in range(total_paginas):
|
342 |
pagina = documento.load_page(numero_pagina)
|
343 |
rect = pagina.rect
|
344 |
+
ancho_pagina, alto_pagina = rect.width, rect.height
|
345 |
|
346 |
# Ajustar el tamaño de página al tamaño original del PDF
|
347 |
+
c.setPageSize((ancho_pagina, alto_pagina))
|
348 |
|
349 |
# Definir márgenes dinámicos en base al tamaño de la página, ej: 5% de ancho y alto
|
350 |
+
margen_x = ancho_pagina * 0.05
|
351 |
+
margen_y = alto_pagina * 0.05
|
352 |
|
353 |
# Procesar texto de esta página
|
354 |
pagina_bloques = pagina.get_text("dict")["blocks"]
|
|
|
377 |
|
378 |
# Ajustar coordenadas al sistema de ReportLab (y invertida)
|
379 |
x = x0
|
380 |
+
y = alto_pagina - y1
|
381 |
|
382 |
# Buscar fuente similar
|
383 |
fuente_encontrada = buscar_fuente_similar(font, fuentes_sistema)
|
|
|
391 |
c.setFont(fuente_encontrada, size)
|
392 |
|
393 |
# Ajustar el tamaño del texto si excede el ancho disponible
|
394 |
+
max_width = (x1 - x0) - margen_x if (x1 - x0) > 0 else (ancho_pagina - 2 * margen_x)
|
395 |
nuevo_tamaño = ajustar_tamano_fuente(texto_traducido, bbox, c, max_width, size)
|
396 |
|
397 |
# Establecer el nuevo tamaño de fuente
|
|
|
427 |
imagen_path = os.path.join(tempfile.gettempdir(), f"imagen_{numero_pagina}.png")
|
428 |
img.save(imagen_path)
|
429 |
img.close()
|
430 |
+
c.drawImage(imagen_path, x0, alto_pagina - y1 - alto_img, width=ancho_img, height=alto_img)
|
431 |
|
432 |
except Exception as e:
|
433 |
logger.error(f"Error al procesar imagen: {e}")
|
434 |
continue
|
435 |
+
|
436 |
+
# Emitir estado y vista previa de la página actual
|
437 |
+
yield (f"Traduciendo página {numero_pagina + 1} de {total_paginas} al idioma {idioma_destino}...", pdf_preview(archivo_pdf.name, numero_pagina))
|
438 |
+
|
439 |
c.showPage()
|
440 |
|
441 |
c.save()
|
442 |
documento.close()
|
443 |
+
yield ("Traducción completada exitosamente.", pdf_preview(pdf_traducido_path, pagina=0))
|
444 |
return pdf_traducido_path
|
|
|
445 |
except Exception as e:
|
446 |
+
logger.error(f"Error al extraer y traducir pdf: {e}")
|
|
|
447 |
|
448 |
+
def pdf_preview(file_path, pagina=0):
|
449 |
"""
|
450 |
+
Previsualiza una página específica del PDF como una imagen.
|
451 |
"""
|
452 |
try:
|
453 |
+
doc = fitz.open(file_path)
|
454 |
+
if pagina >= len(doc):
|
455 |
+
pagina = 0 # Fallback a la primera página si el número es inválido
|
456 |
+
page = doc[pagina]
|
457 |
pix = page.get_pixmap()
|
458 |
image = np.frombuffer(pix.samples, np.uint8).reshape(pix.height, pix.width, pix.n)
|
459 |
if pix.n == 4:
|
|
|
516 |
|
517 |
def procesar_pdf(archivo_pdf, fuentes_subidas):
|
518 |
"""
|
519 |
+
Función generadora para procesar y traducir el PDF.
|
520 |
+
Emite actualizaciones de estado y vista previa durante el proceso.
|
521 |
"""
|
522 |
try:
|
523 |
if not archivo_pdf:
|
524 |
+
yield ("No se ha subido ningún archivo PDF.", None, None)
|
525 |
+
return
|
526 |
+
|
527 |
+
# Emitir estado inicial
|
528 |
+
yield ("Iniciando traducción...", pdf_preview(archivo_pdf.name, pagina=0), None)
|
529 |
|
530 |
# Extraer texto para detectar el idioma
|
531 |
documento = fitz.open(archivo_pdf.name)
|
|
|
539 |
# Si el idioma de origen y destino son iguales, no realizar traducción
|
540 |
if idioma_origen == idioma_sistema:
|
541 |
logger.info("El idioma de origen y destino son iguales. No se realizará la traducción.")
|
542 |
+
yield ("El idioma de origen y destino son iguales. No se realizó la traducción.", pdf_preview(archivo_pdf.name, pagina=0), None)
|
543 |
+
return
|
544 |
|
545 |
# Cargar el modelo de traducción automáticamente
|
546 |
tokenizer, model, dispositivo = cargar_modelo_traduccion(idioma_origen, idioma_sistema)
|
547 |
|
548 |
+
# Realizar la traducción y emitir actualizaciones
|
549 |
+
generator = extraer_y_traducir_pdf_generador(
|
550 |
+
archivo_pdf, tokenizer, model, dispositivo, idioma_sistema
|
551 |
+
)
|
552 |
+
for update in generator:
|
553 |
+
status, imagen = update
|
554 |
+
yield (status, imagen, None)
|
555 |
|
556 |
+
# Emitir estado final
|
557 |
+
pdf_traducido_path = os.path.splitext(archivo_pdf.name)[0] + f"_traducido_{idioma_sistema}.pdf"
|
558 |
+
yield ("Traducción completada exitosamente.", pdf_preview(pdf_traducido_path, pagina=0), pdf_traducido_path)
|
559 |
+
|
560 |
except Exception as e:
|
561 |
logger.error(f"Error en procesar_pdf: {e}")
|
562 |
+
yield (f"Error en la traducción: {e}", None, None)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
563 |
|
564 |
# Interfaz de usuario con Gradio
|
565 |
with gr.Blocks(
|
|
|
586 |
with gr.Column(scale=1):
|
587 |
gr.Markdown("## Vista Previa")
|
588 |
preview = gr.Image(label="Vista Previa", visible=True)
|
589 |
+
status_md = gr.Markdown("**Estado:** Esperando traducción...")
|
590 |
traducir_btn = gr.Button("Traducir PDF")
|
591 |
+
traducir_output = gr.File(label="Descargar PDF traducido", visible=True)
|
592 |
+
|
593 |
+
# Configurar el botón para usar la función generadora
|
594 |
traducir_btn.click(
|
595 |
fn=procesar_pdf,
|
596 |
inputs=[pdf_input, fuentes_subidas],
|
597 |
+
outputs=[status_md, preview, traducir_output],
|
598 |
+
show_progress=True # Opcional: muestra una barra de progreso
|
599 |
)
|
600 |
|
601 |
# Vista previa del PDF
|
602 |
+
def actualizar_preview(file):
|
603 |
+
return pdf_preview(file.name, pagina=0) if file else None
|
604 |
+
|
605 |
pdf_input.change(
|
606 |
+
fn=actualizar_preview,
|
607 |
inputs=pdf_input,
|
608 |
outputs=preview
|
609 |
)
|