@pico-brief/speech-services 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/providers/azure/recommended-voices.d.ts +3 -0
- package/dist/providers/azure/recommended-voices.d.ts.map +1 -0
- package/dist/providers/azure/recommended-voices.js +22 -0
- package/dist/providers/azure/recommended-voices.js.map +1 -0
- package/dist/synthesize.d.ts.map +1 -1
- package/dist/synthesize.js +8 -4
- package/dist/synthesize.js.map +1 -1
- package/dist/voice-resolver.d.ts +7 -1
- package/dist/voice-resolver.d.ts.map +1 -1
- package/dist/voice-resolver.js +51 -3
- package/dist/voice-resolver.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recommended-voices.d.ts","sourceRoot":"","sources":["../../../src/providers/azure/recommended-voices.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,eAAO,MAAM,wBAAwB,EAAE,gBAAgB,EAuBtD,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export const AZURE_RECOMMENDED_VOICES = [
|
|
2
|
+
{ name: "en-US-AvaMultilingualNeural", gender: "female" },
|
|
3
|
+
{ name: "en-US-EmmaNeural", gender: "female" },
|
|
4
|
+
{ name: "en-US-JennyMultilingualNeural", gender: "female" },
|
|
5
|
+
{ name: "en-US-AmandaMultilingualNeural", gender: "female" },
|
|
6
|
+
{ name: "en-US-NovaTurboMultilingualNeural", gender: "female" },
|
|
7
|
+
{ name: "en-US-AndrewMultilingualNeural", gender: "male" },
|
|
8
|
+
{ name: "en-US-KaiNeural", gender: "male" },
|
|
9
|
+
{ name: "en-US-BrandonMultilingualNeural", gender: "male" },
|
|
10
|
+
{ name: "en-US-ChristopherNeural", gender: "male" },
|
|
11
|
+
{ name: "en-US-AdamMultilingualNeural", gender: "male" },
|
|
12
|
+
{ name: "en-US-DavisMultilingualNeural", gender: "male" },
|
|
13
|
+
{ name: "en-US-LewisMultilingualNeural", gender: "male" },
|
|
14
|
+
{ name: "en-US-SamuelMultilingualNeural", gender: "male" },
|
|
15
|
+
{ name: "zh-CN-XiaoxiaoNeural", gender: "female" },
|
|
16
|
+
{ name: "zh-CN-XiaochenNeural", gender: "female" },
|
|
17
|
+
{ name: "zh-CN-XiaoyanNeural", gender: "female" },
|
|
18
|
+
{ name: "zh-CN-XiaoyuMultilingualNeural", gender: "female" },
|
|
19
|
+
{ name: "zh-CN-YunxiNeural", gender: "male" },
|
|
20
|
+
{ name: "zh-CN-YunyangNeural", gender: "male" },
|
|
21
|
+
];
|
|
22
|
+
//# sourceMappingURL=recommended-voices.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recommended-voices.js","sourceRoot":"","sources":["../../../src/providers/azure/recommended-voices.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,wBAAwB,GAAuB;IACxD,EAAE,IAAI,EAAE,6BAA6B,EAAE,MAAM,EAAE,QAAQ,EAAE;IACzD,EAAE,IAAI,EAAE,kBAAkB,EAAE,MAAM,EAAE,QAAQ,EAAE;IAC9C,EAAE,IAAI,EAAE,+BAA+B,EAAE,MAAM,EAAE,QAAQ,EAAE;IAC3D,EAAE,IAAI,EAAE,gCAAgC,EAAE,MAAM,EAAE,QAAQ,EAAE;IAC5D,EAAE,IAAI,EAAE,mCAAmC,EAAE,MAAM,EAAE,QAAQ,EAAE;IAE/D,EAAE,IAAI,EAAE,gCAAgC,EAAE,MAAM,EAAE,MAAM,EAAE;IAC1D,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM,EAAE;IAC3C,EAAE,IAAI,EAAE,iCAAiC,EAAE,MAAM,EAAE,MAAM,EAAE;IAC3D,EAAE,IAAI,EAAE,yBAAyB,EAAE,MAAM,EAAE,MAAM,EAAE;IACnD,EAAE,IAAI,EAAE,8BAA8B,EAAE,MAAM,EAAE,MAAM,EAAE;IACxD,EAAE,IAAI,EAAE,+BAA+B,EAAE,MAAM,EAAE,MAAM,EAAE;IACzD,EAAE,IAAI,EAAE,+BAA+B,EAAE,MAAM,EAAE,MAAM,EAAE;IACzD,EAAE,IAAI,EAAE,gCAAgC,EAAE,MAAM,EAAE,MAAM,EAAE;IAE1D,EAAE,IAAI,EAAE,sBAAsB,EAAE,MAAM,EAAE,QAAQ,EAAE;IAClD,EAAE,IAAI,EAAE,sBAAsB,EAAE,MAAM,EAAE,QAAQ,EAAE;IAClD,EAAE,IAAI,EAAE,qBAAqB,EAAE,MAAM,EAAE,QAAQ,EAAE;IACjD,EAAE,IAAI,EAAE,gCAAgC,EAAE,MAAM,EAAE,QAAQ,EAAE;IAE5D,EAAE,IAAI,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM,EAAE;IAC7C,EAAE,IAAI,EAAE,qBAAqB,EAAE,MAAM,EAAE,MAAM,EAAE;CAClD,CAAC"}
|
package/dist/synthesize.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"synthesize.d.ts","sourceRoot":"","sources":["../src/synthesize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAa,MAAM,YAAY,CAAC;AAE9F,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"synthesize.d.ts","sourceRoot":"","sources":["../src/synthesize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAa,MAAM,YAAY,CAAC;AAE9F,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAW9C,wBAAsB,UAAU,CAC5B,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,gBAAgB,EACxB,UAAU,CAAC,EAAE,UAAU,GACxB,OAAO,CAAC,gBAAgB,CAAC,CA4D3B"}
|
package/dist/synthesize.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { SpeechServiceError } from "./errors.js";
|
|
2
2
|
import { VoiceCache } from "./voice-cache.js";
|
|
3
|
-
import { resolveVoice } from "./voice-resolver.js";
|
|
3
|
+
import { resolveVoice, validateRecommendedVoices } from "./voice-resolver.js";
|
|
4
|
+
import { AZURE_RECOMMENDED_VOICES } from "./providers/azure/recommended-voices.js";
|
|
4
5
|
import * as azure from "./providers/azure/index.js";
|
|
5
6
|
import * as cartesia from "./providers/cartesia/index.js";
|
|
6
7
|
import * as deepgram from "./providers/deepgram/index.js";
|
|
@@ -13,7 +14,7 @@ export async function synthesize(config, params, voiceCache) {
|
|
|
13
14
|
switch (params.provider) {
|
|
14
15
|
case "azure": {
|
|
15
16
|
const cfg = requireConfig(config, "azure", "Azure");
|
|
16
|
-
const resolvedVoice = await resolveVoiceForProvider(cache, () => azure.fetchVoices(cfg), `azure:${cfg.region}`, params);
|
|
17
|
+
const resolvedVoice = await resolveVoiceForProvider(cache, () => azure.fetchVoices(cfg), `azure:${cfg.region}`, params, AZURE_RECOMMENDED_VOICES);
|
|
17
18
|
return azure.synthesize(cfg, params.text, resolvedVoice, params.languages?.[0], params.providerOptions);
|
|
18
19
|
}
|
|
19
20
|
case "cartesia": {
|
|
@@ -57,17 +58,20 @@ function requireConfig(config, provider, displayName) {
|
|
|
57
58
|
}
|
|
58
59
|
return providerConfig;
|
|
59
60
|
}
|
|
60
|
-
async function resolveVoiceForProvider(cache, fetchFn, cacheKey, params) {
|
|
61
|
+
async function resolveVoiceForProvider(cache, fetchFn, cacheKey, params, recommendedVoices) {
|
|
61
62
|
let voices = cache.get(cacheKey);
|
|
62
63
|
if (!voices) {
|
|
63
64
|
voices = await fetchFn();
|
|
64
65
|
cache.set(cacheKey, voices);
|
|
66
|
+
if (recommendedVoices) {
|
|
67
|
+
validateRecommendedVoices(voices, recommendedVoices);
|
|
68
|
+
}
|
|
65
69
|
}
|
|
66
70
|
const resolved = resolveVoice(voices, {
|
|
67
71
|
voice: params.voice,
|
|
68
72
|
language: params.languages?.[0],
|
|
69
73
|
gender: params.gender,
|
|
70
|
-
});
|
|
74
|
+
}, recommendedVoices);
|
|
71
75
|
return resolved.id;
|
|
72
76
|
}
|
|
73
77
|
//# sourceMappingURL=synthesize.js.map
|
package/dist/synthesize.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"synthesize.js","sourceRoot":"","sources":["../src/synthesize.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"synthesize.js","sourceRoot":"","sources":["../src/synthesize.ts"],"names":[],"mappings":"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"}
|
package/dist/voice-resolver.d.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import type { VoiceInfo } from "./types.js";
|
|
2
|
+
export interface RecommendedVoice {
|
|
3
|
+
name: string;
|
|
4
|
+
gender: "male" | "female";
|
|
5
|
+
}
|
|
2
6
|
export declare function resolveVoice(voices: VoiceInfo[], params: {
|
|
3
7
|
voice?: string;
|
|
4
8
|
language?: string;
|
|
5
9
|
gender?: "male" | "female";
|
|
6
|
-
}): VoiceInfo;
|
|
10
|
+
}, recommendedVoices?: RecommendedVoice[]): VoiceInfo;
|
|
11
|
+
/** Validate that all recommended voices exist in the available voice list. Warns for any missing. */
|
|
12
|
+
export declare function validateRecommendedVoices(voices: VoiceInfo[], recommended: RecommendedVoice[]): void;
|
|
7
13
|
//# sourceMappingURL=voice-resolver.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"voice-resolver.d.ts","sourceRoot":"","sources":["../src/voice-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG5C,wBAAgB,YAAY,CACxB,MAAM,EAAE,SAAS,EAAE,EACnB,MAAM,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"voice-resolver.d.ts","sourceRoot":"","sources":["../src/voice-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG5C,MAAM,WAAW,gBAAgB;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAC;CAC7B;AAED,wBAAgB,YAAY,CACxB,MAAM,EAAE,SAAS,EAAE,EACnB,MAAM,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAA;CAAE,EACzE,iBAAiB,CAAC,EAAE,gBAAgB,EAAE,GACvC,SAAS,CAKX;AAED,qGAAqG;AACrG,wBAAgB,yBAAyB,CACrC,MAAM,EAAE,SAAS,EAAE,EACnB,WAAW,EAAE,gBAAgB,EAAE,GAChC,IAAI,CAON"}
|
package/dist/voice-resolver.js
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import { SpeechServiceError } from "./errors.js";
|
|
2
|
-
export function resolveVoice(voices, params) {
|
|
2
|
+
export function resolveVoice(voices, params, recommendedVoices) {
|
|
3
3
|
if (params.voice) {
|
|
4
4
|
return resolveByVoice(voices, params.voice, params.gender);
|
|
5
5
|
}
|
|
6
|
-
return resolveByLanguage(voices, params.language, params.gender);
|
|
6
|
+
return resolveByLanguage(voices, params.language, params.gender, recommendedVoices);
|
|
7
|
+
}
|
|
8
|
+
/** Validate that all recommended voices exist in the available voice list. Warns for any missing. */
|
|
9
|
+
export function validateRecommendedVoices(voices, recommended) {
|
|
10
|
+
for (const rec of recommended) {
|
|
11
|
+
const found = voices.some((v) => v.id.toLowerCase() === rec.name.toLowerCase());
|
|
12
|
+
if (!found) {
|
|
13
|
+
console.warn(`Recommended voice "${rec.name}" is not available in the voice list`);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
7
16
|
}
|
|
8
17
|
function resolveByVoice(voices, voice, gender) {
|
|
9
18
|
const voiceLower = voice.toLowerCase();
|
|
@@ -31,10 +40,16 @@ function resolveByVoice(voices, voice, gender) {
|
|
|
31
40
|
}
|
|
32
41
|
throw new SpeechServiceError(`Voice "${voice}" not found and no similar voice available`, "VOICE_NOT_FOUND");
|
|
33
42
|
}
|
|
34
|
-
function resolveByLanguage(voices, language, gender) {
|
|
43
|
+
function resolveByLanguage(voices, language, gender, recommendedVoices) {
|
|
35
44
|
if (!language) {
|
|
36
45
|
throw new SpeechServiceError("Either voice or languages must be provided for speech synthesis", "INVALID_INPUT");
|
|
37
46
|
}
|
|
47
|
+
// 0. Try recommended voices first
|
|
48
|
+
if (recommendedVoices?.length) {
|
|
49
|
+
const recommended = pickRecommended(voices, recommendedVoices, language, gender);
|
|
50
|
+
if (recommended)
|
|
51
|
+
return recommended;
|
|
52
|
+
}
|
|
38
53
|
// 1. Exact locale match
|
|
39
54
|
const match = pickByLocale(voices, language, gender);
|
|
40
55
|
if (match)
|
|
@@ -46,6 +61,39 @@ function resolveByLanguage(voices, language, gender) {
|
|
|
46
61
|
return baseMatch;
|
|
47
62
|
throw new SpeechServiceError(`No voice found for language "${language}"`, "VOICE_NOT_FOUND");
|
|
48
63
|
}
|
|
64
|
+
/** Pick the best voice from the recommended list that matches locale/language and gender, and is available. */
|
|
65
|
+
function pickRecommended(voices, recommended, language, gender) {
|
|
66
|
+
const langLower = language.toLowerCase();
|
|
67
|
+
// 1. Filter by exact locale (e.g. "en-US")
|
|
68
|
+
let candidates = recommended.filter((r) => {
|
|
69
|
+
const locale = extractLocale(r.name);
|
|
70
|
+
return locale?.toLowerCase() === langLower;
|
|
71
|
+
});
|
|
72
|
+
// 2. If no locale match, try base language (e.g. "en")
|
|
73
|
+
if (candidates.length === 0) {
|
|
74
|
+
const baseLang = language.split("-")[0].toLowerCase();
|
|
75
|
+
candidates = recommended.filter((r) => {
|
|
76
|
+
const locale = extractLocale(r.name);
|
|
77
|
+
return locale?.split("-")[0].toLowerCase() === baseLang;
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
if (candidates.length === 0)
|
|
81
|
+
return undefined;
|
|
82
|
+
// 3. Filter by gender if specified
|
|
83
|
+
if (gender) {
|
|
84
|
+
const genderFiltered = candidates.filter((r) => r.gender === gender);
|
|
85
|
+
if (genderFiltered.length > 0) {
|
|
86
|
+
candidates = genderFiltered;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// 4. Return the first candidate that exists in the available voices
|
|
90
|
+
for (const candidate of candidates) {
|
|
91
|
+
const voice = voices.find((v) => v.id.toLowerCase() === candidate.name.toLowerCase());
|
|
92
|
+
if (voice)
|
|
93
|
+
return voice;
|
|
94
|
+
}
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
49
97
|
/** Try to extract a BCP-47 locale from a voice name (e.g. "en-US-JennyNeural" → "en-US") */
|
|
50
98
|
function extractLocale(voice) {
|
|
51
99
|
const match = voice.match(/^([a-z]{2,3}-[A-Z]{2})/i);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"voice-resolver.js","sourceRoot":"","sources":["../src/voice-resolver.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"voice-resolver.js","sourceRoot":"","sources":["../src/voice-resolver.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pico-brief/speech-services",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Unified speech-to-text and text-to-speech library wrapping AssemblyAI, Azure, Cartesia, Deepgram, ElevenLabs, Google, OpenAI, PlayHT, Rev.ai, and Speechmatics",
|
|
6
6
|
"main": "dist/index.js",
|