gnosticdev commited on
Commit
5859700
·
verified ·
1 Parent(s): c461e0c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +79 -62
app.py CHANGED
@@ -1,70 +1,87 @@
1
  import gradio as gr
2
- import numpy as np
3
- from scipy import signal
 
4
 
5
- # Tabla DTMF estándar
6
- DTMF_TABLE = {
7
- (697, 1209): '1', (697, 1336): '2', (697, 1477): '3', (697, 1633): 'A',
8
- (770, 1209): '4', (770, 1336): '5', (770, 1477): '6', (770, 1633): 'B',
9
- (852, 1209): '7', (852, 1336): '8', (852, 1477): '9', (852, 1633): 'C',
10
- (941, 1209): '*', (941, 1336): '0', (941, 1477): '#', (941, 1633): 'D'
11
- }
12
 
13
- def detectar_dtmf(audio, samplerate):
14
- ventana = int(0.1 * samplerate)
15
- paso = int(0.05 * samplerate)
16
- teclas = []
17
- frecuencias_dtmf = [697, 770, 852, 941, 1209, 1336, 1477, 1633]
18
-
19
- for inicio in range(0, len(audio) - ventana, paso):
20
- segmento = audio[inicio:inicio + ventana]
21
- fft = np.fft.rfft(segmento)
22
- freqs = np.fft.rfftfreq(len(segmento), 1/samplerate)
23
- magnitud = np.abs(fft)
24
- magnitud = magnitud / np.max(magnitud)
25
-
26
- detectadas = []
27
- for f_target in frecuencias_dtmf:
28
- idx = np.argmin(np.abs(freqs - f_target))
29
- if magnitud[idx] > 0.3:
30
- detectadas.append(f_target)
31
-
32
- if len(detectadas) == 2:
33
- baja, alta = min(detectadas), max(detectadas)
34
- for (fb, fa), tecla in DTMF_TABLE.items():
35
- if abs(baja - fb) < 10 and abs(alta - fa) < 10:
36
- teclas.append((inicio/samplerate, tecla))
37
- break
38
- return teclas
39
 
40
- def audio_a_letras(audio):
41
- if audio is None:
42
- return "Esperando audio..."
43
-
44
- samplerate, data = audio
45
- if len(data.shape) > 1:
46
- data = data.mean(axis=1)
47
- if data.dtype in (np.float32, np.float64):
48
- data = (data * 32767).astype(np.int16)
49
 
50
- teclas = detectar_dtmf(data, samplerate)
51
-
52
- if not teclas:
53
- return "No se detectaron tonos DTMF"
54
-
55
- resultado = "TECLAS:\n"
56
- for t, tecla in teclas:
57
- resultado += f"{t:.2f}s: {tecla}\n"
58
- resultado += f"\nTEXTO: {''.join([t[1] for t in teclas])}"
59
- return resultado
 
 
 
 
60
 
61
- with gr.Blocks() as demo:
62
- gr.Markdown("# Decodificador DTMF")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  with gr.Row():
64
- # 👇 ESTA ES LA LÍNEA CORREGIDA
65
- audio = gr.Audio(sources=["microphone"], type="numpy", label="Grabar o subir")
66
- btn = gr.Button("Decodificar")
67
- texto = gr.Textbox(label="Resultado", lines=10)
68
- btn.click(fn=audio_a_letras, inputs=audio, outputs=texto)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
 
70
- demo.launch()
 
 
1
  import gradio as gr
2
+ import whisper
3
+ import os
4
+ import torch
5
 
6
+ # --- Configuración Global ---
7
+ # Usamos 'tiny' para velocidad en CPU gratis.
8
+ # Cambiar a 'base' si tienes GPU pagada o más paciencia.
9
+ MODEL_NAME = "tiny"
10
+ device = "cuda" if torch.cuda.is_available() else "cpu"
 
 
11
 
12
+ print(f"🌀 Cargando modelo Whisper ({MODEL_NAME}) en {device}...")
13
+ try:
14
+ model = whisper.load_model(MODEL_NAME, device=device)
15
+ print("✅ Modelo cargado correctamente.")
16
+ except Exception as e:
17
+ print(f"⚠️ Error cargando modelo: {e}")
18
+ model = None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
+ def analizar_audio_evp(audio_path):
21
+ """
22
+ Analiza el audio buscando patrones lingüísticos en el ruido.
23
+ """
24
+ if model is None:
25
+ return "❌ Error: El modelo no se cargó correctamente en el servidor."
 
 
 
26
 
27
+ if audio_path is None:
28
+ return "⚠️ No se detectó audio. Por favor graba o sube un archivo."
29
+
30
+ try:
31
+ # Opciones de transcripción agresivas para EVP
32
+ # temperature=0.8 ayuda a encontrar patrones en ruido (menos determinista)
33
+ # condition_on_previous_text=False evita que el modelo se 'bloquee' si no oye nada claro
34
+ options = {
35
+ "language": "es",
36
+ "fp16": False if device == "cpu" else True, # FP16 suele fallar en CPU
37
+ "temperature": 0.8,
38
+ "condition_on_previous_text": False,
39
+ "verbose": False
40
+ }
41
 
42
+ print(f"🔍 Analizando archivo: {audio_path}...")
43
+ result = model.transcribe(audio_path, **options)
44
+ texto = result["text"].strip()
45
+
46
+ if texto:
47
+ return f"👻 **PATRÓN DETECTADO:**\n\n"{texto}""
48
+ else:
49
+ return "💤 **SIN PATRONES:**\n\nEl IA no encontró estructuras lingüísticas claras en este ruido (o el silencio es absoluto)."
50
+
51
+ except Exception as e:
52
+ return f"⚠️ **ERROR DE PROCESAMIENTO:**\n\n{str(e)}"
53
+
54
+ # --- Interfaz Gráfica (Gradio) ---
55
+ with gr.Blocks(theme=gr.themes.Soft(primary_hue="purple")) as demo:
56
+ gr.Markdown("""
57
+ # 🕵️‍♂️ Detector de Patrones Auditivos (EVP)
58
+ ## Sube un MP3 de "silencio" o graba tu habitación.
59
+ *La IA intentará encontrar palabras donde solo hay ruido.*
60
+ """)
61
+
62
  with gr.Row():
63
+ with gr.Column():
64
+ audio_input = gr.Audio(
65
+ label="🎙️ Fuente de Audio",
66
+ type="filepath", # Importante: devuelve la ruta del archivo
67
+ sources=["upload", "microphone"],
68
+ format="mp3" # Forzamos formato MP3
69
+ )
70
+ btn_analizar = gr.Button("🔮 Analizar Ruido", variant="primary")
71
+
72
+ with gr.Column():
73
+ output_text = gr.Textbox(
74
+ label="📜 Resultado del Análisis",
75
+ lines=5,
76
+ max_lines=10
77
+ )
78
+
79
+ # Conectar botón a función
80
+ btn_analizar.click(
81
+ fn=analizar_audio_evp,
82
+ inputs=audio_input,
83
+ outputs=output_text
84
+ )
85
 
86
+ if __name__ == "__main__":
87
+ demo.launch()