Spaces:
Runtime error
Runtime error
| import os | |
| import tempfile | |
| from datetime import datetime | |
| import gradio as gr | |
| from faster_whisper import WhisperModel | |
| # ---------------------------------------------------------------------- | |
| # Configuración del modelo | |
| # ---------------------------------------------------------------------- | |
| # Tamaños disponibles (de menor a mayor precisión/lentitud): | |
| # tiny, base, small, medium, large-v3 | |
| # En una Space gratuita (CPU) "small" es un buen balance velocidad/calidad. | |
| # Se puede cambiar sin tocar código con la variable de entorno WHISPER_MODEL | |
| # (Settings > Variables and secrets en la Space de Hugging Face). | |
| MODEL_SIZE = os.environ.get("WHISPER_MODEL", "small") | |
| DEVICE = "cpu" | |
| COMPUTE_TYPE = "int8" # cuantización para que corra rápido en CPU | |
| IDIOMAS = { | |
| "Español": "es", | |
| "Inglés": "en", | |
| "Portugués": "pt", | |
| "Francés": "fr", | |
| } | |
| print(f"Cargando modelo Whisper ({MODEL_SIZE})... esto puede tardar un momento.") | |
| model = WhisperModel(MODEL_SIZE, device=DEVICE, compute_type=COMPUTE_TYPE) | |
| print("Modelo cargado correctamente.") | |
| def format_timestamp(segundos: float) -> str: | |
| m, s = divmod(int(segundos), 60) | |
| h, m = divmod(m, 60) | |
| if h > 0: | |
| return f"{h:02d}:{m:02d}:{s:02d}" | |
| return f"{m:02d}:{s:02d}" | |
| def transcribir(audio_path, idioma, progreso=gr.Progress()): | |
| if audio_path is None: | |
| return "⚠️ Por favor sube un archivo de audio primero.", None | |
| progreso(0, desc="Analizando audio...") | |
| idioma_code = None if idioma == "Detectar automáticamente" else IDIOMAS[idioma] | |
| segments, info = model.transcribe( | |
| audio_path, | |
| language=idioma_code, | |
| beam_size=5, | |
| vad_filter=True, # filtra silencios largos, acelera y limpia el resultado | |
| ) | |
| duracion_total = info.duration if info.duration else 1 | |
| lineas = [] | |
| for segment in segments: | |
| progreso(min(segment.end / duracion_total, 1.0), desc="Transcribiendo...") | |
| inicio = format_timestamp(segment.start) | |
| lineas.append(f"[{inicio}] {segment.text.strip()}") | |
| resultado = "\n".join(lineas) if lineas else "No se detectó voz en el audio." | |
| nombre_archivo = f"transcripcion_{datetime.now().strftime('%Y%m%d_%H%M%S')}.txt" | |
| ruta_salida = os.path.join(tempfile.gettempdir(), nombre_archivo) | |
| with open(ruta_salida, "w", encoding="utf-8") as f: | |
| f.write(resultado) | |
| progreso(1.0, desc="¡Listo!") | |
| return resultado, ruta_salida | |
| with gr.Blocks(title="Transcriptor de Clases") as demo: | |
| gr.Markdown( | |
| """ | |
| # 🎙️ Transcriptor de Clases | |
| Sube el audio de tu clase (mp3, wav, m4a, etc.) y obtén la transcripción | |
| con marcas de tiempo. Funciona mejor con audios claros y sin mucho ruido de fondo. | |
| """ | |
| ) | |
| with gr.Row(): | |
| with gr.Column(): | |
| audio_input = gr.Audio( | |
| label="Audio de la clase", | |
| type="filepath", | |
| sources=["upload"], | |
| ) | |
| idioma_input = gr.Dropdown( | |
| choices=["Detectar automáticamente"] + list(IDIOMAS.keys()), | |
| value="Español", | |
| label="Idioma del audio", | |
| ) | |
| boton = gr.Button("Transcribir", variant="primary") | |
| gr.Markdown( | |
| "_Audios largos (más de 30-40 min) pueden tardar varios minutos " | |
| "en una Space gratuita, ya que corre en CPU._" | |
| ) | |
| with gr.Column(): | |
| salida_texto = gr.Textbox(label="Transcripción", lines=20, buttons=["copy"]) | |
| salida_archivo = gr.File(label="Descargar transcripción (.txt)") | |
| boton.click( | |
| fn=transcribir, | |
| inputs=[audio_input, idioma_input], | |
| outputs=[salida_texto, salida_archivo], | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch() |