w2v2-bert-ethio-v5 / inference_example.py
anshulsc's picture
Upload w2v-bert-ethio recipe-v5 best checkpoint (2026-09-27)
f2a5b60 verified
Raw History Blame Contribute Delete
1.99 kB
"""Greedy-CTC inference for anshulsc/w2v-bert-ethio-v5.
Pipeline matches the evaluation harness exactly:
1. 16 kHz mono audio -> SeamlessM4TFeatureExtractor (from facebook/w2v-bert-2.0)
2. Wav2Vec2BertForCTC forward pass -> argmax over logits
3. Mask the six [LID:*] token ids (311-316) to the CTC blank id
4. Wav2Vec2CTCTokenizer.decode (collapses CTC repeats, maps | to spaces)
Needs: torch transformers soundfile librosa
"""
import sys
import soundfile as sf
import torch
from transformers import SeamlessM4TFeatureExtractor, Wav2Vec2BertForCTC, Wav2Vec2CTCTokenizer
MODEL_ID = "anshulsc/w2v-bert-ethio-v5"
LID_TOKEN_IDS = [311, 312, 313, 314, 315, 316] # [LID:*] tokens must not survive decoding
def transcribe(audio_path: str) -> str:
speech, sr = sf.read(audio_path, dtype="float32")
if speech.ndim > 1: # downmix stereo to mono
speech = speech.mean(axis=1)
feature_extractor = SeamlessM4TFeatureExtractor.from_pretrained("facebook/w2v-bert-2.0")
if sr != feature_extractor.sampling_rate:
import librosa
speech = librosa.resample(speech, orig_sr=sr, target_sr=feature_extractor.sampling_rate)
inputs = feature_extractor(
speech,
sampling_rate=feature_extractor.sampling_rate,
return_tensors="pt",
return_attention_mask=True,
)
device = "cuda" if torch.cuda.is_available() else "cpu"
model = Wav2Vec2BertForCTC.from_pretrained(MODEL_ID, torch_dtype=torch.float16).to(device).eval()
inputs = {k: v.to(device) for k, v in inputs.items()}
tokenizer = Wav2Vec2CTCTokenizer.from_pretrained(MODEL_ID)
with torch.no_grad():
logits = model(**inputs).logits
pred_ids = torch.argmax(logits, dim=-1)
lid = torch.tensor(LID_TOKEN_IDS, device=pred_ids.device)
pred_ids = pred_ids.masked_fill(torch.isin(pred_ids, lid), tokenizer.pad_token_id)
return tokenizer.decode(pred_ids[0]).strip()
if __name__ == "__main__":
print(transcribe(sys.argv[1]))