""" =========================================================== 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)