Subir archivos a "/"
This commit is contained in:
parent
0e63603b0d
commit
ea364b5614
175
01_transcribir_archivo_audio.py
Normal file
175
01_transcribir_archivo_audio.py
Normal file
@ -0,0 +1,175 @@
|
||||
"""
|
||||
===========================================================
|
||||
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 (si se usa).
|
||||
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 SpeechRecognition -> Para usar 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 numpy as np
|
||||
import wave
|
||||
import os
|
||||
import datetime
|
||||
import whisper
|
||||
from pydub import AudioSegment
|
||||
import speech_recognition as sr
|
||||
import sys
|
||||
|
||||
# ================== CONFIGURACIÓN GENERAL ==================
|
||||
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 de silencio (RMS) para descartar fragmentos muy silenciosos
|
||||
TARGET_LANGUAGE = None # Idioma para Whisper (None = detección automática)
|
||||
|
||||
# ================== SELECCIÓN INTERACTIVA DE ARCHIVO ==================
|
||||
extensiones_validas = (".mov", ".mp4", ".m4a", ".3gp", ".3g2", ".mj2")
|
||||
archivos_audio = [f for f in os.listdir() if f.lower().endswith(extensiones_validas)]
|
||||
|
||||
if not archivos_audio:
|
||||
print("❌ No se encontraron archivos de audio compatibles en el directorio actual.")
|
||||
sys.exit(1)
|
||||
|
||||
print("\nArchivos disponibles:")
|
||||
for i, archivo in enumerate(archivos_audio, 1):
|
||||
print(f"{i}. {archivo}")
|
||||
|
||||
while True:
|
||||
try:
|
||||
seleccion = int(input("\nSelecciona el número del archivo a transcribir: "))
|
||||
if 1 <= seleccion <= len(archivos_audio):
|
||||
audio_filename = archivos_audio[seleccion - 1]
|
||||
break
|
||||
else:
|
||||
print("Número fuera de rango.")
|
||||
except ValueError:
|
||||
print("Entrada no válida. Usa un número.")
|
||||
|
||||
# ================== DEFINICIÓN DEL ARCHIVO DE SALIDA ==================
|
||||
output_dir = "transcripciones"
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
|
||||
nombre_sugerido = os.path.splitext(audio_filename)[0] + ".txt"
|
||||
transcription_file = input(f"Nombre del archivo de transcripción [Enter = {nombre_sugerido}]: ").strip()
|
||||
if not transcription_file:
|
||||
transcription_file = nombre_sugerido
|
||||
elif not transcription_file.lower().endswith(".txt"):
|
||||
transcription_file += ".txt"
|
||||
|
||||
transcription_file = os.path.join(output_dir, transcription_file)
|
||||
|
||||
# ================== CARGA DEL MODELO WHISPER ==================
|
||||
print("\nCargando modelo Whisper...")
|
||||
model = whisper.load_model("base") # Puedes usar 'tiny', 'small', 'medium', 'large'
|
||||
print("✅ Modelo cargado.")
|
||||
|
||||
# ================== PROCESAMIENTO DE FRAGMENTOS ==================
|
||||
def process_chunk(chunk):
|
||||
# Calcular RMS (nivel de energía del fragmento) y volumen máximo
|
||||
rms = np.sqrt(np.mean(chunk**2))
|
||||
max_volume = np.max(np.abs(chunk))
|
||||
print(f"RMS: {rms:.5f}, Volumen máximo: {max_volume:.5f}")
|
||||
|
||||
if rms < MIN_VOLUME_THRESHOLD:
|
||||
print("Fragmento silencioso. Se omite.")
|
||||
return
|
||||
|
||||
# Convertir a formato int16 para guardar como WAV
|
||||
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)
|
||||
wf.setframerate(SAMPLE_RATE)
|
||||
wf.writeframes(chunk_int16.tobytes())
|
||||
except Exception as e:
|
||||
print("❌ Error guardando audio temporal:", e)
|
||||
return
|
||||
|
||||
chunk_start_time = datetime.datetime.now()
|
||||
|
||||
# Transcripción con Whisper
|
||||
try:
|
||||
if TARGET_LANGUAGE:
|
||||
result_whisper = model.transcribe(temp_filename, language=TARGET_LANGUAGE, fp16=False)
|
||||
else:
|
||||
result_whisper = model.transcribe(temp_filename, fp16=False)
|
||||
text_whisper = result_whisper["text"].strip()
|
||||
except Exception as e:
|
||||
text_whisper = f"[Error 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 Google: {e}]"
|
||||
|
||||
# Guardar resultado con timestamp
|
||||
timestamp = chunk_start_time.strftime("%Y-%m-%d %H:%M:%S")
|
||||
transcript = f"[{timestamp}] Whisper: {text_whisper}\n[{timestamp}] Google: {text_google}\n"
|
||||
|
||||
print(transcript)
|
||||
with open(transcription_file, "a", encoding="utf-8") as f:
|
||||
f.write(transcript)
|
||||
|
||||
os.remove(temp_filename)
|
||||
|
||||
# ================== EJECUCIÓN PRINCIPAL ==================
|
||||
if __name__ == "__main__":
|
||||
# Preguntar por el idioma de Google STT
|
||||
google_language = input("Código de idioma para Google (ej: es-ES, en-US) [Enter = es-ES]: ").strip()
|
||||
if not google_language:
|
||||
google_language = "es-ES"
|
||||
|
||||
print(f"\n🔊 Cargando archivo: {audio_filename}...")
|
||||
audio_segment = AudioSegment.from_file(audio_filename)
|
||||
|
||||
# Reconfigurar si es necesario (mono, 44100 Hz)
|
||||
if audio_segment.frame_rate != SAMPLE_RATE:
|
||||
audio_segment = audio_segment.set_frame_rate(SAMPLE_RATE)
|
||||
if audio_segment.channels != 1:
|
||||
audio_segment = audio_segment.set_channels(1)
|
||||
|
||||
samples = np.array(audio_segment.get_array_of_samples()).astype(np.float32) / 32767.0
|
||||
|
||||
chunk_size = int(CHUNK_DURATION * SAMPLE_RATE)
|
||||
total_samples = len(samples)
|
||||
|
||||
for start in range(0, total_samples, chunk_size):
|
||||
end = start + chunk_size
|
||||
chunk = samples[start:end].reshape(-1, 1)
|
||||
process_chunk(chunk)
|
||||
|
||||
print(f"\n✅ Transcripción final guardada en: {transcription_file}")
|
Loading…
x
Reference in New Issue
Block a user