-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscript.py
More file actions
102 lines (78 loc) · 3.09 KB
/
Copy pathscript.py
File metadata and controls
102 lines (78 loc) · 3.09 KB
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
import librosa
import numpy as np
from scipy.spatial.distance import euclidean
from librosa.sequence import dtw
import os
import sys
SEUIL_BIO = 44.0 # En dessous = meme personne
SEUIL_TXT = 2250 # En dessous = meme phrase
def charger_audio(chemin):
# Nettoyage du chemin pour compatibilité terminal
chemin = chemin.strip().strip('"').strip("'")
if not os.path.exists(chemin):
print(f"Erreur: fichier introuvable {chemin}")
return None, None
try:
# Chargement à 4kHz (standard voix) mais *2 pour le frequence d'échantillonnage
y, sr = librosa.load(chemin, sr=8000)
# Suppression des silences début/fin pour optimiser la comparaison
y, _ = librosa.effects.trim(y, top_db=20)
return y, sr
except Exception as e:
print(f"Erreur lecture: {e}")
return None, None
def calcul_mfcc(y, sr):
# Extraction des caractéristiques fréquentielles (13 coefficients)
# Hop_length definit la resolution temporelle
return librosa.feature.mfcc(y=y, sr=sr, n_mfcc=13, hop_length=512)
def score_biometrie(mfcc1, mfcc2):
"""
Compare le timbre de voix.
Methode: Distance euclidienne sur les moyennes temporelles.
"""
# Moyenne sur l'axe du temps (réduction vecteur)
vec1 = np.mean(mfcc1, axis=1)
vec2 = np.mean(mfcc2, axis=1)
return euclidean(vec1, vec2)
def score_mot_de_passe(mfcc1, mfcc2):
"""
Compare le contenu prononcé.
Methode: DTW (Dynamic Time Warping) pour aligner les sequences.
"""
# Calcul de la matrice de cout (metric cosine souvent plus robuste pour spectres)
D, wp = dtw(mfcc1, mfcc2, subseq=True)
# Cout normalise par la longueur du chemin
return D[-1, -1]
def main(f_ref, f_test):
global SEUIL_BIO, SEUIL_TXT
# Chargement
y_ref, sr_ref = charger_audio(f_ref)
y_test, sr_test = charger_audio(f_test)
if y_ref is None or y_test is None:
return
mfcc_ref = calcul_mfcc(y_ref, sr_ref)
mfcc_test = calcul_mfcc(y_test, sr_test)
# Calcul de la distances entre les deux vocaux
dist_bio = score_biometrie(mfcc_ref, mfcc_test)
dist_txt = score_mot_de_passe(mfcc_ref, mfcc_test)
# Affichage resultats
print(f"Fichier reference : {f_ref}")
print(f"Fichier test : {f_test}")
print("-" * 30)
print(f"Distance Timbre (Bio) : {dist_bio:.2f} (Seuil: {SEUIL_BIO})")
print(f"Distance Phrase (DTW) : {dist_txt:.3f} (Seuil: {SEUIL_TXT})")
print("-" * 30)
auth_bio = dist_bio < SEUIL_BIO
auth_txt = dist_txt < SEUIL_TXT
if auth_bio and auth_txt:
print("RESULTAT : ACCES AUTORISE")
else:
print("RESULTAT : ACCES REFUSE")
if not auth_bio: print(" -> Identite non reconnue")
if not auth_txt: print(" -> Phrase incorrecte")
if __name__ == "__main__":
# Gestion arguments ligne de commande ou interactif
if len(sys.argv) == 3:
main(sys.argv[1], sys.argv[2])
else:
print("Usage: python app.py <fichier_test1.wav> <fichier_test2.wav>")