ai-voice-api / app.py
kripasree's picture
Update app.py
34a3577 verified
Raw
History Blame Contribute Delete
1.97 kB
import base64
import io
import numpy as np
import librosa
import torch
from fastapi import FastAPI
from transformers import Wav2Vec2FeatureExtractor, Wav2Vec2ForSequenceClassification
THRESHOLD = 0.75
device = "cpu"
app = FastAPI()
print("Loading model...")
feature_extractor = Wav2Vec2FeatureExtractor.from_pretrained("/repository")
model = Wav2Vec2ForSequenceClassification.from_pretrained("/repository").to(device)
model.eval()
print("Model loaded.")
def load_mp3_from_base64(b64):
audio_bytes = base64.b64decode(b64)
with io.BytesIO(audio_bytes) as f:
y, sr = librosa.load(f, sr=16000)
return y
def predict_chunked(y):
chunk_len = 16000
probs = []
for start in range(0, len(y), chunk_len):
chunk = y[start:start + chunk_len]
if len(chunk) < 4000:
continue
inputs = feature_extractor(
chunk,
sampling_rate=16000,
return_tensors="pt"
)
inputs = {k: v.to(device) for k, v in inputs.items()}
with torch.no_grad():
logits = model(**inputs).logits
p = torch.softmax(logits, dim=1)[0][1].item()
probs.append(p)
return float(np.mean(probs)) if probs else 0.0
@app.post("/")
async def predict(data: dict):
language = data.get("language")
audio_base64 = data.get("audioBase64")
y = load_mp3_from_base64(audio_base64)
ai_prob = predict_chunked(y)
if ai_prob >= THRESHOLD:
return {
"status": "success",
"language": language,
"classification": "AI_GENERATED",
"confidenceScore": round(ai_prob, 4),
"explanation": "Synthetic patterns detected"
}
else:
return {
"status": "success",
"language": language,
"classification": "HUMAN",
"confidenceScore": round(1 - ai_prob, 4),
"explanation": "Natural speech patterns detected"
}