node-api / server /routers.ts
taqarub's picture
Deploy Taqarub Node API server
cd2a4c2
Raw History Blame Contribute Delete
2.47 kB
import { z } from "zod";
import { COOKIE_NAME } from "../shared/const.js";
import { getSessionCookieOptions } from "./_core/cookies";
import { systemRouter } from "./_core/systemRouter";
import { publicProcedure, router } from "./_core/trpc";
import { transcribeAudio } from "./_core/voiceTranscription";
import { storagePut } from "./storage";
export const appRouter = router({
system: systemRouter,
auth: router({
me: publicProcedure.query((opts) => opts.ctx.user),
logout: publicProcedure.mutation(({ ctx }) => {
const cookieOptions = getSessionCookieOptions(ctx.req);
ctx.res.clearCookie(COOKIE_NAME, { ...cookieOptions, maxAge: -1 });
return { success: true } as const;
}),
}),
voice: router({
/**
* يستقبل ملف صوتي مُرمَّز بـ Base64، يرفعه إلى S3، ثم يُرسله لـ Whisper للتعرف على الكلام العربي
*/
transcribe: publicProcedure
.input(
z.object({
audioBase64: z.string(), // ملف الصوت مُرمَّز بـ base64
mimeType: z.string().default("audio/m4a"), // نوع الملف
language: z.string().default("ar"), // اللغة (ar للعربية)
})
)
.mutation(async ({ input }) => {
// 1. تحويل base64 إلى Buffer
const audioBuffer = Buffer.from(input.audioBase64, "base64");
// 2. رفع الملف إلى S3 بمفتاح عشوائي
const suffix = Date.now().toString(36);
const ext = input.mimeType.split("/")[1]?.split(";")[0] ?? "m4a";
const fileKey = `voice-recordings/rec-${suffix}.${ext}`;
const { url: audioUrl } = await storagePut(
fileKey,
audioBuffer,
input.mimeType
);
// 3. إرسال الرابط لـ Whisper مع تحديد اللغة العربية
const result = await transcribeAudio({
audioUrl,
language: input.language,
prompt: "هذا تسجيل صوتي باللغة العربية",
});
// التحقق من نوع النتيجة (نجاح أو خطأ)
if ("error" in result) {
throw new Error(result.details ?? result.error);
}
return {
text: result.text ?? "",
language: result.language ?? input.language,
segments: result.segments ?? [],
};
}),
}),
});
export type AppRouter = typeof appRouter;