Spaces:
Running
Running
| import argparse | |
| import os | |
| import sys | |
| import librosa | |
| import numpy as np | |
| import parselmouth | |
| import torch | |
| from transformers import AutoProcessor, AutoModelForCTC | |
| MODEL_ID = "facebook/wav2vec2-lv-60-espeak-cv-ft" | |
| SAMPLE_RATE = 16000 | |
| def main(): | |
| parser = argparse.ArgumentParser(description="Transcribe IPA phonemes and measure F3 from a .wav file.") | |
| parser.add_argument("wav_path", help="Path to a .wav audio file") | |
| args = parser.parse_args() | |
| if not os.path.isfile(args.wav_path): | |
| print(f"ERROR: file not found: {args.wav_path}", file=sys.stderr) | |
| sys.exit(1) | |
| print(f"[1/4] Loading audio from {args.wav_path} at {SAMPLE_RATE} Hz...") | |
| audio, sr = librosa.load(args.wav_path, sr=SAMPLE_RATE) | |
| duration = len(audio) / sr | |
| print(f" Loaded {len(audio)} samples ({duration:.2f}s)") | |
| print(f"[2/4] Loading model {MODEL_ID}...") | |
| processor = AutoProcessor.from_pretrained(MODEL_ID) | |
| model = AutoModelForCTC.from_pretrained(MODEL_ID) | |
| model.eval() | |
| print(" Model loaded.") | |
| print("[3/4] Running phoneme recognition...") | |
| inputs = processor(audio, sampling_rate=SAMPLE_RATE, return_tensors="pt") | |
| with torch.no_grad(): | |
| logits = model(inputs.input_values).logits | |
| predicted_ids = torch.argmax(logits, dim=-1) | |
| transcription = processor.batch_decode(predicted_ids)[0] | |
| print(f" Phonemes: {transcription}") | |
| print("[4/4] Computing F3 formant with parselmouth...") | |
| sound = parselmouth.Sound(args.wav_path) | |
| formants = sound.to_formant_burg() | |
| times = np.linspace(0, sound.duration, num=100) | |
| f3_values = [formants.get_value_at_time(3, t) for t in times] | |
| f3_values = [v for v in f3_values if v is not None and not np.isnan(v)] | |
| if f3_values: | |
| f3_mean = float(np.mean(f3_values)) | |
| print(f" Mean F3: {f3_mean:.1f} Hz (from {len(f3_values)} frames)") | |
| else: | |
| print(" No F3 values detected.") | |
| if __name__ == "__main__": | |
| main() | |