-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
154 lines (128 loc) · 5.96 KB
/
Copy pathapp.py
File metadata and controls
154 lines (128 loc) · 5.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import streamlit as st
import PyPDF2
import docx
import pptx
import tempfile
import asyncio
import edge_tts
import pytesseract
from PIL import Image
import textwrap
import os
import platform
import base64
st.set_page_config(page_title="Lector IA", page_icon="🎧", layout="wide")
st.markdown("<p style='text-align: center; font-size: 14px; font-style: italic; color: #e0c3fc;'>Para la más linda del mundo, Pili ❤️</p>", unsafe_allow_html=True)
if platform.system() == "Windows":
pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'
else:
pytesseract.pytesseract.tesseract_cmd = 'tesseract'
def extraer_texto_pdf(archivo):
lector = PyPDF2.PdfReader(archivo)
texto = ""
for pagina in lector.pages:
if pagina.extract_text():
texto += pagina.extract_text() + "\n"
return texto
def extraer_texto_word(archivo):
doc = docx.Document(archivo)
return "\n".join([parrafo.text for parrafo in doc.paragraphs])
def extraer_texto_pptx(archivo):
presentacion = pptx.Presentation(archivo)
texto = ""
for diapositiva in presentacion.slides:
for forma in diapositiva.shapes:
if hasattr(forma, "text"):
texto += forma.text + "\n"
texto += "\n"
return texto
def extraer_texto_imagen(archivo):
try:
imagen = Image.open(archivo)
imagen = imagen.convert('L')
texto = pytesseract.image_to_string(imagen, lang='spa')
return texto
except Exception as e:
return f"Error técnico del motor: {str(e)}"
async def generar_audio_largo(texto, ruta_salida, velocidad_tts, voz_tts):
fragmentos = textwrap.wrap(texto, width=3000, replace_whitespace=False)
barra_progreso = st.progress(0)
texto_estado = st.empty()
archivos_temporales = []
for i, fragmento in enumerate(fragmentos):
texto_estado.text(f"Procesando parte {i+1} de {len(fragmentos)}...")
with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as fp:
temp_path = fp.name
archivos_temporales.append(temp_path)
comunicador = edge_tts.Communicate(fragmento, voz_tts, rate=velocidad_tts)
await comunicador.save(temp_path)
barra_progreso.progress((i + 1) / len(fragmentos))
with open(ruta_salida, 'wb') as archivo_final:
for temp_path in archivos_temporales:
with open(temp_path, 'rb') as f:
archivo_final.write(f.read())
os.remove(temp_path)
texto_estado.text("¡Audio listo!")
st.title("🎧 Mi Lector de Resúmenes IA")
st.divider()
col_izq, col_der = st.columns([2, 1], gap="large")
texto_final = ""
with col_izq:
st.subheader("📄 1. Cargá tu material")
opcion = st.radio("¿Qué vas a usar?", ("Subir Archivo", "Pegar Texto"), horizontal=True)
if opcion == "Subir Archivo":
archivo_subido = st.file_uploader("PDF, Word, PPT o Foto",
type=["pdf", "docx", "pptx", "png", "jpg", "jpeg"])
if archivo_subido:
if archivo_subido.name.lower().endswith(".pdf"):
texto_final = extraer_texto_pdf(archivo_subido)
elif archivo_subido.name.lower().endswith(".docx"):
texto_final = extraer_texto_word(archivo_subido)
elif archivo_subido.name.lower().endswith(".pptx"):
texto_final = extraer_texto_pptx(archivo_subido)
elif archivo_subido.name.lower().endswith((".png", ".jpg", ".jpeg")):
try:
texto_final = extraer_texto_imagen(archivo_subido)
st.image(archivo_subido, caption="Imagen cargada", use_container_width=True)
except Exception as e:
st.error("Error al leer la foto. Asegurate que sea nítida.")
st.success("¡Contenido leído!")
with st.expander("Editar texto extraído"):
texto_final = st.text_area("Texto:", value=texto_final, height=200)
else:
texto_final = st.text_area("Pegá tu resumen acá:", height=300)
with col_der:
st.subheader("⚙️ 2. Ajustes")
with st.expander("Voz y Velocidad", expanded=True):
voces = {
"🇦🇷 Tomás (Arg)": "es-AR-TomasNeural",
"🇦🇷 Elena (Arg)": "es-AR-ElenaNeural",
"🇪🇸 Álvaro (Esp)": "es-ES-AlvaroNeural",
"🇲🇽 Dalia (Mex)": "es-MX-DaliaNeural"
}
voz_elegida = voces[st.radio("Elegí acento:", list(voces.keys()))]
st.divider()
velocidades = {
"Muy Lento (0.5x)": "-50%",
"Lento (0.75x)": "-25%",
"Normal (1x)": "+0%",
"Rápido (1.25x)": "+25%",
"Repaso (1.5x)": "+50%",
"Turbo (2.0x)": "+100%"
}
velocidad_elegida = velocidades[st.radio("Velocidad:", list(velocidades.keys()), index=2)]
st.divider()
_, col_btn, _ = st.columns([1, 2, 1])
with col_btn:
if texto_final and st.button("🔊 GENERAR AUDIO", use_container_width=True):
try:
with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as fp:
archivo_audio = fp.name
asyncio.run(generar_audio_largo(texto_final, archivo_audio, velocidad_elegida, voz_elegida))
with open(archivo_audio, "rb") as f:
audio_bytes = f.read()
audio_b64 = base64.b64encode(audio_bytes).decode()
st.markdown(f'<audio controls style="width: 100%;"><source src="data:audio/mpeg;base64,{audio_b64}" type="audio/mpeg"></audio>', unsafe_allow_html=True)
st.download_button("⬇️ Descargar MP3", data=audio_bytes, file_name="resumen.mp3", mime="audio/mp3", use_container_width=True)
except Exception as e:
st.error(f"Error: {e}")