"""SONICS AI-song detector service. Ücretsiz Hugging Face Space (CPU basic) üzerinde çalışır ve gradio_client ile programatik olarak çağrılır. Model: SONICS SpecTTTra (ICLR 2025, MIT lisans), Suno/Udio tam şarkıları üzerinde eğitilmiştir. """ import json import gradio as gr import librosa import numpy as np import spaces import torch from sonics import HFAudioClassifier MODEL_ID = "awsaf49/sonics-spectttra-alpha-120s" SAMPLE_RATE = 16000 CHUNK_SEC = 120 model = HFAudioClassifier.from_pretrained(MODEL_ID) model.eval() def _score_chunk(chunk: np.ndarray) -> float: device = "cuda" if torch.cuda.is_available() else "cpu" net = model.to(device) tensor = torch.from_numpy(chunk).float().unsqueeze(0).to(device) with torch.no_grad(): pred = net(tensor) return float(torch.sigmoid(pred).cpu().numpy().reshape(-1)[0]) @spaces.GPU(duration=180) def detect(audio_path: str) -> str: audio, sr = librosa.load(audio_path, sr=SAMPLE_RATE, mono=True) chunk_samples = CHUNK_SEC * SAMPLE_RATE if len(audio) == 0: return json.dumps({"error": "empty audio"}) if len(audio) <= chunk_samples: padded = np.pad(audio, (0, chunk_samples - len(audio))) probs = [_score_chunk(padded)] else: # Baş, orta ve son pencereler: şarkının tek bölümüne bakıp # yanılmamak için üç nokta örneklenir. total = len(audio) starts = [0, (total - chunk_samples) // 2, total - chunk_samples] probs = [_score_chunk(audio[s:s + chunk_samples]) for s in starts] return json.dumps({ "model": MODEL_ID, "fake_prob": float(np.median(probs)), "fake_prob_max": float(np.max(probs)), "chunk_probs": [round(p, 4) for p in probs], "duration_sec": round(len(audio) / SAMPLE_RATE, 2), }) demo = gr.Interface( fn=detect, inputs=gr.Audio(type="filepath", label="Ses dosyası"), outputs=gr.Textbox(label="JSON sonuç"), title="SONICS AI Song Detector", description=( "AI üretimi şarkı tespiti (Suno/Udio). " "Çıktı: fake_prob (0-1, 1 = AI üretimi)." ), flagging_mode="never", ) if __name__ == "__main__": demo.launch()