95 lines
3.5 KiB
TypeScript
95 lines
3.5 KiB
TypeScript
import { FastifyInstance } from "fastify";
|
|
import { VoiceEnrollmentService } from "@shieldai/voiceprint";
|
|
import { AnalysisService } from "@shieldai/voiceprint";
|
|
import { BatchAnalysisService } from "@shieldai/voiceprint";
|
|
|
|
export function voiceprintRoutes(fastify: FastifyInstance) {
|
|
const enrollmentService = new VoiceEnrollmentService();
|
|
const analysisService = new AnalysisService();
|
|
const batchService = new BatchAnalysisService();
|
|
|
|
fastify.post("/enroll", async (request, reply) => {
|
|
const userId = (request.user as { id: string })?.id;
|
|
if (!userId) return reply.code(401).send({ error: "User not authenticated" });
|
|
|
|
const body = request.body as { label: string; audio: string; sampleRate?: number };
|
|
|
|
const audioBuffer = Buffer.from(body.audio, "base64");
|
|
const enrollment = await enrollmentService.enroll(
|
|
{ label: body.label, audioBuffer, sampleRate: body.sampleRate },
|
|
userId
|
|
);
|
|
return reply.code(201).send(enrollment);
|
|
});
|
|
|
|
fastify.get("/enrollments", async (request, reply) => {
|
|
const userId = (request.user as { id: string })?.id;
|
|
if (!userId) return reply.code(401).send({ error: "User not authenticated" });
|
|
|
|
const enrollments = await enrollmentService.listEnrollments(userId);
|
|
return reply.send(enrollments);
|
|
});
|
|
|
|
fastify.delete("/enrollments/:id", async (request, reply) => {
|
|
const userId = (request.user as { id: string })?.id;
|
|
if (!userId) return reply.code(401).send({ error: "User not authenticated" });
|
|
|
|
const enrollmentId = (request.params as { id: string }).id;
|
|
const result = await enrollmentService.removeEnrollment(userId, enrollmentId);
|
|
return reply.send({ removed: result });
|
|
});
|
|
|
|
fastify.post("/analyze", async (request, reply) => {
|
|
const userId = (request.user as { id: string })?.id;
|
|
if (!userId) return reply.code(401).send({ error: "User not authenticated" });
|
|
|
|
const body = request.body as { audio: string; sampleRate?: number; analysisType?: string };
|
|
const audioBuffer = Buffer.from(body.audio, "base64");
|
|
|
|
const result = await analysisService.analyze(
|
|
{ audioBuffer, sampleRate: body.sampleRate, analysisType: body.analysisType },
|
|
userId
|
|
);
|
|
return reply.code(201).send(result);
|
|
});
|
|
|
|
fastify.get("/results/:id", async (request, reply) => {
|
|
const jobId = (request.params as { id: string }).id;
|
|
const result = await analysisService.getResult(jobId);
|
|
|
|
if (!result) return reply.code(404).send({ error: "Analysis result not found" });
|
|
return reply.send(result);
|
|
});
|
|
|
|
fastify.get("/results", async (request, reply) => {
|
|
const userId = (request.user as { id: string })?.id;
|
|
if (!userId) return reply.code(401).send({ error: "User not authenticated" });
|
|
|
|
const limit = parseInt((request.query as { limit?: string }).limit || "20", 10);
|
|
const results = await analysisService.getUserResults(userId, limit);
|
|
return reply.send(results);
|
|
});
|
|
|
|
fastify.post("/batch", async (request, reply) => {
|
|
const userId = (request.user as { id: string })?.id;
|
|
if (!userId) return reply.code(401).send({ error: "User not authenticated" });
|
|
|
|
const body = request.body as {
|
|
files: Array<{ name: string; audio: string; sampleRate?: number }>;
|
|
analysisType?: string;
|
|
};
|
|
|
|
const audioBuffers = body.files.map((f) => ({
|
|
name: f.name,
|
|
buffer: Buffer.from(f.audio, "base64"),
|
|
sampleRate: f.sampleRate,
|
|
}));
|
|
|
|
const result = await batchService.analyzeBatch(
|
|
{ audioBuffers, analysisType: body.analysisType },
|
|
userId
|
|
);
|
|
return reply.code(201).send(result);
|
|
});
|
|
}
|