mirror of
https://github.com/openai/whisper.git
synced 2025-11-23 22:15:58 +00:00
147 lines
5.6 KiB
Python
147 lines
5.6 KiB
Python
import streamlit as st
|
|
import torch
|
|
import numpy as np
|
|
import os
|
|
from whisper.transcribe import transcribe
|
|
from whisper import load_model
|
|
from whisper.tokenizer import LANGUAGES, TO_LANGUAGE_CODE
|
|
|
|
st.set_page_config(page_title="Whisper Transcriber", layout="wide")
|
|
st.title("Whisper Transcriber - Interfaz Streamlit")
|
|
|
|
# Sidebar options
|
|
st.sidebar.header("Opciones de transcripción")
|
|
|
|
# Idiomas para el selector (nombre completo)
|
|
language_names = ["(autodetect)"] + [LANGUAGES[k].title() for k in sorted(LANGUAGES.keys())]
|
|
language_key_map = dict(zip([LANGUAGES[k].title() for k in sorted(LANGUAGES.keys())], sorted(LANGUAGES.keys())))
|
|
|
|
# Modelo
|
|
model_name = st.sidebar.selectbox(
|
|
"Modelo",
|
|
["tiny", "base", "small", "medium", "large", "turbo"],
|
|
index=5,
|
|
help="Selecciona el modelo Whisper a utilizar. Modelos más grandes suelen ser más precisos pero más lentos."
|
|
)
|
|
|
|
# Tarea
|
|
task = st.sidebar.selectbox(
|
|
"Tarea",
|
|
["transcribe", "translate"],
|
|
index=0,
|
|
help="'transcribe' transcribe el audio en el mismo idioma. 'translate' traduce el audio al inglés."
|
|
)
|
|
|
|
# Idioma
|
|
language_display = st.sidebar.selectbox(
|
|
"Idioma (deja vacío para autodetectar)",
|
|
language_names,
|
|
index=0,
|
|
help="Selecciona el idioma hablado en el audio. Si eliges '(autodetect)', el modelo intentará detectarlo automáticamente."
|
|
)
|
|
if language_display == "(autodetect)":
|
|
language = None
|
|
else:
|
|
language = language_key_map[language_display]
|
|
|
|
# Temperatura
|
|
st.sidebar.markdown("<span style='font-size: 12px; color: gray;'>La temperatura controla la aleatoriedad de la transcripción. Valores bajos (0) hacen la salida más determinista, valores altos pueden generar resultados más creativos pero menos precisos.</span>", unsafe_allow_html=True)
|
|
temperature = st.sidebar.slider(
|
|
"Temperatura",
|
|
0.0, 1.0, 0.0, 0.1,
|
|
help="Controla la aleatoriedad de la transcripción. 0 es determinista, valores más altos pueden dar resultados más variados."
|
|
)
|
|
|
|
# Word timestamps
|
|
word_timestamps = st.sidebar.checkbox(
|
|
"Timestamps por palabra",
|
|
value=False,
|
|
help="Si está activado, se mostrarán marcas de tiempo para cada palabra."
|
|
)
|
|
|
|
# Selector de destino de salida
|
|
output_mode = st.sidebar.radio(
|
|
"¿Dónde quieres guardar la salida?",
|
|
("En mi equipo (local)", "En la ruta del contenedor (/app/output)"),
|
|
help="Elige si quieres guardar los archivos en tu equipo local o en la carpeta compartida del contenedor."
|
|
)
|
|
|
|
if output_mode == "En mi equipo (local)":
|
|
st.sidebar.markdown("<small>Selecciona cualquier archivo de la carpeta donde quieras guardar la salida. Se usará la ruta de esa carpeta.</small>", unsafe_allow_html=True)
|
|
selected_file = st.sidebar.file_uploader(
|
|
"Selecciona un archivo de la carpeta destino (solo para elegir la carpeta)",
|
|
type=None,
|
|
accept_multiple_files=False,
|
|
key="folder_selector"
|
|
)
|
|
if selected_file is not None and hasattr(selected_file, 'name'):
|
|
import pathlib
|
|
# En local, file_uploader solo da el nombre, no la ruta absoluta, así que usamos cwd
|
|
selected_folder = os.getcwd()
|
|
else:
|
|
selected_folder = os.getcwd()
|
|
default_dir = selected_folder
|
|
else:
|
|
default_dir = "/app/output"
|
|
|
|
output_dir = st.sidebar.text_input(
|
|
"Carpeta de salida para los resultados",
|
|
value=default_dir,
|
|
help="Ruta donde se guardarán los archivos de salida generados por la transcripción. Puedes personalizarla si lo deseas."
|
|
)
|
|
|
|
# Archivo de audio
|
|
st.header("Selecciona archivos de audio para transcribir")
|
|
audio_files = st.file_uploader(
|
|
"Selecciona uno o varios archivos de audio",
|
|
type=["wav", "mp3", "m4a", "flac", "ogg"],
|
|
accept_multiple_files=True
|
|
)
|
|
|
|
if st.button("Transcribir") and audio_files:
|
|
device = "cuda" if torch.cuda.is_available() else "cpu"
|
|
st.info(f"Cargando modelo '{model_name}' en {device}...")
|
|
model = load_model(model_name, device=device)
|
|
os.makedirs(output_dir, exist_ok=True)
|
|
for idx, audio_file in enumerate(audio_files):
|
|
st.write(f"Procesando archivo: {audio_file.name}")
|
|
with st.spinner(f"Transcribiendo {audio_file.name}..."):
|
|
# Guardar archivo temporalmente
|
|
temp_path = f"temp_{audio_file.name}"
|
|
with open(temp_path, "wb") as f:
|
|
f.write(audio_file.read())
|
|
# Barra de progreso
|
|
progress = st.progress(0)
|
|
def progress_callback(p):
|
|
progress.progress(int(p * 100))
|
|
# Ejecutar transcripción
|
|
result = transcribe(
|
|
model,
|
|
temp_path,
|
|
task=task,
|
|
language=language,
|
|
temperature=temperature,
|
|
word_timestamps=word_timestamps,
|
|
verbose=True
|
|
)
|
|
# Guardar resultado en archivo de texto en la carpeta de salida
|
|
output_txt = os.path.join(output_dir, f"{os.path.splitext(audio_file.name)[0]}.txt")
|
|
with open(output_txt, "w", encoding="utf-8") as f:
|
|
f.write(result["text"])
|
|
# Mostrar resultado
|
|
st.subheader(f"Transcripción de {audio_file.name}")
|
|
st.text_area("Texto transcrito", result["text"], height=200)
|
|
st.write("Detalles:", result)
|
|
# Botón de descarga siempre disponible
|
|
st.download_button(
|
|
label="Descargar transcripción",
|
|
data=result["text"],
|
|
file_name=f"{os.path.splitext(audio_file.name)[0]}.txt",
|
|
mime="text/plain"
|
|
)
|
|
os.remove(temp_path)
|
|
progress.progress(100)
|
|
st.success("¡Transcripción completada!")
|
|
else:
|
|
st.info("Selecciona archivos y pulsa 'Transcribir'.")
|