Downloads · 30 days
12
10% of all-time downloads
bdatdo0601/voicemail-detector-cnn-onnx
voicemail-detector-cnn-onnx is a machine learning model from bdatdo0601. Use it for the machine learning task on the model card, and read the license before you ship it in a product.
Fast and lightweight CNN model for real-time voicemail detection. This model achieves excellent accuracy while maintaining sub-20ms inference time, making it ideal for production phone systems.
Downloads · 30 days
12
10% of all-time downloads
All-time downloads
126
Public
Repo size
39.7 MB
Likes
1
Public
Click a slice to open those files.
.data13.2 MB · 50%
From the Hugging Face model README
Fast and lightweight CNN model for real-time voicemail detection. This model achieves excellent accuracy while maintaining sub-20ms inference time, making it ideal for production phone systems.
The CNN model excels at:
This model is ideal for:
Best suited for: Production systems prioritizing speed, scalability, and zero false positives on voicemail detection.
pip install onnxruntime numpy librosa
import numpy as np
import onnxruntime as ort
import librosa
def extract_mel_spectrogram(audio: np.ndarray, sr: int = 16000) -> np.ndarray:
"""Extract mel-spectrogram features from audio.
Args:
audio: Audio array of shape (64000,) - 4 seconds at 16kHz
sr: Sample rate (default: 16000)
Returns:
Mel-spectrogram of shape (1, 1, 128, 251)
"""
# Compute mel-spectrogram
mel_spec = librosa.feature.melspectrogram(
y=audio,
sr=sr,
n_fft=512,
hop_length=256,
n_mels=128,
fmin=0,
fmax=8000,
)
# Convert to log scale (dB)
mel_spec_db = librosa.power_to_db(mel_spec, ref=np.max)
# Normalize to [0, 1]
mel_spec_normalized = (mel_spec_db - mel_spec_db.min()) / (
mel_spec_db.max() - mel_spec_db.min() + 1e-8
)
# Reshape to (1, 1, 128, 251)
return mel_spec_normalized.reshape(1, 1, 128, -1)
# Load ONNX model
session = ort.InferenceSession("model.onnx")
# Load audio (4 seconds at 16kHz = 64,000 samples)
audio, sr = librosa.load("audio.wav", sr=16000, mono=True)
audio_segment = audio[:64000]
# Pad if shorter
if len(audio_segment) < 64000:
audio_segment = np.pad(audio_segment, (0, 64000 - len(audio_segment)))
# Extract features
mel_spec = extract_mel_spectrogram(audio_segment)
# Run inference
outputs = session.run(None, {"input": mel_spec.astype(np.float32)})
logits = outputs[0]
# Get prediction
prediction_idx = np.argmax(logits, axis=-1)[0]
result = "voicemail" if prediction_idx == 1 else "live_human"
# Get confidence scores
probabilities = np.exp(logits) / np.sum(np.exp(logits), axis=-1, keepdims=True)
confidence = probabilities[0][prediction_idx]
print(f"Detection: {result} (confidence: {confidence:.2%})")
import numpy as np
import onnxruntime as ort
class VoicemailDetector:
"""Real-time voicemail detector using CNN model."""
def __init__(self, model_path: str, sample_rate: int = 16000):
self.session = ort.InferenceSession(model_path)
self.sample_rate = sample_rate
self.buffer_duration = 4.0 # seconds
self.buffer_size = int(sample_rate * self.buffer_duration)
self.audio_buffer = np.zeros(self.buffer_size, dtype=np.float32)
def add_audio(self, audio_chunk: np.ndarray):
"""Add audio chunk to buffer (rolling window)."""
chunk_size = len(audio_chunk)
# Shift buffer and add new audio
self.audio_buffer = np.roll(self.audio_buffer, -chunk_size)
self.audio_buffer[-chunk_size:] = audio_chunk
def detect(self) -> tuple[str, float]:
"""Detect voicemail from current buffer.
Returns:
Tuple of (prediction, confidence)
"""
# Extract features
mel_spec = extract_mel_spectrogram(self.audio_buffer, self.sample_rate)
# Run inference
outputs = self.session.run(None, {"input": mel_spec})
logits = outputs[0]
# Get prediction
prediction_idx = np.argmax(logits, axis=-1)[0]
result = "voicemail" if prediction_idx == 1 else "live_human"
# Calculate confidence
probabilities = np.exp(logits) / np.sum(np.exp(logits), axis=-1, keepdims=True)
confidence = probabilities[0][prediction_idx]
return result, float(confidence)
# Usage
detector = VoicemailDetector("model.onnx")
# Simulate streaming audio
for audio_chunk in audio_stream:
detector.add_audio(audio_chunk)
result, confidence = detector.detect()
print(f"{result}: {confidence:.2%}")
Input: Audio (4s @ 16kHz) → Mel-Spectrogram (128 mels, 251 time steps)
↓
Conv2D (32 filters, 3x3) + ReLU + MaxPool2D
↓
Conv2D (64 filters, 3x3) + ReLU + MaxPool2D
↓
Conv2D (128 filters, 3x3) + ReLU + MaxPool2D
↓
Flatten + Dropout (0.5)
↓
Dense (128) + ReLU + Dropout (0.5)
↓
Dense (2) → Softmax
↓
Output: [live_human_prob, voicemail_prob]
The model expects mel-spectrograms with these parameters:
Input:
input[1, 1, 128, 251]float32Output:
output[1, 2]float32[0: live_human, 1: voicemail]| Category | Correct | Total | Accuracy |
|---|---|---|---|
| Live Human | 34 | 34 | 100.0% |
| Voicemail | 47 | 67 | 70.15% |
| Overall | 81 | 101 | 80.20% |
| Predicted Live Human | Predicted Voicemail | |
|---|---|---|
| Actual Live Human | 34 (True Negative) | 0 (False Positive) |
| Actual Voicemail | 20 (False Negative) | 47 (True Positive) |
Note: The model is tuned to never miss a live human caller, which results in some voicemails being classified as live humans. This is ideal for customer service scenarios where missing a live caller is worse than occasionally forwarding a voicemail to a human agent.
Use ONNX Runtime optimizations:
sess_options = ort.SessionOptions()
sess_options.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL
session = ort.InferenceSession("model.onnx", sess_options)
Batch processing for multiple calls:
# Process multiple audio samples at once
batch_input = np.stack([mel_spec1, mel_spec2, mel_spec3]) # Shape: (3, 1, 128, 251)
outputs = session.run(None, {"input": batch_input})
Reuse feature extraction: Cache mel-filterbank computation for faster repeated processing.
MIT License - Free for commercial and non-commercial use.
For questions or issues, please open an issue in the repository.
Related Models: