Download example.py from Raymxnd/Whisper-Vad-EncDec-ASMR-torch: direct link, hf CLI and curl.
- Browser
- Download file 3.13 kB
-
https://huggingface.co/Raymxnd/Whisper-Vad-EncDec-ASMR-torch/resolve/main/example.py
- Command line
-
hf download hf://Raymxnd/Whisper-Vad-EncDec-ASMR-torch/example.py
-
curl -L -o example.py https://huggingface.co/Raymxnd/Whisper-Vad-EncDec-ASMR-torch/resolve/main/example.py
3.13 kB
| #!/usr/bin/env python3 | |
| """Detect speech in an audio file and write the regions out as WebVTT. | |
| python example.py speech.wav | |
| python example.py speech.mp3 --dtype fp16 --device cpu -o regions.vtt | |
| The VTT is cues covering the detected speech, with no text -- useful for | |
| eyeballing the VAD's decisions in any media player, and as the segmentation | |
| step in front of an ASR model. | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| from pathlib import Path | |
| import torch | |
| from vad_torch import TorchVadRunner, DEFAULT_WEIGHTS, SAMPLE_RATE | |
| def fmt_vtt_time(seconds: float) -> str: | |
| h = int(seconds // 3600) | |
| m = int((seconds % 3600) // 60) | |
| s = seconds % 60 | |
| return f"{h:02d}:{m:02d}:{s:06.3f}" | |
| def main() -> int: | |
| p = argparse.ArgumentParser(description=__doc__, | |
| formatter_class=argparse.RawDescriptionHelpFormatter) | |
| p.add_argument("audio", type=Path) | |
| p.add_argument("-o", "--out", type=Path, default=None, | |
| help="output .vtt (default: alongside the input)") | |
| p.add_argument("--weights", type=Path, default=DEFAULT_WEIGHTS) | |
| p.add_argument("--device", default="cuda" if torch.cuda.is_available() else "cpu") | |
| p.add_argument("--dtype", default="fp32", choices=["fp32", "fp16"], | |
| help="fp32 (default) reproduces the ONNX reference exactly; " | |
| "fp16 is ~2x faster and moves a few boundaries") | |
| p.add_argument("--batch-size", type=int, default=8) | |
| p.add_argument("--threshold", type=float, default=0.4, | |
| help="in LOGIT space, not probability (default 0.4 ~= 0.60)") | |
| a = p.parse_args() | |
| if not a.audio.exists(): | |
| raise SystemExit(f"no such file: {a.audio}") | |
| try: | |
| import librosa | |
| except ImportError: | |
| raise SystemExit("this example needs librosa: pip install librosa") | |
| print(f"loading {a.audio.name}") | |
| audio, _ = librosa.load(str(a.audio), sr=SAMPLE_RATE, mono=True) | |
| duration = len(audio) / SAMPLE_RATE | |
| print(f" {duration:.1f}s at {SAMPLE_RATE} Hz mono") | |
| dt = {"fp32": torch.float32, "fp16": torch.float16}[a.dtype] | |
| if a.dtype == "fp16" and a.device == "cpu": | |
| raise SystemExit("fp16 on CPU is not supported; use --dtype fp32") | |
| runner = TorchVadRunner(weights=a.weights, device=a.device, dtype=dt, | |
| batch_size=a.batch_size) | |
| print(f" model on {a.device}, {a.dtype}") | |
| intervals = runner.speech_intervals(audio, threshold=a.threshold) | |
| speech = sum(e - s for s, e in intervals) | |
| print(f"\n{len(intervals)} speech regions, {speech:.1f}s of {duration:.1f}s " | |
| f"({speech / max(duration, 1e-9) * 100:.1f}% active)") | |
| out = a.out or a.audio.with_suffix(".vtt") | |
| lines = ["WEBVTT", ""] | |
| for i, (start, end) in enumerate(intervals, 1): | |
| lines.append(str(i)) | |
| lines.append(f"{fmt_vtt_time(start)} --> {fmt_vtt_time(end)}") | |
| lines.append(f"[speech {i}]") | |
| lines.append("") | |
| out.write_text("\n".join(lines), encoding="utf-8") | |
| print(f"-> {out}") | |
| return 0 | |
| if __name__ == "__main__": | |
| raise SystemExit(main()) | |