File size: 8,388 Bytes
87be748 8128e5b 87be748 8128e5b 87be748 4f3d2d9 87be748 66b9466 87be748 66b9466 87be748 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | # -*- coding: utf-8 -*-
import numpy as np
import librosa
import librosa.display
import matplotlib.pyplot as plt
import noisereduce as nr
import hashlib
import os
import gradio as gr
class AuthenticMusicShield:
def __init__(self):
print("?? Lancement du Bouclier v4.4.5 (Correction seuil AI Cover Music)...")
self.ia = None
def load_model(self):
if self.ia is None:
try:
from transformers import pipeline
self.ia = pipeline("audio-classification", model="MIT/ast-finetuned-audioset-10-10-0.4593")
except Exception:
self.ia = None
def get_sha256(self, path):
with open(path, "rb") as f:
return hashlib.sha256(f.read()).hexdigest()
def generer_spectrogramme(self, y, sr):
plt.figure(figsize=(10, 4))
S = librosa.feature.melspectrogram(y=y, sr=sr, n_mels=128)
S_dB = librosa.power_to_db(S, ref=np.max)
librosa.display.specshow(S_dB, sr=sr, x_axis='time', y_axis='mel', cmap='magma')
plt.title('Analyse de Texture & Intégrité Vocale')
plt.tight_layout()
plot_path = "spectrum.png"
plt.savefig(plot_path)
plt.close()
return plot_path
def analyser_expert(self, path):
if path is None:
return None, "En attente...", None
try:
self.load_model()
y, sr = librosa.load(path, sr=44100)
# --- DÉBRUITAGE ADAPTATIF ---
# Première passe légère pour détecter la source
y_light = nr.reduce_noise(y=y, sr=sr, prop_decrease=0.3)
pitches_light, magnitudes_light = librosa.piptrack(y=y_light, sr=sr)
centroid_light = np.mean(librosa.feature.spectral_centroid(y=y_light, sr=sr))
# Si centroïde bas = probable broadcast/radio ? débruitage doux
if centroid_light < 3500:
prop = 0.4 # Préserve la signature broadcast
raison_denoise = "Débruitage doux (source broadcast détectée)"
else:
prop = 0.7 # Débruitage standard
raison_denoise = "Débruitage standard"
y_denoised = nr.reduce_noise(y=y, sr=sr, prop_decrease=prop)
# --- MÉTRIQUES ---
pitches, magnitudes = librosa.piptrack(y=y_denoised, sr=sr)
mask = magnitudes > np.median(magnitudes)
jitter = np.std(pitches[mask]) / 1000 if np.any(mask) else 0
flatness = np.mean(librosa.feature.spectral_flatness(y=y_denoised))
# --- DÉTECTION VINTAGE ---
# Analyse du centroïde spectral — les enregistrements vintage ont
# un centroïde plus bas (fréquences hautes absentes ou atténuées)
centroid = np.mean(librosa.feature.spectral_centroid(y=y_denoised, sr=sr))
zcr = np.mean(librosa.feature.zero_crossing_rate(y_denoised))
is_vintage = centroid < 3000 and zcr < 0.06
# --- ANALYSE IA ---
top_label, score_ia = "Inconnu", 0
if self.ia:
res_ia = self.ia(path)
top_label, score_ia = res_ia[0]['label'], res_ia[0]['score'] * 100
# ==========================================
# LOGIQUE DE CONFIANCE v4.4.3
# ==========================================
confiance = 50
raisons = []
# 1. BONUS VINTAGE
if is_vintage:
confiance += 15
raisons.append("Signature vintage détectée (enregistrement ancien)")
# 2. TEST TEXTURE
if flatness > 0.0012:
confiance += 20
raisons.append("Texture organique détectée")
else:
confiance -= 25
raisons.append("Signal trop pur (Signature numérique)")
# Si signal trop pur + score IA faible ? annule les bonus vintage/broadcast
if score_ia < 70:
confiance -= 20
raisons.append("Bonus annulé — signal trop pur + source incertaine")
# 3. FILTRE ANTI-AI COVER (corrigé pour les chansons anciennes)
if "Music" in top_label or "Singing" in top_label:
if jitter > 1.0 or jitter < 0.09:
if is_vintage:
confiance += 10
raisons.append("Jitter élevé validé — enregistrement vintage analogique")
elif flatness < 0.0012:
# Seuil relevé : signal pas assez organique + jitter anormal = AI Cover
confiance -= 60
raisons.append("Instabilité vocale typique AI Cover")
else:
confiance -= 20
raisons.append("Jitter suspect — analyse inconclusif")
else:
confiance += 20
raisons.append("Harmoniques naturelles validées")
# 4. CAS RADIO/VOIX
else:
# Détection broadcast FM — jitter élevé est normal sur radio
is_broadcast = (jitter >= 0.85 and centroid_light < 3500) or prop == 0.4
if 0.10 < jitter < 0.80:
confiance += 25
raisons.append("Vibration humaine naturelle")
elif jitter >= 0.85:
if is_broadcast and flatness > 0.0010:
# Broadcast validé seulement si signal pas trop pur
confiance += 20
raisons.append("Jitter élevé normal — compression broadcast FM")
elif is_broadcast and flatness <= 0.0010:
# Signal trop pur même pour broadcast = suspect
confiance -= 30
raisons.append("Signal trop pur pour broadcast — AI Cover suspect")
elif flatness > 0.0008:
confiance += 15
raisons.append("Instabilité liée au flux radio (Validé)")
else:
confiance -= 60
raisons.append("Instabilité artificielle (Deepfake)")
confiance = max(0, min(100, confiance))
# Verdict
if confiance >= 70:
verdict = "? AUTHENTIQUE CERTIFIÉ"
elif 40 <= confiance < 70:
verdict = "?? ANALYSE INCONCLUSIVE"
else:
verdict = "?? AI COVER / DEEPFAKE DÉTECTÉ"
sha = self.get_sha256(path)
report = f"\n{'='*45}\n??? RAPPORT v4.4.5\n{'='*45}\n"
report += f" ??? SOURCE IA : {top_label} ({score_ia:.1f}%)\n"
report += f" ?? CONFIANCE : {confiance}%\n"
report += f" ?? JITTER : {jitter:.4f}\n"
report += f" ?? VINTAGE : {'Oui' if is_vintage else 'Non'}\n"
report += f" ?? DÉBRUITAGE : {raison_denoise}\n"
report += f" ?? SHA256 : {sha[:24]}...\n"
report += f"{'-'*45}\n >>> VERDICT : {verdict}\n >>> NOTES : {', '.join(raisons)}\n{'='*45}\n"
return self.generer_spectrogramme(y, sr), report, {
"Score": f"{confiance}%",
"Jitter": round(jitter, 4),
"Vintage": is_vintage,
"Centroid": round(float(centroid), 1)
}
except Exception as e:
return None, f"Erreur : {e}", None
# --- Interface Gradio ---
shield = AuthenticMusicShield()
with gr.Blocks(theme=gr.themes.Soft()) as demo:
gr.Markdown("# ??? Antigravity Shield v4.4.5 PRO")
gr.Markdown("### Détecteur d'authenticité audio — AI Cover & Deepfake")
with gr.Row():
with gr.Column():
audio_input = gr.Audio(type="filepath", label="Audio Input")
run_btn = gr.Button("?? ANALYSER", variant="primary")
with gr.Column():
image_output = gr.Image(label="Spectrogramme")
report_output = gr.Textbox(label="Rapport", lines=14)
metrics_output = gr.Json(label="Métriques")
run_btn.click(
fn=shield.analyser_expert,
inputs=audio_input,
outputs=[image_output, report_output, metrics_output]
)
demo.launch(ssr_mode=False) |