- Copy apps/api (Fastify server with spamshield/voiceprint/darkwatch services) - Copy apps/web (SolidJS web app) - Copy apps/mobile (SolidJS mobile app) - Copy packages/shared-db (Prisma schema/models) - Add apps/* to pnpm-workspace.yaml
103 lines
3.2 KiB
TypeScript
103 lines
3.2 KiB
TypeScript
import { z } from 'zod';
|
|
import { checkFlag } from './voiceprint.feature-flags';
|
|
|
|
// Environment variables for VoicePrint
|
|
const envSchema = z.object({
|
|
ECAPA_TDNN_MODEL_PATH: z.string().default('./models/ecapa-tdnn'),
|
|
ML_SERVICE_URL: z.string().default('http://localhost:8001'),
|
|
FAISS_INDEX_PATH: z.string().default('./data/voiceprint_faiss.index'),
|
|
AUDIO_STORAGE_BUCKET: z.string().default('voiceprint-audio'),
|
|
AUDIO_STORAGE_ENDPOINT: z.string().default('http://localhost:9000'),
|
|
SYNTHETIC_THRESHOLD: z.string().transform(Number).default(0.75),
|
|
ENROLLMENT_MIN_DURATION_SEC: z.string().transform(Number).default(3),
|
|
ENROLLMENT_MAX_DURATION_SEC: z.string().transform(Number).default(60),
|
|
EMBEDDING_DIMENSIONS: z.string().transform(Number).default(192),
|
|
BATCH_MAX_FILES: z.string().transform(Number).default(20),
|
|
ANALYSIS_TIMEOUT_MS: z.string().transform(Number).default(30000),
|
|
});
|
|
|
|
export const voicePrintEnv = envSchema.parse({
|
|
ECAPA_TDNN_MODEL_PATH: process.env.ECAPA_TDNN_MODEL_PATH,
|
|
ML_SERVICE_URL: process.env.ML_SERVICE_URL,
|
|
FAISS_INDEX_PATH: process.env.FAISS_INDEX_PATH,
|
|
AUDIO_STORAGE_BUCKET: process.env.AUDIO_STORAGE_BUCKET,
|
|
AUDIO_STORAGE_ENDPOINT: process.env.AUDIO_STORAGE_ENDPOINT,
|
|
SYNTHETIC_THRESHOLD: process.env.SYNTHETIC_THRESHOLD,
|
|
ENROLLMENT_MIN_DURATION_SEC: process.env.ENROLLMENT_MIN_DURATION_SEC,
|
|
ENROLLMENT_MAX_DURATION_SEC: process.env.ENROLLMENT_MAX_DURATION_SEC,
|
|
EMBEDDING_DIMENSIONS: process.env.EMBEDDING_DIMENSIONS,
|
|
BATCH_MAX_FILES: process.env.BATCH_MAX_FILES,
|
|
ANALYSIS_TIMEOUT_MS: process.env.ANALYSIS_TIMEOUT_MS,
|
|
});
|
|
|
|
// Audio source types
|
|
export enum VoicePrintSource {
|
|
UPLOAD = 'upload',
|
|
S3 = 's3',
|
|
URL = 'url',
|
|
REALTIME = 'realtime',
|
|
}
|
|
|
|
// Analysis job status
|
|
export enum AnalysisJobStatus {
|
|
PENDING = 'pending',
|
|
PROCESSING = 'processing',
|
|
COMPLETED = 'completed',
|
|
FAILED = 'failed',
|
|
CANCELLED = 'cancelled',
|
|
}
|
|
|
|
// Detection result types
|
|
export enum DetectionType {
|
|
SYNTHETIC_VOICE = 'synthetic_voice',
|
|
VOICE_CLONE = 'voice_clone',
|
|
DEEPFAKE = 'deepfake',
|
|
NATURAL = 'natural',
|
|
}
|
|
|
|
// Confidence levels
|
|
export enum ConfidenceLevel {
|
|
LOW = 'low',
|
|
MEDIUM = 'medium',
|
|
HIGH = 'high',
|
|
VERY_HIGH = 'very_high',
|
|
}
|
|
|
|
// Audio preprocessing configuration
|
|
export const audioPreprocessingConfig = {
|
|
sampleRate: 16000,
|
|
channels: 1,
|
|
bitDepth: 16,
|
|
vadThreshold: 0.5,
|
|
noiseReduction: true,
|
|
maxSilenceDurationMs: 500,
|
|
};
|
|
|
|
// Feature flags - use centralized system
|
|
export const voicePrintFeatureFlags = {
|
|
enableMLService: checkFlag('voiceprint.enable.ml.service', false),
|
|
enableFAISSIndex: checkFlag('voiceprint.enable.faiss.index', true),
|
|
enableBatchAnalysis: checkFlag('voiceprint.enable.batch.analysis', true),
|
|
enableRealtimeAnalysis: checkFlag('voiceprint.enable.realtime.analysis', false),
|
|
enableMockModel: checkFlag('voiceprint.enable.mock.model', true),
|
|
};
|
|
|
|
// Rate limits for voice analysis
|
|
export const voicePrintRateLimits = {
|
|
basic: {
|
|
analysesPerMinute: 5,
|
|
enrollmentsPerDay: 10,
|
|
maxAudioFileSizeMB: 50,
|
|
},
|
|
plus: {
|
|
analysesPerMinute: 30,
|
|
enrollmentsPerDay: 50,
|
|
maxAudioFileSizeMB: 200,
|
|
},
|
|
premium: {
|
|
analysesPerMinute: 100,
|
|
enrollmentsPerDay: 500,
|
|
maxAudioFileSizeMB: 500,
|
|
},
|
|
};
|