mirror of
https://github.com/decolua/9router.git
synced 2026-05-08 12:01:28 +00:00
40 lines
1.9 KiB
JavaScript
40 lines
1.9 KiB
JavaScript
// Shared TTS helpers
|
|
import { Buffer } from "node:buffer";
|
|
|
|
export const UA = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36";
|
|
|
|
// Convert upstream Response (binary audio) to { base64, format }
|
|
export async function responseToBase64(res, defaultFormat = "mp3") {
|
|
const buf = await res.arrayBuffer();
|
|
if (buf.byteLength < 100) throw new Error("Upstream returned empty audio");
|
|
const ctype = res.headers.get("content-type") || "";
|
|
let format = defaultFormat;
|
|
if (ctype.includes("wav")) format = "wav";
|
|
else if (ctype.includes("mpeg") || ctype.includes("mp3")) format = "mp3";
|
|
else if (ctype.includes("ogg")) format = "ogg";
|
|
return { base64: Buffer.from(buf).toString("base64"), format };
|
|
}
|
|
|
|
export async function throwUpstreamError(res) {
|
|
const text = await res.text().catch(() => "");
|
|
let msg = `Upstream error (${res.status})`;
|
|
try {
|
|
const parsed = JSON.parse(text);
|
|
msg = parsed?.error?.message || parsed?.message || parsed?.detail?.message || (typeof parsed?.detail === "string" ? parsed.detail : null) || text || msg;
|
|
} catch { msg = text || msg; }
|
|
throw new Error(msg);
|
|
}
|
|
|
|
// Parse `model` string as "modelId/voiceId" — match against known model list (longest prefix wins)
|
|
export function parseModelVoice(model, defaultModel = "", defaultVoice = "", knownModels = []) {
|
|
if (!model) return { modelId: defaultModel, voiceId: defaultVoice };
|
|
const known = knownModels.map((m) => m.id || m).filter(Boolean).sort((a, b) => b.length - a.length);
|
|
for (const id of known) {
|
|
if (model === id) return { modelId: id, voiceId: defaultVoice };
|
|
if (model.startsWith(`${id}/`)) return { modelId: id, voiceId: model.slice(id.length + 1) };
|
|
}
|
|
const idx = model.lastIndexOf("/");
|
|
if (idx > 0) return { modelId: model.slice(0, idx), voiceId: model.slice(idx + 1) };
|
|
return { modelId: defaultModel || model, voiceId: defaultVoice || model };
|
|
}
|