Spaces:
Running
on
Zero
Running
on
Zero
File size: 4,125 Bytes
18fd051 f2325ad 18fd051 f2325ad 18fd051 802caeb 18fd051 46b613a 18fd051 802caeb f2325ad 802caeb f2325ad 802caeb 18fd051 46b613a 29bd05d 46b613a 29bd05d 802caeb 18fd051 802caeb 18fd051 802caeb 18fd051 f2325ad 18fd051 f2325ad 8985e44 f2325ad 8985e44 18fd051 802caeb f2325ad 81392ea 18fd051 8985e44 f2325ad 18fd051 81392ea |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
"""
Transcrição de áudio — ZeroGPU Space
Envie um arquivo de áudio (mp3, wav, m4a, etc.) e transcreva com Whisper.
"""
import tempfile
from pathlib import Path
import gradio as gr
# ZeroGPU: decorator é no-op fora do HF
try:
import spaces
except ImportError:
class _Spaces:
def GPU(self, fn=None, **kwargs):
def decorator(f):
return f
return decorator(fn) if fn else decorator
spaces = _Spaces()
def _fmt_tempo(segundos: float) -> str:
"""Formata segundos como MM:SS ou HH:MM:SS."""
h = int(segundos // 3600)
m = int((segundos % 3600) // 60)
s = int(segundos % 60)
if h > 0:
return f"{h:01d}:{m:02d}:{s:02d}"
return f"{m:01d}:{s:02d}"
@spaces.GPU(duration=180)
def transcrever(audio, modelo: str, idioma: str) -> str:
"""Transcreve áudio enviado com Whisper."""
try:
from faster_whisper import WhisperModel
path = None
if isinstance(audio, str) and audio and Path(audio).exists():
path = str(audio)
elif hasattr(audio, "name"):
p = getattr(audio, "name", None)
if p and Path(str(p)).exists():
path = str(p)
elif isinstance(audio, bytes) and audio:
with tempfile.NamedTemporaryFile(suffix=".mp3", delete=False) as f:
f.write(audio)
path = f.name
if not path:
return "❌ Envie um arquivo de áudio."
model = WhisperModel(modelo, device="cuda", compute_type="float16")
lang = None if idioma == "Auto" else idioma.lower()
segments, info = model.transcribe(
path,
language=lang,
beam_size=5,
vad_filter=True,
)
resultado = []
for seg in segments:
resultado.append({
"start": seg.start,
"end": seg.end,
"text": seg.text.strip(),
})
# Timestamp + parágrafos: [MM:SS] texto, linha em branco quando pausa > 1.5s
PAUSA_PARAGRAFO = 1.5
linhas = []
prev_end = 0
for s in resultado:
if not s["text"]:
continue
if prev_end > 0 and (s["start"] - prev_end) > PAUSA_PARAGRAFO:
linhas.append("") # linha em branco = novo parágrafo
ts = _fmt_tempo(s["start"])
linhas.append(f"[{ts}] {s['text']}")
prev_end = s["end"]
texto = "\n".join(linhas)
if not texto:
return "⚠️ Nenhum texto transcrito (áudio sem fala?)."
return f"Idioma detectado: {info.language}\n\n{texto}"
except Exception as e:
return f"❌ Erro: {type(e).__name__}: {e}"
MODELOS = ["tiny", "base", "small", "medium", "large-v3"]
IDIOMAS = ["Auto", "pt", "en", "es", "fr"]
with gr.Blocks(
title="Transcrição de áudio",
theme=gr.themes.Soft(),
) as demo:
gr.Markdown("# 🎙️ Transcrição de áudio")
gr.Markdown(
"Envie um arquivo de áudio (mp3, wav, m4a, webm, etc.) e transcreva com Whisper. "
"**ZeroGPU** — processamento gratuito na nuvem."
)
with gr.Row():
audio = gr.File(
label="Áudio",
file_types=[".mp3", ".wav", ".m4a", ".webm", ".opus", ".ogg", ".flac"],
)
with gr.Row():
modelo = gr.Dropdown(
label="Modelo Whisper",
choices=MODELOS,
value="small",
info="small = bom equilíbrio; large-v3 = mais preciso (mais lento)",
)
idioma = gr.Dropdown(
label="Idioma",
choices=IDIOMAS,
value="Auto",
)
btn = gr.Button("Transcrever", variant="primary")
saida = gr.Textbox(
label="Transcrição",
lines=15,
max_lines=30,
)
btn.click(
fn=transcrever,
inputs=[audio, modelo, idioma],
outputs=saida,
)
gr.Markdown("---")
gr.Markdown(
"A transcrição pode levar 1–2 min para iniciar (fila da GPU)."
)
demo.launch(show_error=True, share=True)
|