sonido-de-sistema-a-texto/V00/captura_audio_comentado.py

188 lines
8.8 KiB
Python

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