From 8ff94186b8ae284cd9364eff4c6957ed33546eb5 Mon Sep 17 00:00:00 2001 From: josemanuel Date: Thu, 15 May 2025 05:34:38 +0100 Subject: [PATCH] Subir archivos a "V00" --- V00/captura_audio_comentado.py | 187 +++++++++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 V00/captura_audio_comentado.py diff --git a/V00/captura_audio_comentado.py b/V00/captura_audio_comentado.py new file mode 100644 index 0000000..9ef45d9 --- /dev/null +++ b/V00/captura_audio_comentado.py @@ -0,0 +1,187 @@ +""" +=========================================================== +INSTALACIÓN DE PYTHON Y DEPENDENCIAS (SISTEMA WINDOWS) +=========================================================== + +1. INSTALACIÓN DE PYTHON: + - Descarga Python para Windows desde: https://www.python.org/downloads/windows/ + - Se recomienda instalar Python 3.12 o superior. + - Durante la instalación, asegúrate de marcar la opción "Add Python to PATH" para que puedas ejecutar Python y pip desde la línea de comandos. + +2. CONFIGURACIÓN DEL ENTORNO: + - Abre una ventana de comandos (CMD o PowerShell). + +3. INSTALACIÓN DE DEPENDENCIAS: + Ejecuta los siguientes comandos para instalar las dependencias necesarias: + + pip install sounddevice -> Para capturar audio en tiempo real. + pip install numpy -> Para operaciones numéricas y manejo de arrays. + pip install openai-whisper -> Para transcripción con el modelo Whisper. + * Requiere además: + - ffmpeg: Descárgalo desde https://ffmpeg.org/download.html#build-windows y agrega la carpeta "bin" al PATH. + - PyTorch: Instálalo siguiendo las instrucciones en https://pytorch.org/ + pip install pydub -> Para manipulación y segmentación de audio (requiere ffmpeg instalado y en el PATH). + pip install pyAudioAnalysis -> (No se usará la diarización en este script, pero se puede instalar para otros usos). + pip install hmmlearn -> Dependencia de pyAudioAnalysis. + pip install matplotlib -> Usado por pyAudioAnalysis para gráficos. + pip install eyed3 -> Dependencia de pyAudioAnalysis para manejo de metadatos. + pip install imbalanced-learn -> En algunos casos requerido por pyAudioAnalysis. + pip install plotly -> En algunos casos requerido por pyAudioAnalysis. + pip install SpeechRecognition -> Para Google Speech-to-Text. + +4. EJECUCIÓN DEL SCRIPT: + - Guarda este código en un archivo (por ejemplo, "transcriptor.py"). + - Ejecuta el script desde la línea de comandos con: + python transcriptor.py + - Sigue las instrucciones en pantalla para ingresar el código de idioma para Google Speech-to-Text. + +Nota: En Windows, para capturar el audio del sistema (lo que se reproduce en el sistema), puede ser necesario configurar el dispositivo WASAPI loopback. +=========================================================== +""" + +import sounddevice as sd # Captura de audio en tiempo real +import numpy as np # Procesamiento numérico +import queue # Manejo de colas +import threading # Para procesamiento en segundo plano (hilos) +import time # Funciones de tiempo y pausas +import wave # Manejo de archivos WAV +import os # Operaciones con archivos/sistema +import datetime # Para trabajar con fechas y horas +import whisper # Transcripción con modelo Whisper (openai-whisper) +from pydub import AudioSegment # Manipulación de audio (pydub) +import speech_recognition as sr # Transcripción con Google Speech-to-Text + +# ================== Configuración ================== +SAMPLE_RATE = 44100 # Frecuencia de muestreo (Hz) +CHUNK_DURATION = 6 # Duración en segundos de cada fragmento a procesar +MIN_VOLUME_THRESHOLD = 0.003 # Umbral mínimo de RMS para descartar silencios excesivos +transcription_file = "250506_UNIVERSAL_ROBOTS_ROBOPLUS.txt" # Archivo donde se guardará la transcripción + +# Para Whisper: Si TARGET_LANGUAGE es None, Whisper detecta automáticamente el idioma. +TARGET_LANGUAGE = 'es' # Ejemplo: 'es' para español + +# Cola para almacenar los fragmentos de audio capturados +audio_queue = queue.Queue() + +# Cargar el modelo Whisper (puedes elegir 'base', 'small', 'medium', etc.) +print("Cargando modelo Whisper...") +model = whisper.load_model('base') +print("Modelo cargado.") + +# ================== Captura de Audio ================== +def audio_callback(indata, frames, time_info, status): + """ + Callback de sounddevice para capturar audio en tiempo real. + Los datos se copian y se colocan en la cola para su posterior procesamiento. + """ + if status: + print("Status:", status) + audio_queue.put(indata.copy()) + +# ================== Procesamiento en Segundo Plano ================== +def process_audio(): + """ + Acumula fragmentos de audio hasta alcanzar CHUNK_DURATION segundos y luego los procesa. + """ + audio_buffer = [] + samples_needed = int(CHUNK_DURATION * SAMPLE_RATE) + while True: + try: + data = audio_queue.get(timeout=1) + audio_buffer.append(data) + total_samples = sum(chunk.shape[0] for chunk in audio_buffer) + if total_samples >= samples_needed: + # Concatenar los fragmentos acumulados en un único fragmento + audio_chunk = np.concatenate(audio_buffer, axis=0) + audio_buffer = [] # Reiniciar buffer tras el procesamiento + process_chunk(audio_chunk) + except queue.Empty: + continue + +def process_chunk(chunk): + """ + Procesa un fragmento de audio completo: + 1. Verifica que el audio no esté en silencio (según el umbral). + 2. Guarda el fragmento en un archivo WAV temporal. + 3. Transcribe el fragmento utilizando tanto Whisper como Google Speech-to-Text. + 4. Guarda la transcripción (con timestamp) en 'transcripcion.txt' y elimina los archivos temporales. + """ + # Calcular RMS y el volumen máximo del fragmento + rms = np.sqrt(np.mean(chunk**2)) + max_volume = np.max(np.abs(chunk)) + print(f"RMS: {rms:.5f}, Volumen máximo detectado: {max_volume:.5f}") + + if rms < MIN_VOLUME_THRESHOLD: + print("Fragmento demasiado silencioso. Se omite.") + return + + # Convertir de float32 (rango [-1, 1]) a int16 + chunk_int16 = np.int16(chunk * 32767) + + temp_filename = "temp_audio.wav" + try: + with wave.open(temp_filename, 'wb') as wf: + channels = chunk.shape[1] if chunk.ndim > 1 else 1 + wf.setnchannels(channels) + wf.setsampwidth(2) # 2 bytes para int16 + wf.setframerate(SAMPLE_RATE) + wf.writeframes(chunk_int16.tobytes()) + except Exception as e: + print("Error al guardar el archivo temporal:", e) + return + + # Registrar el timestamp de inicio del fragmento + chunk_start_time = datetime.datetime.now() + + # ----------------- Transcripción con Whisper ----------------- + try: + if TARGET_LANGUAGE is not None: + result_whisper = model.transcribe(temp_filename, language=TARGET_LANGUAGE) + else: + result_whisper = model.transcribe(temp_filename) + text_whisper = result_whisper["text"].strip() + except Exception as e: + text_whisper = f"[Error transcribiendo con Whisper: {e}]" + + # ----------------- Transcripción con Google Speech-to-Text ----------------- + r = sr.Recognizer() + try: + with sr.AudioFile(temp_filename) as source: + audio_data = r.record(source) + text_google = r.recognize_google(audio_data, language=google_language) + except Exception as e: + text_google = f"[Error transcribiendo con Google: {e}]" + + # Formatear el timestamp + timestamp_str = chunk_start_time.strftime("%Y-%m-%d %H:%M:%S") + # Preparar la línea de transcripción (sin identificación de narrador) + transcript_line = (f"[{timestamp_str}] Whisper: {text_whisper}\n" + f"[{timestamp_str}] Google: {text_google}\n") + print(transcript_line) + with open(transcription_file, "a", encoding="utf-8") as f: + f.write(transcript_line) + + # Eliminar el archivo temporal + os.remove(temp_filename) + +# ================== EJECUCIÓN PRINCIPAL ================== +if __name__ == "__main__": + # Preguntar al usuario el código de idioma para Google Speech-to-Text. + google_language = input("Ingrese el código de idioma para Google Speech-to-Text (ej: es-ES, en-US, ca-ES, enter para es-ES): ").strip() + if not google_language: + google_language = "es-ES" # Valor por defecto si no se ingresa nada + + # Iniciar el hilo de procesamiento en segundo plano + processing_thread = threading.Thread(target=process_audio, daemon=True) + processing_thread.start() + + try: + # Nota: En Windows, para capturar el audio del sistema puede ser necesario configurar el dispositivo WASAPI loopback. + with sd.InputStream(samplerate=SAMPLE_RATE, channels=1, callback=audio_callback): + print("Capturando audio... Presiona Ctrl+C para detener.") + while True: + time.sleep(0.1) + except KeyboardInterrupt: + print("Interrupción del usuario. Finalizando ejecución...") + except Exception as e: + print("Error:", e)