mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-03 16:50:22 +00:00
feat(tts): enrich speech voice metadata
This commit is contained in:
@@ -27,6 +27,14 @@ function findSpeechProviderIdsForPlugin(pluginId: string) {
|
||||
.toSorted((left, right) => left.localeCompare(right));
|
||||
}
|
||||
|
||||
function findSpeechProviderForPlugin(pluginId: string) {
|
||||
const entry = speechProviderContractRegistry.find((candidate) => candidate.pluginId === pluginId);
|
||||
if (!entry) {
|
||||
throw new Error(`speech provider contract missing for ${pluginId}`);
|
||||
}
|
||||
return entry.provider;
|
||||
}
|
||||
|
||||
function findRegistrationForPlugin(pluginId: string) {
|
||||
const entry = pluginRegistrationContractRegistry.find(
|
||||
(candidate) => candidate.pluginId === pluginId,
|
||||
@@ -97,4 +105,10 @@ describe("plugin contract registry", () => {
|
||||
speechProviderIds: ["microsoft"],
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps bundled speech voice-list support explicit", () => {
|
||||
expect(findSpeechProviderForPlugin("openai").listVoices).toEqual(expect.any(Function));
|
||||
expect(findSpeechProviderForPlugin("elevenlabs").listVoices).toEqual(expect.any(Function));
|
||||
expect(findSpeechProviderForPlugin("microsoft").listVoices).toEqual(expect.any(Function));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -42,6 +42,9 @@ export type SpeechVoiceOption = {
|
||||
name?: string;
|
||||
category?: string;
|
||||
description?: string;
|
||||
locale?: string;
|
||||
gender?: string;
|
||||
personalities?: string[];
|
||||
};
|
||||
|
||||
export type SpeechListVoicesRequest = {
|
||||
|
||||
@@ -35,7 +35,10 @@ describe("listMicrosoftVoices", () => {
|
||||
id: "en-US-AvaNeural",
|
||||
name: "Microsoft Ava Online (Natural) - English (United States)",
|
||||
category: "General",
|
||||
description: "en-US · Female · Friendly, Positive",
|
||||
description: "Friendly, Positive",
|
||||
locale: "en-US",
|
||||
gender: "Female",
|
||||
personalities: ["Friendly", "Positive"],
|
||||
},
|
||||
]);
|
||||
expect(globalThis.fetch).toHaveBeenCalledWith(
|
||||
|
||||
@@ -39,13 +39,8 @@ function buildMicrosoftVoiceHeaders(): Record<string, string> {
|
||||
}
|
||||
|
||||
function formatMicrosoftVoiceDescription(entry: MicrosoftVoiceListEntry): string | undefined {
|
||||
const parts = [entry.Locale, entry.Gender];
|
||||
const personalities = entry.VoiceTag?.VoicePersonalities?.filter(Boolean) ?? [];
|
||||
if (personalities.length > 0) {
|
||||
parts.push(personalities.join(", "));
|
||||
}
|
||||
const filtered = parts.filter((part): part is string => Boolean(part?.trim()));
|
||||
return filtered.length > 0 ? filtered.join(" · ") : undefined;
|
||||
return personalities.length > 0 ? personalities.join(", ") : undefined;
|
||||
}
|
||||
|
||||
export async function listMicrosoftVoices(): Promise<SpeechVoiceOption[]> {
|
||||
@@ -67,6 +62,11 @@ export async function listMicrosoftVoices(): Promise<SpeechVoiceOption[]> {
|
||||
name: voice.FriendlyName?.trim() || voice.ShortName?.trim() || undefined,
|
||||
category: voice.VoiceTag?.ContentCategories?.find((value) => value.trim().length > 0),
|
||||
description: formatMicrosoftVoiceDescription(voice),
|
||||
locale: voice.Locale?.trim() || undefined,
|
||||
gender: voice.Gender?.trim() || undefined,
|
||||
personalities: voice.VoiceTag?.VoicePersonalities?.filter(
|
||||
(value): value is string => value.trim().length > 0,
|
||||
),
|
||||
}))
|
||||
.filter((voice) => voice.id.length > 0)
|
||||
: [];
|
||||
|
||||
Reference in New Issue
Block a user