Hive_2 / voiceprint.py
Paulhayes's picture
Create voiceprint.py
5d4b193 verified
import numpy as np
import librosa
from pathlib import Path
import hashlib
from cryptography.fernet import Fernet
import os
import json
class VoicePrint:
def __init__(self, hive_home):
self.hive_home = Path(hive_home)
self.vp_dir = self.hive_home / "users" / "voiceprints"
self.vp_dir.mkdir(parents=True, exist_ok=True)
self.key = os.getenv("VP_KEY", Fernet.generate_key().decode())
self.cipher = Fernet(self.key.encode())
self.users_file = self.hive_home / "users" / "profiles.json"
self.users = self.load_users()
def load_users(self):
if self.users_file.exists():
return json.loads(self.users_file.read_text())
return {}
def save_users(self):
self.users_file.write_text(json.dumps(self.users, indent=2))
def extract_features(self, audio_path):
try:
y, sr = librosa.load(str(audio_path), sr=16000)
mfcc = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=20)
return np.hstack([np.mean(mfcc, axis=1), np.std(mfcc, axis=1)])
except:
return np.zeros(40)
def enroll(self, audio_path, user_id):
features = self.extract_features(audio_path)
encrypted = self.cipher.encrypt(features.tobytes())
fp = self.vp_dir / f"{user_id}.vp"
fp.write_bytes(encrypted)
# Update user profile
if user_id not in self.users:
self.users[user_id] = {"id": user_id, "voice_enrolled": True}
else:
self.users[user_id]["voice_enrolled"] = True
self.save_users()
return True
def verify(self, audio_path, user_id):
stored_fp = self.vp_dir / f"{user_id}.vp"
if not stored_fp.exists():
return 0.0
try:
encrypted = stored_fp.read_bytes()
decrypted = self.cipher.decrypt(encrypted)
stored = np.frombuffer(decrypted, dtype=np.float64)
current = self.extract_features(audio_path)
if np.linalg.norm(current) == 0 or np.linalg.norm(stored) == 0:
return 0.0
return np.dot(stored, current) / (np.linalg.norm(stored) * np.linalg.norm(current))
except:
return 0.0
def identify(self, audio_path):
current = self.extract_features(audio_path)
if np.linalg.norm(current) == 0:
return None
best_score = 0.0
best_user = None
for fp in self.vp_dir.glob("*.vp"):
user_id = fp.stem
score = self.verify(audio_path, user_id)
if score > best_score and score >= 0.7:
best_score = score
best_user = user_id
return best_user