mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-09-22 12:03:25 -04:00
refactor: list available voices independent of locale configs
This commit is contained in:
parent
76aaf672cb
commit
3d44d773e8
@ -1,3 +1,22 @@
|
||||
<script setup lang="ts">
|
||||
import type { VoiceKey } from '#shared/pronunciation/voices.ts';
|
||||
import useConfig from '~/composables/useConfig.ts';
|
||||
|
||||
defineProps<{
|
||||
pronunciation: string;
|
||||
text?: boolean;
|
||||
}>();
|
||||
|
||||
const config = useConfig();
|
||||
|
||||
const voices = computed((): VoiceKey[] => {
|
||||
if (!config.pronunciation?.enabled) {
|
||||
return [];
|
||||
}
|
||||
return config.pronunciation.voices;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<span class="text-nowrap">
|
||||
<span v-if="text" class="text-pronunciation">
|
||||
@ -13,33 +32,6 @@
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
import useConfig from '../composables/useConfig.ts';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
pronunciation: { required: true, type: String },
|
||||
text: { default: false, type: Boolean },
|
||||
},
|
||||
setup() {
|
||||
return {
|
||||
config: useConfig(),
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
voices(): string[] {
|
||||
if (this.config.pronunciation?.enabled) {
|
||||
return Object.keys(this.config.pronunciation.voices);
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "~/assets/variables";
|
||||
|
||||
|
@ -1,3 +1,41 @@
|
||||
<script setup lang="ts">
|
||||
import { escapePronunciationString, unescapePronunciationString } from '#shared/helpers.ts';
|
||||
import type { VoiceKey } from '#shared/pronunciation/voices.ts';
|
||||
import useConfig from '~/composables/useConfig.ts';
|
||||
|
||||
const modelValue = defineModel<string | null>({ required: true });
|
||||
|
||||
const config = useConfig();
|
||||
|
||||
const rawPronunciation = computed({
|
||||
get(): string {
|
||||
if (modelValue.value) {
|
||||
const phonemes = modelValue.value.substring(1, modelValue.value.length - 1);
|
||||
return unescapePronunciationString(phonemes);
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
set(rawPronunciation: string) {
|
||||
let pronunciation;
|
||||
if (rawPronunciation) {
|
||||
pronunciation = `/${escapePronunciationString(rawPronunciation)}/`;
|
||||
} else {
|
||||
pronunciation = null;
|
||||
}
|
||||
|
||||
modelValue.value = pronunciation;
|
||||
},
|
||||
});
|
||||
|
||||
const voices = computed((): VoiceKey[] => {
|
||||
if (!config.pronunciation?.enabled) {
|
||||
return [];
|
||||
}
|
||||
return config.pronunciation.voices;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="input-group input-group-sm w-auto">
|
||||
<span class="input-group-text">/</span>
|
||||
@ -17,53 +55,3 @@
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import type { PropType } from 'vue';
|
||||
|
||||
import useConfig from '../composables/useConfig.ts';
|
||||
|
||||
import { escapePronunciationString, unescapePronunciationString } from '#shared/helpers.ts';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
modelValue: { default: null, type: String as PropType<string | null> },
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
setup() {
|
||||
return {
|
||||
config: useConfig(),
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
rawPronunciation: {
|
||||
get(): string {
|
||||
if (this.modelValue) {
|
||||
const phonemes = this.modelValue.substring(1, this.modelValue.length - 1);
|
||||
return unescapePronunciationString(phonemes);
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
set(rawPronunciation: string) {
|
||||
let pronunciation;
|
||||
if (rawPronunciation) {
|
||||
pronunciation = `/${escapePronunciationString(rawPronunciation)}/`;
|
||||
} else {
|
||||
pronunciation = null;
|
||||
}
|
||||
|
||||
this.$emit('update:modelValue', pronunciation);
|
||||
},
|
||||
},
|
||||
voices(): string[] {
|
||||
if (this.config.pronunciation?.enabled) {
|
||||
return Object.keys(this.config.pronunciation.voices);
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
@ -1,9 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import { Base64 } from 'js-base64';
|
||||
|
||||
import type { VoiceKey } from '#shared/pronunciation/voices.ts';
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
pronunciation?: string | null;
|
||||
voice: string;
|
||||
voice: VoiceKey;
|
||||
button?: boolean;
|
||||
}>(), {
|
||||
pronunciation: null,
|
||||
@ -58,16 +60,16 @@ const icon = computed((): string => {
|
||||
const config = useConfig();
|
||||
const name = computed((): string | null => {
|
||||
if (!config.pronunciation?.enabled) {
|
||||
return props.voice;
|
||||
return props.voice.toUpperCase();
|
||||
}
|
||||
|
||||
const voices = Object.keys(config.pronunciation.voices);
|
||||
const voices = config.pronunciation.voices;
|
||||
if (voices.length === 1 && props.voice === voices[0]) {
|
||||
// don’t show voice name if it is considered the main voice for this locale
|
||||
return null;
|
||||
}
|
||||
|
||||
return props.voice;
|
||||
return props.voice.toUpperCase();
|
||||
});
|
||||
</script>
|
||||
|
||||
|
@ -99,11 +99,7 @@ pronouns:
|
||||
|
||||
pronunciation:
|
||||
enabled: true
|
||||
voices:
|
||||
GB:
|
||||
language: 'en-GB'
|
||||
voice: 'Emma'
|
||||
engine: 'neural'
|
||||
voices: ['gb']
|
||||
|
||||
sources:
|
||||
enabled: true
|
||||
|
@ -51,15 +51,7 @@ pronouns:
|
||||
|
||||
pronunciation:
|
||||
enabled: true
|
||||
voices:
|
||||
AR:
|
||||
language: 'arb'
|
||||
voice: 'Zeina'
|
||||
engine: 'standard'
|
||||
AE:
|
||||
language: 'ar-AE'
|
||||
voice: 'Hala'
|
||||
engine: 'neural'
|
||||
voices: ['ar', 'ae']
|
||||
|
||||
sources:
|
||||
enabled: false
|
||||
|
@ -1,7 +1,6 @@
|
||||
import type { Engine, LanguageCode, VoiceId } from '@aws-sdk/client-polly';
|
||||
|
||||
import type { Category } from '#shared/classes.ts';
|
||||
import type { GrammarTablesDefinition } from '#shared/language/grammarTables.ts';
|
||||
import type { VoiceKey } from '#shared/pronunciation/voices.ts';
|
||||
import type { LocaleCode } from '~~/locale/locales.ts';
|
||||
|
||||
export type Toggable<T> = ({ enabled: true } & T) | { enabled: false } & Partial<T>;
|
||||
@ -404,45 +403,7 @@ interface PronunciationConfig {
|
||||
* whether to treat letter graphemes as phonemes. useful when the configured locale has no matching voice
|
||||
*/
|
||||
ipa?: boolean;
|
||||
voices: Record<string, PronunciationVoiceConfig>;
|
||||
}
|
||||
|
||||
export type PronunciationVoiceConfig = AwsPollyPronunciationVoiceConfig | NarakeetPronunciationVoiceConfig;
|
||||
|
||||
/**
|
||||
* @see https://docs.aws.amazon.com/polly/latest/dg/voicelist.html
|
||||
*/
|
||||
export interface AwsPollyPronunciationVoiceConfig {
|
||||
/**
|
||||
* text-to-speech provider (aws_polly is the default, if not specified)
|
||||
*/
|
||||
provider?: 'aws_polly';
|
||||
/**
|
||||
* language code
|
||||
*/
|
||||
language: LanguageCode;
|
||||
/**
|
||||
* voice name
|
||||
*/
|
||||
voice: VoiceId;
|
||||
/**
|
||||
* voice engine (default: 'standard')
|
||||
*/
|
||||
engine?: Engine;
|
||||
}
|
||||
export interface NarakeetPronunciationVoiceConfig {
|
||||
/**
|
||||
* text-to-speech provider
|
||||
*/
|
||||
provider: 'narakeet';
|
||||
/**
|
||||
* language code
|
||||
*/
|
||||
language: string;
|
||||
/**
|
||||
* voice name
|
||||
*/
|
||||
voice: string;
|
||||
voices: VoiceKey[];
|
||||
}
|
||||
|
||||
interface SourcesConfig {
|
||||
|
@ -149,11 +149,7 @@ pronouns:
|
||||
|
||||
pronunciation:
|
||||
enabled: true
|
||||
voices:
|
||||
GB:
|
||||
language: 'en-GB'
|
||||
voice: 'Emma'
|
||||
engine: 'neural'
|
||||
voices: ['gb']
|
||||
|
||||
sources:
|
||||
enabled: true
|
||||
|
@ -97,7 +97,6 @@ pronouns:
|
||||
|
||||
pronunciation:
|
||||
enabled: false
|
||||
voices: {}
|
||||
|
||||
sources:
|
||||
enabled: true
|
||||
|
@ -128,15 +128,7 @@ pronouns:
|
||||
|
||||
pronunciation:
|
||||
enabled: true
|
||||
voices:
|
||||
ES:
|
||||
language: 'es-ES'
|
||||
voice: 'Lucia'
|
||||
engine: 'standard'
|
||||
MX:
|
||||
language: 'es-MX'
|
||||
voice: 'Mia'
|
||||
engine: 'standard'
|
||||
voices: ['es', 'mx']
|
||||
|
||||
sources:
|
||||
enabled: true
|
||||
|
@ -37,11 +37,7 @@ pronouns:
|
||||
|
||||
pronunciation:
|
||||
enabled: false
|
||||
voices:
|
||||
FI:
|
||||
language: 'fi-FI'
|
||||
voice: 'Suvi'
|
||||
engine: 'neural'
|
||||
voices: ['fi']
|
||||
|
||||
sources:
|
||||
enabled: true
|
||||
|
@ -133,11 +133,6 @@ pronouns:
|
||||
|
||||
pronunciation:
|
||||
enabled: false
|
||||
voices:
|
||||
GB:
|
||||
language: 'en-GB'
|
||||
voice: 'Emma'
|
||||
engine: 'neural'
|
||||
|
||||
sources:
|
||||
enabled: true
|
||||
|
@ -65,15 +65,7 @@ pronouns:
|
||||
|
||||
pronunciation:
|
||||
enabled: true
|
||||
voices:
|
||||
FR:
|
||||
language: 'fr-FR'
|
||||
voice: 'Lea'
|
||||
engine: 'standard'
|
||||
CA:
|
||||
language: 'fr-CA'
|
||||
voice: 'Gabrielle'
|
||||
engine: 'neural'
|
||||
voices: ['fr', 'ca']
|
||||
|
||||
sources:
|
||||
enabled: true
|
||||
|
@ -79,8 +79,7 @@ pronouns:
|
||||
shortMorphemes: 3
|
||||
|
||||
pronunciation:
|
||||
enabled: true
|
||||
voices: {}
|
||||
enabled: false
|
||||
|
||||
sources:
|
||||
enabled: true
|
||||
|
@ -98,19 +98,7 @@ pronouns:
|
||||
|
||||
pronunciation:
|
||||
enabled: true
|
||||
voices:
|
||||
BOS:
|
||||
language: 'bos'
|
||||
voice: 'suada'
|
||||
provider: 'narakeet'
|
||||
HRV:
|
||||
language: 'hrv'
|
||||
voice: 'jasna'
|
||||
provider: 'narakeet'
|
||||
SRP:
|
||||
language: 'srp'
|
||||
voice: 'milica-latin'
|
||||
provider: 'narakeet'
|
||||
voices: ['bos', 'hrv', 'srp']
|
||||
|
||||
sources:
|
||||
enabled: true
|
||||
|
@ -44,12 +44,7 @@ pronouns:
|
||||
others: 'Other pronouns'
|
||||
|
||||
pronunciation:
|
||||
enabled: true
|
||||
voices:
|
||||
GB:
|
||||
language: 'en-GB'
|
||||
voice: 'Emma'
|
||||
engine: 'neural'
|
||||
enabled: false
|
||||
|
||||
sources:
|
||||
enabled: true
|
||||
|
@ -324,11 +324,7 @@ pronouns:
|
||||
|
||||
pronunciation:
|
||||
enabled: true
|
||||
voices:
|
||||
IT:
|
||||
language: 'it-IT'
|
||||
voice: 'Bianca'
|
||||
engine: 'neural'
|
||||
voices: ['it']
|
||||
|
||||
sources:
|
||||
enabled: true
|
||||
|
@ -45,11 +45,7 @@ pronouns:
|
||||
|
||||
pronunciation:
|
||||
enabled: true
|
||||
voices:
|
||||
JA:
|
||||
language: 'ja-JP'
|
||||
voice: 'Mizuki'
|
||||
engine: 'standard'
|
||||
voices: ['ja']
|
||||
|
||||
sources:
|
||||
enabled: true
|
||||
|
@ -40,11 +40,7 @@ pronouns:
|
||||
|
||||
pronunciation:
|
||||
enabled: true
|
||||
voices:
|
||||
KO:
|
||||
language: 'ko-KR'
|
||||
voice: 'Seoyeon'
|
||||
engine: 'neural'
|
||||
voices: ['ko']
|
||||
|
||||
sources:
|
||||
enabled: true
|
||||
|
@ -120,11 +120,7 @@ pronouns:
|
||||
|
||||
pronunciation:
|
||||
enabled: true
|
||||
voices:
|
||||
NO:
|
||||
language: 'nb-NO'
|
||||
voice: 'Liv'
|
||||
engine: 'standard'
|
||||
voices: ['no']
|
||||
|
||||
sources:
|
||||
enabled: true
|
||||
|
@ -71,11 +71,7 @@ pronouns:
|
||||
|
||||
pronunciation:
|
||||
enabled: true
|
||||
voices:
|
||||
GB:
|
||||
language: 'nl-NL'
|
||||
voice: 'Ruben'
|
||||
engine: 'standard'
|
||||
voices: ['nl']
|
||||
|
||||
sources:
|
||||
enabled: true
|
||||
|
@ -121,11 +121,7 @@ pronouns:
|
||||
|
||||
pronunciation:
|
||||
enabled: true
|
||||
voices:
|
||||
NO:
|
||||
language: 'nb-NO'
|
||||
voice: 'Liv'
|
||||
engine: 'standard'
|
||||
voices: ['no']
|
||||
|
||||
sources:
|
||||
enabled: true
|
||||
|
@ -322,11 +322,7 @@ pronouns:
|
||||
|
||||
pronunciation:
|
||||
enabled: true
|
||||
voices:
|
||||
PL:
|
||||
language: 'pl-PL'
|
||||
voice: 'Ewa'
|
||||
engine: 'standard'
|
||||
voices: ['pl']
|
||||
|
||||
sources:
|
||||
enabled: true
|
||||
|
@ -81,15 +81,7 @@ pronouns:
|
||||
|
||||
pronunciation:
|
||||
enabled: true
|
||||
voices:
|
||||
PT:
|
||||
language: 'pt-PT'
|
||||
voice: 'Cristiano'
|
||||
engine: 'standard'
|
||||
BR:
|
||||
language: 'pt-BR'
|
||||
voice: 'Vitoria'
|
||||
engine: 'standard'
|
||||
voices: ['pt', 'br']
|
||||
|
||||
sources:
|
||||
enabled: true
|
||||
|
@ -113,11 +113,7 @@ pronouns:
|
||||
|
||||
pronunciation:
|
||||
enabled: true
|
||||
voices:
|
||||
RO:
|
||||
language: 'ro-RO'
|
||||
voice: 'Carmen'
|
||||
engine: 'standard'
|
||||
voices: ['ro']
|
||||
|
||||
sources:
|
||||
enabled: true
|
||||
|
@ -162,11 +162,7 @@ pronouns:
|
||||
|
||||
pronunciation:
|
||||
enabled: true
|
||||
voices:
|
||||
GB:
|
||||
language: 'ru-RU'
|
||||
voice: 'Tatyana'
|
||||
engine: 'standard'
|
||||
voices: ['ru']
|
||||
|
||||
sources:
|
||||
enabled: true
|
||||
|
@ -50,11 +50,7 @@ pronouns:
|
||||
|
||||
pronunciation:
|
||||
enabled: true
|
||||
voices:
|
||||
SE:
|
||||
language: 'sv-SE'
|
||||
voice: 'Astrid'
|
||||
engine: 'standard'
|
||||
voices: ['se']
|
||||
|
||||
sources:
|
||||
enabled: true
|
||||
|
@ -29,11 +29,7 @@ pronouns:
|
||||
pronunciation:
|
||||
enabled: false
|
||||
ipa: true
|
||||
voices:
|
||||
TOK:
|
||||
language: 'es-US'
|
||||
voice: 'Lupe'
|
||||
engine: 'standard'
|
||||
voices: ['tok']
|
||||
|
||||
sources:
|
||||
enabled: false
|
||||
|
@ -11,11 +11,7 @@ pronouns:
|
||||
|
||||
pronunciation:
|
||||
enabled: true
|
||||
voices:
|
||||
TR:
|
||||
language: 'tr-TR'
|
||||
voice: 'Filiz'
|
||||
engine: 'standard'
|
||||
voices: ['tr']
|
||||
|
||||
sources:
|
||||
enabled: false
|
||||
|
@ -83,7 +83,6 @@ pronouns:
|
||||
|
||||
pronunciation:
|
||||
enabled: false
|
||||
voices: {}
|
||||
|
||||
sources:
|
||||
enabled: true
|
||||
|
@ -35,7 +35,6 @@ pronouns:
|
||||
|
||||
pronunciation:
|
||||
enabled: false
|
||||
voices: {}
|
||||
|
||||
sources:
|
||||
enabled: true
|
||||
|
@ -35,11 +35,7 @@ pronouns:
|
||||
|
||||
pronunciation:
|
||||
enabled: true
|
||||
voices:
|
||||
CN:
|
||||
language: 'cmn-CN'
|
||||
voice: 'Zhiyu'
|
||||
engine: 'standard'
|
||||
voices: ['cn']
|
||||
|
||||
sources:
|
||||
enabled: true
|
||||
|
@ -14,11 +14,8 @@ import {
|
||||
convertPronunciationStringToNarakeetFormat,
|
||||
handleErrorAsync,
|
||||
} from '#shared/helpers.ts';
|
||||
import type {
|
||||
PronunciationVoiceConfig,
|
||||
AwsPollyPronunciationVoiceConfig,
|
||||
NarakeetPronunciationVoiceConfig,
|
||||
} from '~~/locale/config.ts';
|
||||
import { voices } from '#shared/pronunciation/voices.ts';
|
||||
import type { VoiceKey, AwsPollyVoice, NarakeetVoice, Voice } from '#shared/pronunciation/voices.ts';
|
||||
import { getLocale, loadConfig, localesDict } from '~~/server/data.ts';
|
||||
|
||||
const router = Router();
|
||||
@ -26,7 +23,7 @@ const router = Router();
|
||||
type ProviderKey = 'aws_polly' | 'narakeet';
|
||||
interface Provider {
|
||||
tokenised(text: string): string;
|
||||
generate(textTokenised: string, voice: PronunciationVoiceConfig): Promise<[Uint8Array, string]>;
|
||||
generate(textTokenised: string, voice: Voice): Promise<[Uint8Array, string]>;
|
||||
}
|
||||
|
||||
const providers: Record<ProviderKey, Provider> = {
|
||||
@ -34,7 +31,7 @@ const providers: Record<ProviderKey, Provider> = {
|
||||
tokenised(text: string): string {
|
||||
return convertPronunciationStringToSsml(text);
|
||||
},
|
||||
async generate(textTokenised: string, voice: AwsPollyPronunciationVoiceConfig): Promise<[Uint8Array, string]> {
|
||||
async generate(textTokenised: string, voice: AwsPollyVoice): Promise<[Uint8Array, string]> {
|
||||
const polly = new Polly(awsConfig) as NodeJsClient<Polly>;
|
||||
|
||||
const pollyResponse = await polly.synthesizeSpeech({
|
||||
@ -56,7 +53,7 @@ const providers: Record<ProviderKey, Provider> = {
|
||||
tokenised(text: string): string {
|
||||
return convertPronunciationStringToNarakeetFormat(text);
|
||||
},
|
||||
async generate(textTokenised: string, voice: NarakeetPronunciationVoiceConfig): Promise<[Uint8Array, string]> {
|
||||
async generate(textTokenised: string, voice: NarakeetVoice): Promise<[Uint8Array, string]> {
|
||||
const url = `https://api.narakeet.com/text-to-speech/mp3?voice=${voice.voice}&language=${voice.language}`;
|
||||
|
||||
const response = await fetch(url, {
|
||||
@ -91,11 +88,11 @@ router.get('/pronounce/:voice/:pronunciation', handleErrorAsync(async (req, res)
|
||||
const locale = getLocale(getH3Event(req));
|
||||
const config = await loadConfig(locale);
|
||||
|
||||
const voice: PronunciationVoiceConfig | undefined = config.pronunciation?.voices?.[req.params.voice];
|
||||
if (!voice) {
|
||||
if (!(req.params.voice in voices)) {
|
||||
return res.status(404).json({ error: 'Not found' });
|
||||
}
|
||||
|
||||
const voice = voices[req.params.voice as VoiceKey];
|
||||
const provider = providers[(voice.provider || 'aws_polly') as ProviderKey];
|
||||
const tokenised = provider.tokenised(text);
|
||||
const key = `pronunciation/${config.locale}-${req.params.voice}/${sha1(tokenised)}.mp3`;
|
||||
|
177
shared/pronunciation/voices.ts
Normal file
177
shared/pronunciation/voices.ts
Normal file
@ -0,0 +1,177 @@
|
||||
import type { Engine, LanguageCode, VoiceId } from '@aws-sdk/client-polly';
|
||||
|
||||
export type Voice = AwsPollyVoice | NarakeetVoice;
|
||||
|
||||
/**
|
||||
* @see https://docs.aws.amazon.com/polly/latest/dg/voicelist.html
|
||||
*/
|
||||
export interface AwsPollyVoice {
|
||||
/**
|
||||
* text-to-speech provider (aws_polly is the default, if not specified)
|
||||
*/
|
||||
provider?: 'aws_polly';
|
||||
/**
|
||||
* language code
|
||||
*/
|
||||
language: LanguageCode;
|
||||
/**
|
||||
* voice name
|
||||
*/
|
||||
voice: VoiceId;
|
||||
/**
|
||||
* voice engine (default: 'standard')
|
||||
*/
|
||||
engine?: Engine;
|
||||
}
|
||||
|
||||
export interface NarakeetVoice {
|
||||
/**
|
||||
* text-to-speech provider
|
||||
*/
|
||||
provider: 'narakeet';
|
||||
/**
|
||||
* language code
|
||||
*/
|
||||
language: string;
|
||||
/**
|
||||
* voice name
|
||||
*/
|
||||
voice: string;
|
||||
}
|
||||
|
||||
const defineVoices = <T extends Record<string, Voice>>(voices: T) => voices as Readonly<Record<keyof T, Voice>>;
|
||||
|
||||
export const voices = defineVoices({
|
||||
ar: {
|
||||
language: 'arb',
|
||||
voice: 'Zeina',
|
||||
engine: 'standard',
|
||||
},
|
||||
ae: {
|
||||
language: 'ar-AE',
|
||||
voice: 'Hala',
|
||||
engine: 'neural',
|
||||
},
|
||||
de: {
|
||||
language: 'de-DE',
|
||||
voice: 'Vicki',
|
||||
engine: 'standard',
|
||||
},
|
||||
gb: {
|
||||
language: 'en-GB',
|
||||
voice: 'Emma',
|
||||
engine: 'neural',
|
||||
},
|
||||
es: {
|
||||
language: 'es-ES',
|
||||
voice: 'Lucia',
|
||||
engine: 'standard',
|
||||
},
|
||||
mx: {
|
||||
language: 'es-MX',
|
||||
voice: 'Mia',
|
||||
engine: 'standard',
|
||||
},
|
||||
fi: {
|
||||
language: 'fi-FI',
|
||||
voice: 'Suvi',
|
||||
engine: 'neural',
|
||||
},
|
||||
fr: {
|
||||
language: 'fr-FR',
|
||||
voice: 'Lea',
|
||||
engine: 'standard',
|
||||
},
|
||||
ca: {
|
||||
language: 'fr-CA',
|
||||
voice: 'Gabrielle',
|
||||
engine: 'neural',
|
||||
},
|
||||
bos: {
|
||||
language: 'bos',
|
||||
voice: 'suada',
|
||||
provider: 'narakeet',
|
||||
},
|
||||
hrv: {
|
||||
language: 'hrv',
|
||||
voice: 'jasna',
|
||||
provider: 'narakeet',
|
||||
},
|
||||
srp: {
|
||||
language: 'srp',
|
||||
voice: 'milica-latin',
|
||||
provider: 'narakeet',
|
||||
},
|
||||
it: {
|
||||
language: 'it-IT',
|
||||
voice: 'Bianca',
|
||||
engine: 'neural',
|
||||
},
|
||||
ja: {
|
||||
language: 'ja-JP',
|
||||
voice: 'Mizuki',
|
||||
engine: 'standard',
|
||||
},
|
||||
ko: {
|
||||
language: 'ko-KR',
|
||||
voice: 'Seoyeon',
|
||||
engine: 'neural',
|
||||
},
|
||||
nb: {
|
||||
language: 'nb-NO',
|
||||
voice: 'Liv',
|
||||
engine: 'standard',
|
||||
},
|
||||
nl: {
|
||||
language: 'nl-NL',
|
||||
voice: 'Ruben',
|
||||
engine: 'standard',
|
||||
},
|
||||
pl: {
|
||||
language: 'pl-PL',
|
||||
voice: 'Ewa',
|
||||
engine: 'standard',
|
||||
},
|
||||
pt: {
|
||||
language: 'pt-PT',
|
||||
voice: 'Cristiano',
|
||||
engine: 'standard',
|
||||
},
|
||||
br: {
|
||||
language: 'pt-BR',
|
||||
voice: 'Vitoria',
|
||||
engine: 'standard',
|
||||
},
|
||||
ro: {
|
||||
language: 'ro-RO',
|
||||
voice: 'Carmen',
|
||||
engine: 'standard',
|
||||
},
|
||||
ru: {
|
||||
language: 'ru-RU',
|
||||
voice: 'Tatyana',
|
||||
engine: 'standard',
|
||||
},
|
||||
se: {
|
||||
language: 'sv-SE',
|
||||
voice: 'Astrid',
|
||||
engine: 'standard',
|
||||
},
|
||||
tok: {
|
||||
language: 'es-US',
|
||||
voice: 'Lupe',
|
||||
engine: 'standard',
|
||||
},
|
||||
tr: {
|
||||
language: 'tr-TR',
|
||||
voice: 'Filiz',
|
||||
engine: 'standard',
|
||||
},
|
||||
cn: {
|
||||
language: 'cmn-CN',
|
||||
voice: 'Zhiyu',
|
||||
engine: 'standard',
|
||||
},
|
||||
});
|
||||
|
||||
export type VoiceKey = keyof typeof voices;
|
Loading…
x
Reference in New Issue
Block a user