Indian AMD: YAMNet-GRU (person vs machine on Indian phone calls)

This is a small, fast answering-machine / voicemail detector for Indian outbound calls (Hindi and Indian English). It listens to the first seconds of a call and tells a live person from a machine: carrier announcements ("the number you are calling is switched off"), voicemail greetings, IVR menus, call-progress tones, and robocalls.

  • 3.5M parameters, 14 MB, and about 7–70 ms per check on one CPU thread.
  • It needs no transcript and no speech-to-text; it works on the audio directly.
  • It was built because no public AMD model handles Hindi. Every public model we tested flagged 44–90% of Hindi speakers as machines; this one flags 0.7–9.3% (details below).

Current version: v2 (2026-10-13). v1 is still available at revision tag v1.

Results (v2)

Test sets: all held out from training (no shared speakers, scripts or files). Every clip went through a real 8 kHz G.711 Β΅-law round trip, so it sounds like a phone line.

Decision rule: the machine-only rule described below. "Caught" means the share of machines it detected; "wrongly flagged" means the share of real people it called a machine.

Group (clips) v2 v1 Median audio heard (v2)
Real US robocalls (150) 98.7% caught 99.3% 1.1 s
Indian English machine voices (45) 100% caught 100% 1.3 s
Hindi machine voices (24) 100% caught 100% 1.3 s
Hindi-then-English machine voices (7) 100% caught 100% 1.3 s
Indian English people (150) 1.3% wrongly flagged 2.7% –
Hindi people, microphone recordings (150) 9.3% wrongly flagged 13.3% –
Hindi people on a phone line, 8 kHz (150) 0.7% wrongly flagged 22.7% –

Share called "machine" by seconds of audio heard (v2, one-shot, threshold 0.5):

Group 1 s 2 s 3 s 4 s 6 s 10 s
Robocall 76.7% 84.0% 90.0% 93.3% 98.0% 97.3%
Indian machine voices 96.1% 100% 100% 100% 100% 100%
Indian English people 2.7% 1.3% 0.7% 0.7% 0.7% 0.7%
Hindi people (microphone) 12.7% 10.0% 7.3% 8.0% 9.3% 8.7%

v2 is more cautious than v1 in the first second: one-shot robocall recall at 1 s is 77%, against 93% for v1. With the streaming rule it still catches 98.7%; the slowest 10% of robocalls are flagged by about 4.5 s.

Compared with public models on the same test set and rule

Model Hindi people wrongly flagged Indian English people wrongly flagged CPU per check
AbijahKaj/whisper-telephony-amd (as published) 61.3% 5.3% ~750 ms
ozonetg/amd-telephony-yamnet-gru (as published, CC BY-NC) 44.0% 4.0% ~10–70 ms
EfficientAT mn04 / CED-tiny (AudioSet, zero-shot) ~90% 96–98% 15–75 ms
This model, v1 13.3% 2.7% 11–70 ms
This model, v2 9.3% 1.3% 7–70 ms

Speed (CPU, 1 thread, PyTorch fp32, Intel Core Ultra 7 155H)

Audio heard 1 s 2 s 4 s 8 s
ms per check 7–11 12–18 23–34 48–70

The ranges come from repeated runs under different machine load.

How to use

import numpy as np, soundfile as sf
from huggingface_hub import snapshot_download
import sys

folder = snapshot_download("Aakash22134/indian-amd-yamnet-gru")      # add revision="v1" for v1
sys.path.insert(0, folder)
from amd_yamnet import AMDYamnet, MachineOnlyRule

model = AMDYamnet.from_pretrained(folder)
audio, sr = sf.read("call_start.wav", dtype="float32")   # mono, 16 kHz (resample 8 kHz phone audio up)
print("p_machine:", model.p_machine(audio))              # one-shot, uses the last 8 s

t = MachineOnlyRule(model).run(audio)                     # the rule used for the results above
print("machine at %.2f s" % t if t is not None else "person")

Requirements: torch, torchaudio, numpy, safetensors (and soundfile for the example).

The decision rule (MachineOnlyRule)

  • Start checking 0.8 s after speech starts, then every 0.5 s, up to 8 s.
  • Say "machine" if p β‰₯ 0.9 once, or p β‰₯ 0.75 on two checks in a row. Otherwise stay "person".
  • It is asymmetric on purpose. Hanging up on a real person is the costly mistake, so "person" is never decided early. A voice bot can start talking normally and stop only if "machine" fires.
  • Run inference on a worker thread (for example asyncio.to_thread), not on the audio event loop.

Training (v2)

  • Backbone: Google YAMNet (AudioSet), loaded from the MIT PyTorch port w-hc/torch_audioset. Head: linear 1024β†’128 + tanh, then a bidirectional GRU (hidden 96), then linear β†’ 1 logit. The whole network was fine-tuned.

  • Frontend: YAMNet's: 16 kHz, 25 ms / 10 ms STFT, 64 mel bands (125–7500 Hz), log(mel + 0.001), 0.96 s patches with a 0.48 s hop, last 8 s of audio.

  • Data: about 12,450 clips, ~24 h. Batch sampling: 60% people and 40% machines.

    Group Class Clips Source
    Telephony people person 1,500 AbijahKaj/telephony-amd-dataset (train split)
    Real callers on phone lines (v2) person 1,500 PolyAI MINDS14, 14 languages
    Indian English people person 1,374 (458 speakers) Mozilla Common Voice, "India and South Asia" accent
    Hindi people person 1,600 Google FLEURS hi_in (train split)
    Hindi people (v2) person 1,150 (403 speakers) Mozilla Common Voice 17 Hindi
    Hindi people, 8 kHz (v2) person 1,500 (13 speakers) MUCS 2021 Hindi (OpenSLR 103)
    Telephony machines machine 2,000 AbijahKaj/telephony-amd-dataset (train split)
    Robocalls machine 1,223 wspr-ncsu/robocall-audio-dataset
    Indian English and Hindi machine voices machine 360 ~80 scripts written for this model (carrier announcements, bank and telecom IVR, voicemail, Hinglish), spoken by Microsoft edge-tts en-IN / hi-IN voices
    Call-progress tones (v2) machine 240 generated Indian ringback, busy, congestion and SIT tones
  • Augmentation: each sample is the first 1–8 s of a clip, after 0–0.8 s of leading silence, with random loudness, light noise (SNR 25–45 dB), and a real G.711 Β΅-law 8 kHz round trip.

  • Optimisation: 8 epochs Γ— 250 steps Γ— batch 32, AdamW (backbone lr 1e-4, head 1e-3), cosine decay, bf16 on one RTX 2000 Ada (~9 min). Best epoch chosen on a held-out validation split.

Test sets

Group Clips Source
Real US robocalls 150 robocall-audio-dataset, files not used in training
Indian machine voices 76 34 scripts different from training, edge-tts en-IN / hi-IN voices
Indian English people 150 Common Voice, speakers not in training
Hindi people, microphone 150 FLEURS hi_in validation split (separate speakers from train)
Hindi people, 8 kHz phone 150 MUCS 2021 Hindi, 6 speakers not in training (same corpus and sentences as the training speakers)

All test clips were loudness-normalised and sent through G.711 Β΅-law at 8 kHz.

License and attribution

  • Model weights and code: Apache-2.0.

  • YAMNet (Google, tensorflow/models, Apache-2.0). PyTorch port and the vendored network code in amd_yamnet.py are from w-hc/torch_audioset: MIT, Β© 2021 Haochen (see LICENSE-torch_audioset-MIT).

  • Training data:

    • Google FLEURS (CC BY 4.0, attribution: Conneau et al., 2022)
    • PolyAI MINDS14 (CC BY 4.0, attribution: Gerz et al., 2021)
    • Mozilla Common Voice and Common Voice 17 Hindi (CC0)
    • wspr-ncsu robocall-audio-dataset (public domain)
    • MUCS 2021 Hindi, OpenSLR 103 (Microsoft Research data license)
    • AbijahKaj/telephony-amd-dataset (no license stated on its card)
    • audio generated with Microsoft edge-tts (subject to Microsoft's service terms)

    If you plan commercial use, review the last three items yourself.

  • No CC BY-NC model weights were used to train this model.

Downloads last month
68
Safetensors
Model size
3.51M params
Tensor type
F32
Β·
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support

Datasets used to train Aakash22134/indian-amd-yamnet-gru