diff --git a/packages/kbot/cat_out.png b/packages/kbot/cat_out.png deleted file mode 100644 index 90e1b90c..00000000 Binary files a/packages/kbot/cat_out.png and /dev/null differ diff --git a/packages/kbot/dist-in/commands/tts.d.ts b/packages/kbot/dist-in/commands/tts.d.ts new file mode 100644 index 00000000..8c5a846c --- /dev/null +++ b/packages/kbot/dist-in/commands/tts.d.ts @@ -0,0 +1,2 @@ +export declare const TTSOptionsSchema: () => any; +export declare const ttsCommand: (argv: any) => Promise; diff --git a/packages/kbot/dist-in/commands/tts.js b/packages/kbot/dist-in/commands/tts.js new file mode 100644 index 00000000..6ff73300 --- /dev/null +++ b/packages/kbot/dist-in/commands/tts.js @@ -0,0 +1,206 @@ +import { z } from 'zod'; +import * as path from 'node:path'; +import { sync as write } from '@polymech/fs/write'; +import { sync as exists } from '@polymech/fs/exists'; +import { sync as read } from '@polymech/fs/read'; +import { isString } from '@polymech/core/primitives'; +import { OptionsSchema } from '../zod_schema.js'; +import { generateSpeech } from '../lib/tts-elevenlabs.js'; +import { getLogger } from '../index.js'; +import { prompt as resolvePrompt } from '../prompt.js'; +import { variables } from '../variables.js'; +import { resolve } from '@polymech/commons'; +// Cache for voices data +let voicesCache = null; +const getVoicesData = async () => { + if (!voicesCache) { + try { + // Try multiple possible paths for voices.json + const possiblePaths = [ + path.resolve('src/lib/voices.json'), + path.resolve('lib/voices.json'), + path.resolve(path.dirname(new URL(import.meta.url).pathname), '..', 'lib', 'voices.json'), + path.resolve(path.dirname(new URL(import.meta.url).pathname), 'lib', 'voices.json'), + ]; + let voicesContent = ''; + for (const voicesPath of possiblePaths) { + const cleanPath = process.platform === 'win32' && voicesPath.startsWith('/') + ? voicesPath.substring(1) + : voicesPath; + if (exists(cleanPath)) { + voicesContent = read(cleanPath, 'string'); + break; + } + } + if (voicesContent) { + voicesCache = JSON.parse(voicesContent); + } + else { + // Fallback to empty voices list if file doesn't exist + voicesCache = { voices: [] }; + } + } + catch (error) { + // Fallback to empty voices list if file doesn't exist + voicesCache = { voices: [] }; + } + } + return voicesCache; +}; +// Extract voice names and IDs for help text +const getVoicesList = async () => { + const voicesData = await getVoicesData(); + return voicesData.voices.map((voice) => `${voice.name} (${voice.voice_id})`).join(', '); +}; +const getVoiceNames = async () => { + const voicesData = await getVoicesData(); + return voicesData.voices.map((voice) => voice.name); +}; +const findVoiceIdByName = async (name) => { + const voicesData = await getVoicesData(); + const voice = voicesData.voices.find((v) => v.name.toLowerCase() === name.toLowerCase()); + return voice?.voice_id; +}; +export const TTSOptionsSchema = () => { + const baseSchema = OptionsSchema().pick({ + prompt: true, + include: true, + dst: true, + logLevel: true, + config: true, + api_key: true, + alt: true, + }); + // Create a synchronous voices list for help text + let voicesHelpText = 'Voice ID or name to use for speech generation. Common voices: Rachel, Clyde, Sarah, Laura, Thomas, Charlie, George (default), Callum, River, Harry, Liam, Alice, Matilda, Will, Jessica, Eric, Chris, Brian, Daniel, Lily, Bill'; + // Try to load voices synchronously for help text + try { + const possiblePaths = [ + path.resolve('src/lib/voices.json'), + path.resolve('lib/voices.json'), + ]; + for (const voicesPath of possiblePaths) { + if (exists(voicesPath)) { + const voicesContent = read(voicesPath, 'string'); + const voicesData = JSON.parse(voicesContent); + const voicesList = voicesData.voices.slice(0, 10).map((voice) => voice.name).join(', '); + voicesHelpText = `Voice ID or name to use for speech generation. Available voices: ${voicesList} (and ${voicesData.voices.length - 10} more)`; + break; + } + } + } + catch (error) { + // Use fallback help text if loading fails + } + return baseSchema.extend({ + dst: z.string().describe('Destination path for the output audio file. Required.'), + prompt: z.string().optional().describe('The text to convert to speech.'), + voiceId: z.string().default('JBFqnCBsd6RMkjVDRZzb').describe(voicesHelpText), + outputFormat: z.enum(['mp3_22050_32', 'mp3_44100_32', 'mp3_44100_64', 'mp3_44100_96', 'mp3_44100_128', 'mp3_44100_192', 'pcm_16000', 'pcm_22050', 'pcm_24000', 'pcm_44100', 'ulaw_8000']).default('mp3_44100_128').describe('Output format of the generated audio.'), + modelId: z.string().default('eleven_multilingual_v2').describe('Model ID to use for speech generation.'), + languageCode: z.string().optional().describe('Language code (ISO 639-1) to enforce for the model.'), + stability: z.number().min(0).max(1).optional().describe('Voice stability (0-1).'), + similarityBoost: z.number().min(0).max(1).optional().describe('Voice similarity boost (0-1).'), + style: z.number().min(0).max(1).optional().describe('Voice style (0-1).'), + useSpeakerBoost: z.boolean().optional().describe('Use speaker boost for voice enhancement.'), + seed: z.number().optional().describe('Seed for deterministic generation (0-4294967295).'), + previousText: z.string().optional().describe('Text that came before the current text for continuity.'), + nextText: z.string().optional().describe('Text that comes after the current text for continuity.'), + applyTextNormalization: z.enum(['auto', 'on', 'off']).default('auto').describe('Text normalization mode.'), + applyLanguageTextNormalization: z.boolean().default(false).describe('Apply language-specific text normalization.'), + usePvcAsIvc: z.boolean().default(false).describe('Use PVC as IVC (deprecated).'), + }); +}; +export const ttsCommand = async (argv) => { + const logger = getLogger(argv); + if (argv.include && isString(argv.include)) { + argv.include = [argv.include]; + } + try { + const parsedOptions = TTSOptionsSchema().parse(argv); + const { include, dst, ...rest } = parsedOptions; + let textContent = ''; + // Handle voice name to ID conversion + let voiceId = parsedOptions.voiceId; + if (voiceId && !voiceId.match(/^[a-zA-Z0-9]{20}$/)) { + // If voiceId doesn't look like an ID (20 alphanumeric chars), treat it as a name + const foundVoiceId = await findVoiceIdByName(voiceId); + if (foundVoiceId) { + voiceId = foundVoiceId; + logger.info(`Using voice "${parsedOptions.voiceId}" (${voiceId})`); + } + else { + const availableVoices = await getVoiceNames(); + logger.warn(`Voice name "${voiceId}" not found. Available voices: ${availableVoices.join(', ')}`); + logger.info(`Using default voice ID: ${parsedOptions.voiceId}`); + } + } + // Get text from --prompt or --include file + if (parsedOptions.prompt) { + const promptMessage = await resolvePrompt(parsedOptions); + textContent = promptMessage?.content || ''; + } + else if (include && include.length > 0) { + // Read text from file(s) + const filePath = include[0]; // Use first file + if (!exists(filePath)) { + logger.error(`Input file not found at: ${filePath}`); + return; + } + textContent = read(filePath, 'string'); + logger.info(`Reading text from file: ${filePath}`); + } + if (!textContent.trim()) { + logger.error('No text provided. Use --prompt "text" or --include path/to/textfile.txt'); + return; + } + if (!dst) { + logger.error('--dst is required to specify the output audio file path.'); + return; + } + // Prepare voice settings if any are specified + let voiceSettings = null; + if (parsedOptions.stability !== undefined || + parsedOptions.similarityBoost !== undefined || + parsedOptions.style !== undefined || + parsedOptions.useSpeakerBoost !== undefined) { + voiceSettings = { + stability: parsedOptions.stability, + similarityBoost: parsedOptions.similarityBoost, + style: parsedOptions.style, + useSpeakerBoost: parsedOptions.useSpeakerBoost, + }; + } + logger.info(`Converting text to speech: "${textContent.substring(0, 100)}${textContent.length > 100 ? '...' : ''}"`); + const audioBuffer = await generateSpeech({ + text: textContent, + voiceId: voiceId, + outputFormat: parsedOptions.outputFormat, + modelId: parsedOptions.modelId, + languageCode: parsedOptions.languageCode, + voiceSettings, + seed: parsedOptions.seed, + previousText: parsedOptions.previousText, + nextText: parsedOptions.nextText, + applyTextNormalization: parsedOptions.applyTextNormalization, + applyLanguageTextNormalization: parsedOptions.applyLanguageTextNormalization, + usePvcAsIvc: parsedOptions.usePvcAsIvc, + config: parsedOptions.config, + api_key: parsedOptions.api_key, + logger, + }); + if (audioBuffer) { + const vars = variables(parsedOptions); + const dstPath = path.resolve(resolve(dst, parsedOptions.alt, vars)); + write(dstPath, audioBuffer); + logger.info(`Audio saved to: ${dstPath}`); + } + else { + logger.error('Failed to generate audio.'); + } + } + catch (error) { + logger.error('Failed to parse options or generate speech:', error.message, error.issues, error.stack); + } +}; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbW1hbmRzL3R0cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsQ0FBQyxFQUFFLE1BQU0sS0FBSyxDQUFDO0FBQ3hCLE9BQU8sS0FBSyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBQ2xDLE9BQU8sRUFBRSxJQUFJLElBQUksS0FBSyxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDbkQsT0FBTyxFQUFFLElBQUksSUFBSSxNQUFNLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNyRCxPQUFPLEVBQUUsSUFBSSxJQUFJLElBQUksRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBRWpELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUVyRCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDakQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzFELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDeEMsT0FBTyxFQUFFLE1BQU0sSUFBSSxhQUFhLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDdkQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzVDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUM1Qyx3QkFBd0I7QUFDeEIsSUFBSSxXQUFXLEdBQVEsSUFBSSxDQUFDO0FBRTVCLE1BQU0sYUFBYSxHQUFHLEtBQUssSUFBSSxFQUFFO0lBQzdCLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUNmLElBQUksQ0FBQztZQUNELDhDQUE4QztZQUM5QyxNQUFNLGFBQWEsR0FBRztnQkFDbEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxxQkFBcUIsQ0FBQztnQkFDbkMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQztnQkFDL0IsSUFBSSxD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 \ No newline at end of file diff --git a/packages/kbot/dist-in/lib/tts-elevenlabs.d.ts b/packages/kbot/dist-in/lib/tts-elevenlabs.d.ts new file mode 100644 index 00000000..632e624a --- /dev/null +++ b/packages/kbot/dist-in/lib/tts-elevenlabs.d.ts @@ -0,0 +1,31 @@ +type OutputFormat = "mp3_22050_32" | "mp3_44100_32" | "mp3_44100_64" | "mp3_44100_96" | "mp3_44100_128" | "mp3_44100_192" | "pcm_16000" | "pcm_22050" | "pcm_24000" | "pcm_44100" | "ulaw_8000"; +export interface TTSOptions { + text: string; + voiceId?: string; + outputFormat?: OutputFormat; + modelId?: string; + languageCode?: string | null; + voiceSettings?: { + stability?: number; + similarityBoost?: number; + style?: number; + useSpeakerBoost?: boolean; + } | null; + pronunciationDictionaryLocators?: Array<{ + pronunciationDictionaryId: string; + versionId: string; + }> | null; + seed?: number | null; + previousText?: string | null; + nextText?: string | null; + previousRequestIds?: string[] | null; + nextRequestIds?: string[] | null; + applyTextNormalization?: 'auto' | 'on' | 'off'; + applyLanguageTextNormalization?: boolean; + usePvcAsIvc?: boolean; + config?: any; + api_key?: string; + logger?: any; +} +export declare const generateSpeech: (options: TTSOptions) => Promise; +export {}; diff --git a/packages/kbot/dist-in/lib/tts-elevenlabs.js b/packages/kbot/dist-in/lib/tts-elevenlabs.js new file mode 100644 index 00000000..8762704c --- /dev/null +++ b/packages/kbot/dist-in/lib/tts-elevenlabs.js @@ -0,0 +1,71 @@ +import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js"; +import { getLogger } from '../index.js'; +import { loadConfig } from '../config.js'; +export const generateSpeech = async (options) => { + const logger = options.logger || getLogger({ logLevel: 4 }); + // Get API key from options or config + const config = loadConfig(options); + const apiKey = options.api_key || config?.elevenlabs?.key; + if (!apiKey) { + throw new Error('ElevenLabs API key not found. Please provide it via --api_key or in your config file under elevenlabs.key'); + } + const client = new ElevenLabsClient({ + apiKey: apiKey + }); + try { + logger.info(`Generating speech with ElevenLabs...`); + logger.debug(`Voice ID: ${options.voiceId || 'JBFqnCBsd6RMkjVDRZzb'}`); + logger.debug(`Model: ${options.modelId || 'eleven_multilingual_v2'}`); + logger.debug(`Output Format: ${options.outputFormat || 'mp3_44100_128'}`); + logger.debug(`Text length: ${options.text.length} characters`); + const audioStream = await client.textToSpeech.convert(options.voiceId || "JBFqnCBsd6RMkjVDRZzb", { + outputFormat: options.outputFormat || "mp3_44100_128", + text: options.text, + modelId: options.modelId || "eleven_multilingual_v2", + languageCode: options.languageCode, + voiceSettings: options.voiceSettings, + pronunciationDictionaryLocators: options.pronunciationDictionaryLocators, + seed: options.seed, + previousText: options.previousText, + nextText: options.nextText, + previousRequestIds: options.previousRequestIds, + nextRequestIds: options.nextRequestIds, + applyTextNormalization: options.applyTextNormalization || 'auto', + applyLanguageTextNormalization: options.applyLanguageTextNormalization || false, + usePvcAsIvc: options.usePvcAsIvc || false, + }); + // The convert endpoint returns a ReadableStream, we need to collect all chunks + const chunks = []; + const reader = audioStream.getReader(); + try { + while (true) { + const { done, value } = await reader.read(); + if (done) + break; + chunks.push(value); + } + } + finally { + reader.releaseLock(); + } + // Combine all chunks into a single buffer + const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0); + const audioBuffer = new Uint8Array(totalLength); + let offset = 0; + for (const chunk of chunks) { + audioBuffer.set(chunk, offset); + offset += chunk.length; + } + const finalBuffer = Buffer.from(audioBuffer); + logger.info(`Successfully generated ${finalBuffer.length} bytes of audio`); + return finalBuffer; + } + catch (error) { + logger.error('Failed to generate speech with ElevenLabs:', error.message); + if (error.response?.data) { + logger.error('API Error Details:', error.response.data); + } + throw error; + } +}; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHRzLWVsZXZlbmxhYnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbGliL3R0cy1lbGV2ZW5sYWJzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQzdELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDeEMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQW9DMUMsTUFBTSxDQUFDLE1BQU0sY0FBYyxHQUFHLEtBQUssRUFBRSxPQUFtQixFQUFtQixFQUFFO0lBQ3pFLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLElBQUksU0FBUyxDQUFDLEVBQUUsUUFBUSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFFNUQscUNBQXFDO0lBQ3JDLE1BQU0sTUFBTSxHQUFHLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNuQyxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsT0FBTyxJQUFJLE1BQU0sRUFBRSxVQUFVLEVBQUUsR0FBRyxDQUFDO0lBRTFELElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNWLE1BQU0sSUFBSSxLQUFLLENBQUMsMkdBQTJHLENBQUMsQ0FBQztJQUNqSSxDQUFDO0lBRUQsTUFBTSxNQUFNLEdBQUcsSUFBSSxnQkFBZ0IsQ0FBQztRQUNoQyxNQUFNLEVBQUUsTUFBTTtLQUNqQixDQUFDLENBQUM7SUFFSCxJQUFJLENBQUM7UUFDRCxNQUFNLENBQUMsSUFBSSxDQUFDLHNDQUFzQyxDQUFDLENBQUM7UUFDcEQsTUFBTSxDQUFDLEtBQUssQ0FBQyxhQUFhLE9BQU8sQ0FBQyxPQUFPLElBQUksc0JBQXNCLEVBQUUsQ0FBQyxDQUFDO1FBQ3ZFLE1BQU0sQ0FBQyxLQUFLLENBQUMsVUFBVSxPQUFPLENBQUMsT0FBTyxJQUFJLHdCQUF3QixFQUFFLENBQUMsQ0FBQztRQUN0RSxNQUFNLENBQUMsS0FBSyxDQUFDLGtCQUFrQixPQUFPLENBQUMsWUFBWSxJQUFJLGVBQWUsRUFBRSxDQUFDLENBQUM7UUFDMUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxnQkFBZ0IsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLGFBQWEsQ0FBQyxDQUFDO1FBRS9ELE1BQU0sV0FBVyxHQUFHLE1BQU0sTUFBTSxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQ2pELE9BQU8sQ0FBQyxPQUFPLElBQUksc0JBQXNCLEVBQ3pDO1lBQ0ksWUFBWSxFQUFFLE9BQU8sQ0FBQyxZQUFZLElBQUksZUFBZTtZQUNyRCxJQUFJLEVBQUUsT0FBTyxDQUFDLElBQUk7WUFDbEIsT0FBTyxFQUFFLE9BQU8sQ0FBQyxPQUFPLElBQUksd0JBQXdCO1lBQ3BELFlBQVksRUFBRSxPQUFPLENBQUMsWUFBWTtZQUNsQyxhQUFhLEVBQUUsT0FBTyxDQUFDLGFBQWE7WUFDcEMsK0JBQStCLEVBQUUsT0FBTyxDQUFDLCtCQUErQjtZQUN4RSxJQUFJLEVBQUUsT0FBTyxDQUFDLElBQUk7WUFDbEIsWUFBWSxFQUFFLE9BQU8sQ0FBQyxZQUFZO1lBQ2xDLFFBQVEsRUFBRSxPQUFPLENBQUMsUUFBUTtZQUMxQixrQkFBa0IsRUFBRSxPQUFPLENBQUMsa0JBQWtCO1lBQzlDLGNBQWMsRUFBRSxPQUFPLENBQUMsY0FBYztZQUN0QyxzQkFBc0IsRUFBRSxPQUFPLENBQUMsc0JBQXNCLElBQUksTUFBTTtZQUNoRSw4QkFBOEIsRUFBRSxPQUFPLENBQUMsOEJBQThCLElBQUksS0FBSztZQUMvRSxXQUFXLEVBQUUsT0FBTyxDQUFDLFdBQVcsSUFBSSxLQUFLO1NBQzVDLENBQ0osQ0FBQztRQUVGLCtFQUErRTtRQUMvRSxNQUFNLE1BQU0sR0FBaUIsRUFBRSxDQUFDO1FBQ2hDLE1BQU0sTUFBTSxHQUFHLFdBQVcsQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUV2QyxJQUFJLENBQUM7WUFDRCxPQUFPLElBQUksRUFBRSxDQUFDO2dCQUNWLE1BQU0sRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEdBQUcsTUFBTSxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQzVDLElBQUksSUFBSTtvQkFBRSxNQUFNO2dCQUNoQixNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3ZCLENBQUM7UUFDTCxDQUFDO2dCQUFTLENBQUM7WUFDUCxNQUFNLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDekIsQ0FBQztRQUVELDBDQUEwQztRQUMxQyxNQUFNLFdBQVcsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsR0FBRyxHQUFHLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDekUsTUFBTSxXQUFXLEdBQUcsSUFBSSxVQUFVLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDaEQsSUFBSSxNQUFNLEdBQUcsQ0FBQyxDQUFDO1FBQ2YsS0FBSyxNQUFNLEtBQUssSUFBSSxNQUFNLEVBQUUsQ0FBQztZQUN6QixXQUFXLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQztZQUMvQixNQUFNLElBQUksS0FBSyxDQUFDLE1BQU0sQ0FBQztRQUMzQixDQUFDO1FBRUQsTUFBTSxXQUFXLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUM3QyxNQUFNLENBQUMsSUFBSSxDQUFDLDBCQUEwQixXQUFXLENBQUMsTUFBTSxpQkFBaUIsQ0FBQyxDQUFDO1FBRTNFLE9BQU8sV0FBVyxDQUFDO0lBRXZCLENBQUM7SUFBQyxPQUFPLEtBQVUsRUFBRSxDQUFDO1FBQ2xCLE1BQU0sQ0FBQyxLQUFLLENBQUMsNENBQTRDLEVBQUUsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzFFLElBQUksS0FBSyxDQUFDLFFBQVEsRUFBRSxJQUFJLEVBQUUsQ0FBQztZQUN2QixNQUFNLENBQUMsS0FBSyxDQUFDLG9CQUFvQixFQUFFLEtBQUssQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDNUQsQ0FBQztRQUNELE1BQU0sS0FBSyxDQUFDO0lBQ2hCLENBQUM7QUFDTCxDQUFDLENBQUMifQ== \ No newline at end of file diff --git a/packages/kbot/dist-in/main.js b/packages/kbot/dist-in/main.js index f38a9e26..b6c4b1dd 100644 --- a/packages/kbot/dist-in/main.js +++ b/packages/kbot/dist-in/main.js @@ -12,6 +12,7 @@ import { fetch } from './commands/fetch.js'; import { run } from './commands/run.js'; import { transcribeCommand, TranscribeOptionsSchema } from './commands/transcribe.js'; import { imageCommand, ImageOptionsSchema } from './commands/images.js'; +import { ttsCommand, TTSOptionsSchema } from './commands/tts.js'; export const logger = createLogger('llm-tools'); const modify = async (argv) => await run(argv); const yargOptions = { @@ -33,6 +34,7 @@ yargs(hideBin(process.argv)) .command('modify [prompt]', 'Modify an existing project', (yargs) => toYargs(yargs, OptionsSchema(), yargOptions), modify) .command('image [prompt]', 'Create or edit an image', (yargs) => toYargs(yargs, ImageOptionsSchema(), yargOptions), imageCommand) .command('transcribe', 'Transcribe audio files', (yargs) => toYargs(yargs, TranscribeOptionsSchema(), yargOptions), transcribeCommand) + .command('tts', 'Convert text to speech using ElevenLabs', (yargs) => toYargs(yargs, TTSOptionsSchema(), yargOptions), ttsCommand) .command('types', 'Generate types', (yargs) => { }, (argv) => types()) .command('schemas', 'Generate schemas', (yargs) => { }, (argv) => schemas()) .command('build', 'Build kbot essentials', (yargs) => { }, (argv) => build()) @@ -43,4 +45,4 @@ yargs(hideBin(process.argv)) .help() //.wrap(yargs.terminalWidth() - 20) .parse(); -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9tYWluLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFDQSxPQUFPLEtBQUssTUFBTSxPQUFPLENBQUE7QUFDekIsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLGVBQWUsQ0FBQTtBQUN2QyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sbUJBQW1CLENBQUE7QUFDM0MsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGVBQWUsQ0FBQTtBQUU1QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQTtBQUcvRCxPQUFPLFdBQVcsTUFBTSxvQkFBb0IsQ0FBQTtBQUM1QyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sd0JBQXdCLENBQUE7QUFDakQsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLG9CQUFvQixDQUFBO0FBQ3pDLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQTtBQUMzQyxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0scUJBQXFCLENBQUE7QUFDM0MsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLG1CQUFtQixDQUFBO0FBRXZDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSx1QkFBdUIsRUFBRSxNQUFNLDBCQUEwQixDQUFBO0FBQ3JGLE9BQU8sRUFBRSxZQUFZLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQTtBQUV2RSxNQUFNLENBQUMsTUFBTSxNQUFNLEdBQVEsWUFBWSxDQUFDLFdBQVcsQ0FBQyxDQUFBO0FBRXBELE1BQU0sTUFBTSxHQUFHLEtBQUssRUFBRSxJQUFlLEVBQUUsRUFBRSxDQUFFLE1BQU0sR0FBRyxDQUFDLElBQWlCLENBQUMsQ0FBQTtBQUV2RSxNQUFNLFdBQVcsR0FBUTtJQUN2QixLQUFLLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxHQUFHLEVBQUUsT0FBTyxFQUFFLEVBQUU7UUFD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 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9tYWluLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFDQSxPQUFPLEtBQUssTUFBTSxPQUFPLENBQUE7QUFDekIsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLGVBQWUsQ0FBQTtBQUN2QyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sbUJBQW1CLENBQUE7QUFDM0MsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGVBQWUsQ0FBQTtBQUU1QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQTtBQUcvRCxPQUFPLFdBQVcsTUFBTSxvQkFBb0IsQ0FBQTtBQUM1QyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sd0JBQXdCLENBQUE7QUFDakQsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLG9CQUFvQixDQUFBO0FBQ3pDLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQTtBQUMzQyxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0scUJBQXFCLENBQUE7QUFDM0MsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLG1CQUFtQixDQUFBO0FBRXZDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSx1QkFBdUIsRUFBRSxNQUFNLDBCQUEwQixDQUFBO0FBQ3JGLE9BQU8sRUFBRSxZQUFZLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQTtBQUN2RSxPQUFPLEVBQUUsVUFBVSxFQUFFLGdCQUFnQixFQUFFLE1BQU0sbUJBQW1CLENBQUE7QUFFaEUsTUFBTSxDQUFDLE1BQU0sTUFBTSxHQUFRLFlBQVksQ0FBQyxXQUFXLENBQUMsQ0FBQTtBQUVwRCxNQUFNLE1BQU0sR0FBRyxLQUFLLEVBQUUsSUFBZSxFQUFFLEVBQUUsQ0FBRSxNQUFNLEdBQUcsQ0FBQyxJQUFpQixDQUFDLENBQUE7QUFFdkUsTUFBTSxXQUFXLEdBQVE7SUFDdkIsS0FB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 \ No newline at end of file diff --git a/packages/kbot/dist/win-64/tauri-app.exe b/packages/kbot/dist/win-64/tauri-app.exe index 0a30844b..72ab6cc2 100644 Binary files a/packages/kbot/dist/win-64/tauri-app.exe and b/packages/kbot/dist/win-64/tauri-app.exe differ diff --git a/packages/kbot/gui/tauri-app/src/App.tsx b/packages/kbot/gui/tauri-app/src/App.tsx index ae779834..7709b510 100644 --- a/packages/kbot/gui/tauri-app/src/App.tsx +++ b/packages/kbot/gui/tauri-app/src/App.tsx @@ -2,6 +2,7 @@ import { useState, useEffect } from "react"; import { invoke } from "@tauri-apps/api/core"; import { open, save } from '@tauri-apps/plugin-dialog'; import { readFile, writeFile, BaseDirectory } from '@tauri-apps/plugin-fs'; +import { fetch } from '@tauri-apps/plugin-http'; // Path imports commented out since they're not currently used // import { // homeDir, audioDir, cacheDir, configDir, dataDir, localDataDir, desktopDir, @@ -103,28 +104,20 @@ function App() { console.log('API key available:', !!apiKey); console.log('Include images count:', includeImages.length); - // Use the same approach as the backend - import GoogleGenerativeAI dynamically - console.log('Importing GoogleGenerativeAI...'); - const { GoogleGenerativeAI } = await import('@google/generative-ai'); - console.log('GoogleGenerativeAI imported successfully'); - - const ai = new GoogleGenerativeAI(apiKey); - console.log('GoogleGenerativeAI client created'); - - const model = ai.getGenerativeModel({ model: 'gemini-2.5-flash-image-preview' }); - console.log('Model obtained:', 'gemini-2.5-flash-image-preview'); + // Use Tauri's HTTP client directly instead of Google SDK (which has fetch issues in Tauri) + console.log('Using Tauri HTTP client for API calls...'); + + // Prepare the request payload for Google Gemini API + const parts: any[] = []; if (includeImages.length > 0) { - // Image editing - similar to editImage function - const imageParts: any[] = []; - + // Add image parts for editing for (const imageFile of includeImages) { - // Extract base64 data from the data URL const base64Match = imageFile.src.match(/^data:([^;]+);base64,(.+)$/); if (base64Match) { const mimeType = base64Match[1]; const base64Data = base64Match[2]; - imageParts.push({ + parts.push({ inlineData: { mimeType, data: base64Data @@ -132,58 +125,49 @@ function App() { }); } } + } - const textPart = { text: promptText }; - const promptParts = [...imageParts, textPart]; - - console.log('Making API call for image editing with parts:', promptParts.length); - const result = await model.generateContent(promptParts); - console.log('API call completed for image editing'); - const response = result.response; - const parts = response.candidates?.[0]?.content?.parts; - - for (const part of parts || []) { - if ('inlineData' in part) { - const inlineData = part.inlineData; - if (inlineData) { - const generatedImage: GeneratedImage = { - id: Date.now().toString(), - src: `data:${inlineData.mimeType};base64,${inlineData.data}`, - prompt: promptText, - timestamp: Date.now(), - saved: false - }; - - setGeneratedImages(prev => [...prev, generatedImage]); - console.log('Generated new image (edit):', generatedImage.id); - return; - } - } - } - } else { - // Image creation - similar to createImage function - console.log('Making API call for image creation with prompt:', promptText); - const result = await model.generateContent(promptText); - console.log('API call completed for image creation'); - const response = result.response; - const parts = response.candidates?.[0]?.content?.parts; - - for (const part of parts || []) { - if ('inlineData' in part) { - const inlineData = part.inlineData; - if (inlineData) { - const generatedImage: GeneratedImage = { - id: Date.now().toString(), - src: `data:${inlineData.mimeType};base64,${inlineData.data}`, - prompt: promptText, - timestamp: Date.now(), - saved: false - }; - - setGeneratedImages(prev => [...prev, generatedImage]); - console.log('Generated new image (create):', generatedImage.id); - return; - } + // Add text prompt + parts.push({ text: promptText }); + + const requestBody = { + contents: [{ + parts: parts + }] + }; + + console.log('Making API call with parts:', parts.length); + const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-image-preview:generateContent?key=${apiKey}`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(requestBody) + }); + + if (!response.ok) { + throw new Error(`API request failed: ${response.status} ${response.statusText}`); + } + + const data = await response.json(); + console.log('API call completed successfully'); + + // Extract generated image from response + const candidates = data.candidates; + if (candidates && candidates[0]?.content?.parts) { + for (const part of candidates[0].content.parts) { + if (part.inlineData) { + const generatedImage: GeneratedImage = { + id: Date.now().toString(), + src: `data:${part.inlineData.mimeType};base64,${part.inlineData.data}`, + prompt: promptText, + timestamp: Date.now(), + saved: false + }; + + setGeneratedImages(prev => [...prev, generatedImage]); + console.log('Generated new image:', generatedImage.id); + return; } } } diff --git a/packages/kbot/package-lock.json b/packages/kbot/package-lock.json index 2518bddc..546c5cad 100644 --- a/packages/kbot/package-lock.json +++ b/packages/kbot/package-lock.json @@ -10,6 +10,7 @@ "license": "MIT", "dependencies": { "@dmitryrechkin/json-schema-to-zod": "1.0.1", + "@elevenlabs/elevenlabs-js": "2.15.0", "@google/genai": "1.19.0", "@google/generative-ai": "0.24.1", "@polymech/ai-tools": "file:../ai-tools", @@ -427,6 +428,19 @@ "zod": "^3.23.8" } }, + "node_modules/@elevenlabs/elevenlabs-js": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/@elevenlabs/elevenlabs-js/-/elevenlabs-js-2.15.0.tgz", + "integrity": "sha512-YCeWBFh3FSd4Qaf2j8a1Ko1+QwT1cphktSrPL5yxUrBP73fQGjkXlwuCddm7eB/XO3VifYajt39x9eleBKO8Mw==", + "license": "MIT", + "dependencies": { + "command-exists": "^1.2.9", + "node-fetch": "^2.7.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", @@ -3806,6 +3820,12 @@ "node": ">= 0.8" } }, + "node_modules/command-exists": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", + "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", + "license": "MIT" + }, "node_modules/commander": { "version": "12.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", diff --git a/packages/kbot/package.json b/packages/kbot/package.json index 36b75cd5..733ffc58 100644 --- a/packages/kbot/package.json +++ b/packages/kbot/package.json @@ -29,6 +29,7 @@ "register-commands": "pm-cli register-commands --config=salamand.json --group=kbot", "test": "vitest run", "test:basic": "vitest run tests/unit/basic.test.ts", + "test:tts": "vitest run tests/unit/audio/tts.test.ts", "test:transcribe": "vitest run tests/unit/transcribe/transcribe.test.ts", "test:images": "vitest run tests/unit/images/images.test.ts", "test:math": "vitest run tests/unit/math.test.ts", @@ -60,6 +61,7 @@ }, "dependencies": { "@dmitryrechkin/json-schema-to-zod": "1.0.1", + "@elevenlabs/elevenlabs-js": "2.15.0", "@google/genai": "1.19.0", "@google/generative-ai": "0.24.1", "@polymech/ai-tools": "file:../ai-tools", diff --git a/packages/kbot/src/commands/tts.ts b/packages/kbot/src/commands/tts.ts new file mode 100644 index 00000000..2dd0c742 --- /dev/null +++ b/packages/kbot/src/commands/tts.ts @@ -0,0 +1,225 @@ +import { z } from 'zod'; +import * as path from 'node:path'; +import { sync as write } from '@polymech/fs/write'; +import { sync as exists } from '@polymech/fs/exists'; +import { sync as read } from '@polymech/fs/read'; + +import { isString } from '@polymech/core/primitives'; + +import { OptionsSchema } from '../zod_schema.js'; +import { generateSpeech } from '../lib/tts-elevenlabs.js'; +import { getLogger } from '../index.js'; +import { prompt as resolvePrompt } from '../prompt.js'; +import { variables } from '../variables.js'; +import { resolve } from '@polymech/commons'; +// Cache for voices data +let voicesCache: any = null; + +const getVoicesData = async () => { + if (!voicesCache) { + try { + // Try multiple possible paths for voices.json + const possiblePaths = [ + path.resolve('src/lib/voices.json'), + path.resolve('lib/voices.json'), + path.resolve(path.dirname(new URL(import.meta.url).pathname), '..', 'lib', 'voices.json'), + path.resolve(path.dirname(new URL(import.meta.url).pathname), 'lib', 'voices.json'), + ]; + + let voicesContent = ''; + for (const voicesPath of possiblePaths) { + const cleanPath = process.platform === 'win32' && voicesPath.startsWith('/') + ? voicesPath.substring(1) + : voicesPath; + + if (exists(cleanPath)) { + voicesContent = read(cleanPath, 'string') as string; + break; + } + } + + if (voicesContent) { + voicesCache = JSON.parse(voicesContent); + } else { + // Fallback to empty voices list if file doesn't exist + voicesCache = { voices: [] }; + } + } catch (error) { + // Fallback to empty voices list if file doesn't exist + voicesCache = { voices: [] }; + } + } + return voicesCache; +}; + +// Extract voice names and IDs for help text +const getVoicesList = async () => { + const voicesData = await getVoicesData(); + return voicesData.voices.map((voice: any) => `${voice.name} (${voice.voice_id})`).join(', '); +}; + +const getVoiceNames = async () => { + const voicesData = await getVoicesData(); + return voicesData.voices.map((voice: any) => voice.name); +}; + +const findVoiceIdByName = async (name: string): Promise => { + const voicesData = await getVoicesData(); + const voice = voicesData.voices.find((v: any) => v.name.toLowerCase() === name.toLowerCase()); + return voice?.voice_id; +}; + +export const TTSOptionsSchema = () => { + const baseSchema = OptionsSchema().pick({ + prompt: true, + include: true, + dst: true, + logLevel: true, + config: true, + api_key: true, + alt: true, + }); + + // Create a synchronous voices list for help text + let voicesHelpText = 'Voice ID or name to use for speech generation. Common voices: Rachel, Clyde, Sarah, Laura, Thomas, Charlie, George (default), Callum, River, Harry, Liam, Alice, Matilda, Will, Jessica, Eric, Chris, Brian, Daniel, Lily, Bill'; + + // Try to load voices synchronously for help text + try { + const possiblePaths = [ + path.resolve('src/lib/voices.json'), + path.resolve('lib/voices.json'), + ]; + + for (const voicesPath of possiblePaths) { + if (exists(voicesPath)) { + const voicesContent = read(voicesPath, 'string') as string; + const voicesData = JSON.parse(voicesContent); + const voicesList = voicesData.voices.slice(0, 10).map((voice: any) => voice.name).join(', '); + voicesHelpText = `Voice ID or name to use for speech generation. Available voices: ${voicesList} (and ${voicesData.voices.length - 10} more)`; + break; + } + } + } catch (error) { + // Use fallback help text if loading fails + } + + return baseSchema.extend({ + dst: z.string().describe('Destination path for the output audio file. Required.'), + prompt: z.string().optional().describe('The text to convert to speech.'), + voiceId: z.string().default('JBFqnCBsd6RMkjVDRZzb').describe(voicesHelpText), + outputFormat: z.enum(['mp3_22050_32', 'mp3_44100_32', 'mp3_44100_64', 'mp3_44100_96', 'mp3_44100_128', 'mp3_44100_192', 'pcm_16000', 'pcm_22050', 'pcm_24000', 'pcm_44100', 'ulaw_8000']).default('mp3_44100_128').describe('Output format of the generated audio.'), + modelId: z.string().default('eleven_multilingual_v2').describe('Model ID to use for speech generation.'), + languageCode: z.string().optional().describe('Language code (ISO 639-1) to enforce for the model.'), + stability: z.number().min(0).max(1).optional().describe('Voice stability (0-1).'), + similarityBoost: z.number().min(0).max(1).optional().describe('Voice similarity boost (0-1).'), + style: z.number().min(0).max(1).optional().describe('Voice style (0-1).'), + useSpeakerBoost: z.boolean().optional().describe('Use speaker boost for voice enhancement.'), + seed: z.number().optional().describe('Seed for deterministic generation (0-4294967295).'), + previousText: z.string().optional().describe('Text that came before the current text for continuity.'), + nextText: z.string().optional().describe('Text that comes after the current text for continuity.'), + applyTextNormalization: z.enum(['auto', 'on', 'off']).default('auto').describe('Text normalization mode.'), + applyLanguageTextNormalization: z.boolean().default(false).describe('Apply language-specific text normalization.'), + usePvcAsIvc: z.boolean().default(false).describe('Use PVC as IVC (deprecated).'), + }); +} + +export const ttsCommand = async (argv: any) => { + const logger = getLogger(argv); + + if (argv.include && isString(argv.include)) { + argv.include = [argv.include]; + } + + try { + const parsedOptions = TTSOptionsSchema().parse(argv); + const { include, dst, ...rest } = parsedOptions; + + let textContent = ''; + + // Handle voice name to ID conversion + let voiceId = parsedOptions.voiceId; + if (voiceId && !voiceId.match(/^[a-zA-Z0-9]{20}$/)) { + // If voiceId doesn't look like an ID (20 alphanumeric chars), treat it as a name + const foundVoiceId = await findVoiceIdByName(voiceId); + if (foundVoiceId) { + voiceId = foundVoiceId; + logger.info(`Using voice "${parsedOptions.voiceId}" (${voiceId})`); + } else { + const availableVoices = await getVoiceNames(); + logger.warn(`Voice name "${voiceId}" not found. Available voices: ${availableVoices.join(', ')}`); + logger.info(`Using default voice ID: ${parsedOptions.voiceId}`); + } + } + + // Get text from --prompt or --include file + if (parsedOptions.prompt) { + const promptMessage = await resolvePrompt(parsedOptions); + textContent = promptMessage?.content as string || ''; + } else if (include && include.length > 0) { + // Read text from file(s) + const filePath = include[0]; // Use first file + if (!exists(filePath)) { + logger.error(`Input file not found at: ${filePath}`); + return; + } + textContent = read(filePath, 'string') as string; + logger.info(`Reading text from file: ${filePath}`); + } + + if (!textContent.trim()) { + logger.error('No text provided. Use --prompt "text" or --include path/to/textfile.txt'); + return; + } + + if (!dst) { + logger.error('--dst is required to specify the output audio file path.'); + return; + } + + // Prepare voice settings if any are specified + let voiceSettings = null; + if (parsedOptions.stability !== undefined || + parsedOptions.similarityBoost !== undefined || + parsedOptions.style !== undefined || + parsedOptions.useSpeakerBoost !== undefined) { + voiceSettings = { + stability: parsedOptions.stability, + similarityBoost: parsedOptions.similarityBoost, + style: parsedOptions.style, + useSpeakerBoost: parsedOptions.useSpeakerBoost, + }; + } + + logger.info(`Converting text to speech: "${textContent.substring(0, 100)}${textContent.length > 100 ? '...' : ''}"`); + + const audioBuffer = await generateSpeech({ + text: textContent, + voiceId: voiceId, + outputFormat: parsedOptions.outputFormat, + modelId: parsedOptions.modelId, + languageCode: parsedOptions.languageCode, + voiceSettings, + seed: parsedOptions.seed, + previousText: parsedOptions.previousText, + nextText: parsedOptions.nextText, + applyTextNormalization: parsedOptions.applyTextNormalization, + applyLanguageTextNormalization: parsedOptions.applyLanguageTextNormalization, + usePvcAsIvc: parsedOptions.usePvcAsIvc, + config: parsedOptions.config, + api_key: parsedOptions.api_key, + logger, + }); + + if (audioBuffer) { + const vars = variables(parsedOptions); + const dstPath = path.resolve(resolve(dst, parsedOptions.alt, vars)); + write(dstPath, audioBuffer); + logger.info(`Audio saved to: ${dstPath}`); + } else { + logger.error('Failed to generate audio.'); + } + + } catch (error: any) { + logger.error('Failed to parse options or generate speech:', error.message, error.issues, error.stack); + } +}; diff --git a/packages/kbot/src/lib/tts-elevenlabs.ts b/packages/kbot/src/lib/tts-elevenlabs.ts new file mode 100644 index 00000000..966d489a --- /dev/null +++ b/packages/kbot/src/lib/tts-elevenlabs.ts @@ -0,0 +1,116 @@ +import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js"; +import { getLogger } from '../index.js'; +import { loadConfig } from '../config.js'; + +// Define output format type based on ElevenLabs API documentation +type OutputFormat = + | "mp3_22050_32" | "mp3_44100_32" | "mp3_44100_64" | "mp3_44100_96" | "mp3_44100_128" | "mp3_44100_192" + | "pcm_16000" | "pcm_22050" | "pcm_24000" | "pcm_44100" | "ulaw_8000"; + +export interface TTSOptions { + text: string; + voiceId?: string; + outputFormat?: OutputFormat; + modelId?: string; + languageCode?: string | null; + voiceSettings?: { + stability?: number; + similarityBoost?: number; + style?: number; + useSpeakerBoost?: boolean; + } | null; + pronunciationDictionaryLocators?: Array<{ + pronunciationDictionaryId: string; + versionId: string; + }> | null; + seed?: number | null; + previousText?: string | null; + nextText?: string | null; + previousRequestIds?: string[] | null; + nextRequestIds?: string[] | null; + applyTextNormalization?: 'auto' | 'on' | 'off'; + applyLanguageTextNormalization?: boolean; + usePvcAsIvc?: boolean; + config?: any; + api_key?: string; + logger?: any; +} + +export const generateSpeech = async (options: TTSOptions): Promise => { + const logger = options.logger || getLogger({ logLevel: 4 }); + + // Get API key from options or config + const config = loadConfig(options); + const apiKey = options.api_key || config?.elevenlabs?.key; + + if (!apiKey) { + throw new Error('ElevenLabs API key not found. Please provide it via --api_key or in your config file under elevenlabs.key'); + } + + const client = new ElevenLabsClient({ + apiKey: apiKey + }); + + try { + logger.info(`Generating speech with ElevenLabs...`); + logger.debug(`Voice ID: ${options.voiceId || 'JBFqnCBsd6RMkjVDRZzb'}`); + logger.debug(`Model: ${options.modelId || 'eleven_multilingual_v2'}`); + logger.debug(`Output Format: ${options.outputFormat || 'mp3_44100_128'}`); + logger.debug(`Text length: ${options.text.length} characters`); + + const audioStream = await client.textToSpeech.convert( + options.voiceId || "JBFqnCBsd6RMkjVDRZzb", + { + outputFormat: options.outputFormat || "mp3_44100_128", + text: options.text, + modelId: options.modelId || "eleven_multilingual_v2", + languageCode: options.languageCode, + voiceSettings: options.voiceSettings, + pronunciationDictionaryLocators: options.pronunciationDictionaryLocators, + seed: options.seed, + previousText: options.previousText, + nextText: options.nextText, + previousRequestIds: options.previousRequestIds, + nextRequestIds: options.nextRequestIds, + applyTextNormalization: options.applyTextNormalization || 'auto', + applyLanguageTextNormalization: options.applyLanguageTextNormalization || false, + usePvcAsIvc: options.usePvcAsIvc || false, + } + ); + + // The convert endpoint returns a ReadableStream, we need to collect all chunks + const chunks: Uint8Array[] = []; + const reader = audioStream.getReader(); + + try { + while (true) { + const { done, value } = await reader.read(); + if (done) break; + chunks.push(value); + } + } finally { + reader.releaseLock(); + } + + // Combine all chunks into a single buffer + const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0); + const audioBuffer = new Uint8Array(totalLength); + let offset = 0; + for (const chunk of chunks) { + audioBuffer.set(chunk, offset); + offset += chunk.length; + } + + const finalBuffer = Buffer.from(audioBuffer); + logger.info(`Successfully generated ${finalBuffer.length} bytes of audio`); + + return finalBuffer; + + } catch (error: any) { + logger.error('Failed to generate speech with ElevenLabs:', error.message); + if (error.response?.data) { + logger.error('API Error Details:', error.response.data); + } + throw error; + } +}; diff --git a/packages/kbot/src/lib/voices.json b/packages/kbot/src/lib/voices.json new file mode 100644 index 00000000..6e9797b0 --- /dev/null +++ b/packages/kbot/src/lib/voices.json @@ -0,0 +1,3349 @@ +{ + "voices": [ + { + "voice_id": "21m00Tcm4TlvDq8ikWAM", + "name": "Rachel", + "samples": null, + "category": "premade", + "fine_tuning": { + "is_allowed_to_fine_tune": false, + "state": {}, + "verification_failures": [], + "verification_attempts_count": 0, + "manual_verification_requested": false, + "language": null, + "progress": {}, + "message": {}, + "dataset_duration_seconds": null, + "verification_attempts": null, + "slice_ids": null, + "manual_verification": null, + "max_verification_attempts": null, + "next_max_verification_attempts_reset_unix_ms": null + }, + "labels": { + "accent": "american", + "descriptive": "casual", + "age": "young", + "gender": "female", + "language": "en", + "use_case": "conversational" + }, + "description": "Matter-of-fact, personable woman. Great for conversational use cases.", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/21m00Tcm4TlvDq8ikWAM/b4928a68-c03b-411f-8533-3d5c299fd451.mp3", + "available_for_tiers": [], + "settings": null, + "sharing": null, + "high_quality_base_model_ids": [], + "verified_languages": [], + "safety_control": null, + "voice_verification": { + "requires_verification": false, + "is_verified": false, + "verification_failures": [], + "verification_attempts_count": 0, + "language": null, + "verification_attempts": null + }, + "permission_on_resource": null, + "is_owner": false, + "is_legacy": false, + "is_mixed": false, + "favorited_at_unix": null, + "created_at_unix": null + }, + { + "voice_id": "2EiwWnXFnvU5JabPnv8n", + "name": "Clyde", + "samples": null, + "category": "premade", + "fine_tuning": { + "is_allowed_to_fine_tune": true, + "state": { + "eleven_flash_v2_5": "fine_tuned", + "eleven_turbo_v2": "fine_tuned", + "eleven_flash_v2": "fine_tuned", + "eleven_v2_flash": "fine_tuned", + "eleven_v2_5_flash": "fine_tuned" + }, + "verification_failures": [], + "verification_attempts_count": 0, + "manual_verification_requested": false, + "language": "en", + "progress": { + "eleven_flash_v2_5": 1, + "eleven_v2_flash": 1, + "eleven_flash_v2": 1, + "eleven_v2_5_flash": 1 + }, + "message": { + "eleven_multilingual_v2": "", + "eleven_turbo_v2_5": "", + "eleven_flash_v2_5": "Done!", + "eleven_v2_flash": "Done!", + "eleven_v2_5_flash": "Done!", + "eleven_turbo_v2": "", + "eleven_flash_v2": "Done!" + }, + "dataset_duration_seconds": null, + "verification_attempts": null, + "slice_ids": null, + "manual_verification": null, + "max_verification_attempts": 5, + "next_max_verification_attempts_reset_unix_ms": 1700000000000 + }, + "labels": { + "accent": "american", + "descriptive": "intense", + "age": "middle_aged", + "gender": "male", + "language": "en", + "use_case": "characters_animation" + }, + "description": "Great for character use-cases", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/2EiwWnXFnvU5JabPnv8n/65d80f52-703f-4cae-a91d-75d4e200ed02.mp3", + "available_for_tiers": [], + "settings": null, + "sharing": null, + "high_quality_base_model_ids": [ + "eleven_v2_flash", + "eleven_flash_v2", + "eleven_turbo_v2_5", + "eleven_multilingual_v2", + "eleven_multilingual_v1", + "eleven_v2_5_flash", + "eleven_flash_v2_5", + "eleven_turbo_v2" + ], + "verified_languages": [ + { + "language": "en", + "model_id": "eleven_v2_flash", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/2EiwWnXFnvU5JabPnv8n/65d80f52-703f-4cae-a91d-75d4e200ed02.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/2EiwWnXFnvU5JabPnv8n/65d80f52-703f-4cae-a91d-75d4e200ed02.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2_5", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/2EiwWnXFnvU5JabPnv8n/65d80f52-703f-4cae-a91d-75d4e200ed02.mp3" + }, + { + "language": "en", + "model_id": "eleven_multilingual_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/2EiwWnXFnvU5JabPnv8n/65d80f52-703f-4cae-a91d-75d4e200ed02.mp3" + }, + { + "language": "en", + "model_id": "promade_v1", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/2EiwWnXFnvU5JabPnv8n/65d80f52-703f-4cae-a91d-75d4e200ed02.mp3" + }, + { + "language": "en", + "model_id": "eleven_v2_5_flash", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/2EiwWnXFnvU5JabPnv8n/65d80f52-703f-4cae-a91d-75d4e200ed02.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2_5", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/2EiwWnXFnvU5JabPnv8n/65d80f52-703f-4cae-a91d-75d4e200ed02.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/2EiwWnXFnvU5JabPnv8n/65d80f52-703f-4cae-a91d-75d4e200ed02.mp3" + } + ], + "safety_control": null, + "voice_verification": { + "requires_verification": false, + "is_verified": false, + "verification_failures": [], + "verification_attempts_count": 0, + "language": null, + "verification_attempts": null + }, + "permission_on_resource": null, + "is_owner": false, + "is_legacy": false, + "is_mixed": false, + "favorited_at_unix": null, + "created_at_unix": null + }, + { + "voice_id": "CwhRBWXzGAHq8TQ4Fs17", + "name": "Roger", + "samples": null, + "category": "premade", + "fine_tuning": { + "is_allowed_to_fine_tune": true, + "state": { + "eleven_multilingual_v2": "fine_tuned", + "eleven_turbo_v2_5": "failed", + "eleven_flash_v2_5": "fine_tuned", + "eleven_v2_flash": "fine_tuned", + "eleven_v2_5_flash": "fine_tuned", + "eleven_turbo_v2": "fine_tuned", + "eleven_flash_v2": "fine_tuned" + }, + "verification_failures": [], + "verification_attempts_count": 0, + "manual_verification_requested": false, + "language": "en", + "progress": { + "eleven_flash_v2_5": 1, + "eleven_v2_flash": 1, + "eleven_flash_v2": 1, + "eleven_v2_5_flash": 1 + }, + "message": { + "eleven_flash_v2_5": "Done!", + "eleven_v2_flash": "Done!", + "eleven_flash_v2": "Done!", + "eleven_v2_5_flash": "Done!" + }, + "dataset_duration_seconds": null, + "verification_attempts": null, + "slice_ids": null, + "manual_verification": null, + "max_verification_attempts": 5, + "next_max_verification_attempts_reset_unix_ms": 1700000000000 + }, + "labels": { + "accent": "american", + "descriptive": "classy", + "age": "middle_aged", + "gender": "male", + "language": "en", + "use_case": "conversational" + }, + "description": "Easy going and perfect for casual conversations.", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/CwhRBWXzGAHq8TQ4Fs17/58ee3ff5-f6f2-4628-93b8-e38eb31806b0.mp3", + "available_for_tiers": [], + "settings": null, + "sharing": null, + "high_quality_base_model_ids": [ + "eleven_v2_flash", + "eleven_flash_v2", + "eleven_turbo_v2_5", + "eleven_multilingual_v2", + "eleven_v2_5_flash", + "eleven_flash_v2_5", + "eleven_turbo_v2" + ], + "verified_languages": [ + { + "language": "en", + "model_id": "eleven_v2_flash", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/CwhRBWXzGAHq8TQ4Fs17/58ee3ff5-f6f2-4628-93b8-e38eb31806b0.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/CwhRBWXzGAHq8TQ4Fs17/58ee3ff5-f6f2-4628-93b8-e38eb31806b0.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2_5", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/CwhRBWXzGAHq8TQ4Fs17/58ee3ff5-f6f2-4628-93b8-e38eb31806b0.mp3" + }, + { + "language": "en", + "model_id": "eleven_multilingual_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/CwhRBWXzGAHq8TQ4Fs17/58ee3ff5-f6f2-4628-93b8-e38eb31806b0.mp3" + }, + { + "language": "en", + "model_id": "eleven_v2_5_flash", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/CwhRBWXzGAHq8TQ4Fs17/58ee3ff5-f6f2-4628-93b8-e38eb31806b0.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2_5", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/CwhRBWXzGAHq8TQ4Fs17/58ee3ff5-f6f2-4628-93b8-e38eb31806b0.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/CwhRBWXzGAHq8TQ4Fs17/58ee3ff5-f6f2-4628-93b8-e38eb31806b0.mp3" + }, + { + "language": "fr", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "fr-FR", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/CwhRBWXzGAHq8TQ4Fs17/042d9b70-5927-4630-985e-e95107b74ec2.mp3" + }, + { + "language": "de", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "de-DE", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/CwhRBWXzGAHq8TQ4Fs17/fa6a7658-18a9-4634-a96f-95dc3c47629d.mp3" + }, + { + "language": "nl", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "nl-NL", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/CwhRBWXzGAHq8TQ4Fs17/12a2ba8b-4fb3-44b6-9bc7-da0afd076fc9.mp3" + }, + { + "language": "es", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": null, + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/CwhRBWXzGAHq8TQ4Fs17/f172f037-5e23-44ea-a08e-56ddb6447d5b.mp3" + } + ], + "safety_control": null, + "voice_verification": { + "requires_verification": false, + "is_verified": false, + "verification_failures": [], + "verification_attempts_count": 0, + "language": null, + "verification_attempts": null + }, + "permission_on_resource": null, + "is_owner": false, + "is_legacy": false, + "is_mixed": false, + "favorited_at_unix": null, + "created_at_unix": null + }, + { + "voice_id": "EXAVITQu4vr4xnSDxMaL", + "name": "Sarah", + "samples": null, + "category": "premade", + "fine_tuning": { + "is_allowed_to_fine_tune": true, + "state": {}, + "verification_failures": [], + "verification_attempts_count": 0, + "manual_verification_requested": false, + "language": "en", + "progress": {}, + "message": {}, + "dataset_duration_seconds": null, + "verification_attempts": null, + "slice_ids": null, + "manual_verification": null, + "max_verification_attempts": 5, + "next_max_verification_attempts_reset_unix_ms": 1700000000000 + }, + "labels": { + "accent": "american", + "descriptive": "professional", + "age": "young", + "gender": "female", + "language": "en", + "use_case": "entertainment_tv" + }, + "description": "Young adult woman with a confident and warm, mature quality and a reassuring, professional tone.", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/EXAVITQu4vr4xnSDxMaL/01a3e33c-6e99-4ee7-8543-ff2216a32186.mp3", + "available_for_tiers": [], + "settings": null, + "sharing": null, + "high_quality_base_model_ids": [ + "eleven_turbo_v2", + "eleven_multilingual_v2", + "eleven_turbo_v2_5" + ], + "verified_languages": [ + { + "language": "en", + "model_id": "eleven_turbo_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/EXAVITQu4vr4xnSDxMaL/01a3e33c-6e99-4ee7-8543-ff2216a32186.mp3" + }, + { + "language": "en", + "model_id": "eleven_multilingual_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/EXAVITQu4vr4xnSDxMaL/01a3e33c-6e99-4ee7-8543-ff2216a32186.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2_5", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/EXAVITQu4vr4xnSDxMaL/01a3e33c-6e99-4ee7-8543-ff2216a32186.mp3" + }, + { + "language": "fr", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "fr-FR", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/EXAVITQu4vr4xnSDxMaL/093154f2-dd9f-4a4c-b5c3-81836c7ac3f6.mp3" + }, + { + "language": "ar", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": null, + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/EXAVITQu4vr4xnSDxMaL/ecb43dfe-b9f3-4691-8ee8-90c5ad3f4dbb.mp3" + }, + { + "language": "zh", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "cmn-CN", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/EXAVITQu4vr4xnSDxMaL/d9b9f54d-c08b-426e-80f3-b4f2089c3a59.mp3" + }, + { + "language": "es", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": null, + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/EXAVITQu4vr4xnSDxMaL/57ab5344-ed96-46fc-b319-82dc1c89bf66.mp3" + }, + { + "language": "hi", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "hi-IN", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/EXAVITQu4vr4xnSDxMaL/2f2caaae-ad5e-4ff2-a084-7a6067913a69.mp3" + } + ], + "safety_control": null, + "voice_verification": { + "requires_verification": false, + "is_verified": false, + "verification_failures": [], + "verification_attempts_count": 0, + "language": null, + "verification_attempts": null + }, + "permission_on_resource": null, + "is_owner": false, + "is_legacy": false, + "is_mixed": false, + "favorited_at_unix": null, + "created_at_unix": null + }, + { + "voice_id": "FGY2WhTYpPnrIDTdsKH5", + "name": "Laura", + "samples": null, + "category": "premade", + "fine_tuning": { + "is_allowed_to_fine_tune": true, + "state": { + "eleven_multilingual_v2": "fine_tuned", + "eleven_turbo_v2_5": "fine_tuned", + "eleven_flash_v2_5": "fine_tuned", + "eleven_v2_flash": "fine_tuned", + "eleven_v2_5_flash": "fine_tuned", + "eleven_turbo_v2": "fine_tuned", + "eleven_flash_v2": "fine_tuned" + }, + "verification_failures": [], + "verification_attempts_count": 0, + "manual_verification_requested": false, + "language": "en", + "progress": { + "eleven_flash_v2_5": 1, + "eleven_v2_flash": 1, + "eleven_flash_v2": 1, + "eleven_v2_5_flash": 1 + }, + "message": { + "eleven_flash_v2_5": "Done!", + "eleven_v2_flash": "Done!", + "eleven_flash_v2": "Done!", + "eleven_v2_5_flash": "Done!" + }, + "dataset_duration_seconds": null, + "verification_attempts": null, + "slice_ids": null, + "manual_verification": null, + "max_verification_attempts": 5, + "next_max_verification_attempts_reset_unix_ms": 1700000000000 + }, + "labels": { + "accent": "american", + "descriptive": "sassy", + "age": "young", + "gender": "female", + "language": "en", + "use_case": "social_media" + }, + "description": "This young adult female voice delivers sunny enthusiasm with a quirky attitude.", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/FGY2WhTYpPnrIDTdsKH5/67341759-ad08-41a5-be6e-de12fe448618.mp3", + "available_for_tiers": [], + "settings": null, + "sharing": null, + "high_quality_base_model_ids": [ + "eleven_v2_flash", + "eleven_flash_v2", + "eleven_turbo_v2_5", + "eleven_multilingual_v2", + "eleven_v2_5_flash", + "eleven_flash_v2_5", + "eleven_turbo_v2" + ], + "verified_languages": [ + { + "language": "en", + "model_id": "eleven_v2_flash", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/FGY2WhTYpPnrIDTdsKH5/67341759-ad08-41a5-be6e-de12fe448618.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/FGY2WhTYpPnrIDTdsKH5/67341759-ad08-41a5-be6e-de12fe448618.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2_5", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/FGY2WhTYpPnrIDTdsKH5/67341759-ad08-41a5-be6e-de12fe448618.mp3" + }, + { + "language": "en", + "model_id": "eleven_multilingual_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/FGY2WhTYpPnrIDTdsKH5/67341759-ad08-41a5-be6e-de12fe448618.mp3" + }, + { + "language": "en", + "model_id": "eleven_v2_5_flash", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/FGY2WhTYpPnrIDTdsKH5/67341759-ad08-41a5-be6e-de12fe448618.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2_5", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/FGY2WhTYpPnrIDTdsKH5/67341759-ad08-41a5-be6e-de12fe448618.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/FGY2WhTYpPnrIDTdsKH5/67341759-ad08-41a5-be6e-de12fe448618.mp3" + }, + { + "language": "fr", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "fr-FR", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/FGY2WhTYpPnrIDTdsKH5/21082ee9-c176-4454-ac50-54bdf230ef49.mp3" + }, + { + "language": "ar", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": null, + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/FGY2WhTYpPnrIDTdsKH5/ec8fcd73-ed00-4478-ad2f-0dca5c5a5583.mp3" + }, + { + "language": "zh", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "cmn-CN", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/FGY2WhTYpPnrIDTdsKH5/56e58899-8324-4908-a617-3e7710251c39.mp3" + }, + { + "language": "de", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "de-DE", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/FGY2WhTYpPnrIDTdsKH5/210e72ad-ba9e-475e-9e18-000bc7cd771c.mp3" + } + ], + "safety_control": null, + "voice_verification": { + "requires_verification": false, + "is_verified": false, + "verification_failures": [], + "verification_attempts_count": 0, + "language": null, + "verification_attempts": null + }, + "permission_on_resource": null, + "is_owner": false, + "is_legacy": false, + "is_mixed": false, + "favorited_at_unix": null, + "created_at_unix": null + }, + { + "voice_id": "GBv7mTt0atIp3Br8iCZE", + "name": "Thomas", + "samples": null, + "category": "premade", + "fine_tuning": { + "is_allowed_to_fine_tune": true, + "state": { + "eleven_flash_v2_5": "fine_tuned", + "eleven_turbo_v2": "fine_tuned", + "eleven_flash_v2": "fine_tuned", + "eleven_v2_flash": "fine_tuned", + "eleven_v2_5_flash": "fine_tuned" + }, + "verification_failures": [], + "verification_attempts_count": 0, + "manual_verification_requested": false, + "language": "en", + "progress": { + "eleven_flash_v2_5": 1, + "eleven_v2_flash": 1, + "eleven_flash_v2": 1, + "eleven_v2_5_flash": 1 + }, + "message": { + "eleven_multilingual_v2": "", + "eleven_turbo_v2_5": "", + "eleven_flash_v2_5": "Done!", + "eleven_v2_flash": "Done!", + "eleven_v2_5_flash": "Done!", + "eleven_turbo_v2": "", + "eleven_flash_v2": "Done!" + }, + "dataset_duration_seconds": null, + "verification_attempts": null, + "slice_ids": null, + "manual_verification": null, + "max_verification_attempts": 5, + "next_max_verification_attempts_reset_unix_ms": 1700000000000 + }, + "labels": { + "accent": "american", + "descriptive": "meditative", + "age": "young", + "gender": "male", + "language": "en", + "use_case": "narrative_story" + }, + "description": "Soft and subdued male voice, optimal for narrations or meditations", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/GBv7mTt0atIp3Br8iCZE/98542988-5267-4148-9a9e-baa8c4f14644.mp3", + "available_for_tiers": [], + "settings": null, + "sharing": null, + "high_quality_base_model_ids": [ + "eleven_v2_flash", + "eleven_flash_v2", + "eleven_turbo_v2_5", + "eleven_multilingual_v2", + "eleven_multilingual_v1", + "eleven_v2_5_flash", + "eleven_flash_v2_5", + "eleven_turbo_v2" + ], + "verified_languages": [ + { + "language": "en", + "model_id": "eleven_v2_flash", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/GBv7mTt0atIp3Br8iCZE/98542988-5267-4148-9a9e-baa8c4f14644.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/GBv7mTt0atIp3Br8iCZE/98542988-5267-4148-9a9e-baa8c4f14644.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2_5", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/GBv7mTt0atIp3Br8iCZE/98542988-5267-4148-9a9e-baa8c4f14644.mp3" + }, + { + "language": "en", + "model_id": "eleven_multilingual_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/GBv7mTt0atIp3Br8iCZE/98542988-5267-4148-9a9e-baa8c4f14644.mp3" + }, + { + "language": "en", + "model_id": "promade_v1", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/GBv7mTt0atIp3Br8iCZE/98542988-5267-4148-9a9e-baa8c4f14644.mp3" + }, + { + "language": "en", + "model_id": "eleven_v2_5_flash", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/GBv7mTt0atIp3Br8iCZE/98542988-5267-4148-9a9e-baa8c4f14644.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2_5", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/GBv7mTt0atIp3Br8iCZE/98542988-5267-4148-9a9e-baa8c4f14644.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/GBv7mTt0atIp3Br8iCZE/98542988-5267-4148-9a9e-baa8c4f14644.mp3" + } + ], + "safety_control": null, + "voice_verification": { + "requires_verification": false, + "is_verified": false, + "verification_failures": [], + "verification_attempts_count": 0, + "language": null, + "verification_attempts": null + }, + "permission_on_resource": null, + "is_owner": false, + "is_legacy": false, + "is_mixed": false, + "favorited_at_unix": null, + "created_at_unix": null + }, + { + "voice_id": "IKne3meq5aSn9XLyUdCD", + "name": "Charlie", + "samples": null, + "category": "premade", + "fine_tuning": { + "is_allowed_to_fine_tune": true, + "state": { + "eleven_flash_v2_5": "fine_tuned", + "eleven_turbo_v2": "fine_tuned", + "eleven_flash_v2": "fine_tuned", + "eleven_v2_flash": "fine_tuned", + "eleven_v2_5_flash": "fine_tuned" + }, + "verification_failures": [], + "verification_attempts_count": 0, + "manual_verification_requested": false, + "language": "en", + "progress": { + "eleven_flash_v2_5": 1, + "eleven_v2_flash": 1, + "eleven_flash_v2": 1, + "eleven_v2_5_flash": 1 + }, + "message": { + "eleven_flash_v2_5": "Done!", + "eleven_turbo_v2": "", + "eleven_flash_v2": "Done!", + "eleven_v2_flash": "Done!", + "eleven_v2_5_flash": "Done!" + }, + "dataset_duration_seconds": null, + "verification_attempts": null, + "slice_ids": null, + "manual_verification": null, + "max_verification_attempts": 5, + "next_max_verification_attempts_reset_unix_ms": 1700000000000 + }, + "labels": { + "accent": "australian", + "descriptive": "hyped", + "age": "young", + "gender": "male", + "language": "en", + "use_case": "conversational" + }, + "description": "A young Australian male with a confident and energetic voice.", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/IKne3meq5aSn9XLyUdCD/102de6f2-22ed-43e0-a1f1-111fa75c5481.mp3", + "available_for_tiers": [], + "settings": null, + "sharing": null, + "high_quality_base_model_ids": [ + "eleven_v2_flash", + "eleven_flash_v2", + "eleven_turbo_v2_5", + "eleven_multilingual_v2", + "eleven_multilingual_v1", + "eleven_v2_5_flash", + "eleven_flash_v2_5", + "eleven_turbo_v2" + ], + "verified_languages": [ + { + "language": "en", + "model_id": "eleven_v2_flash", + "accent": "australian", + "locale": "en-AU", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/IKne3meq5aSn9XLyUdCD/102de6f2-22ed-43e0-a1f1-111fa75c5481.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2", + "accent": "australian", + "locale": "en-AU", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/IKne3meq5aSn9XLyUdCD/102de6f2-22ed-43e0-a1f1-111fa75c5481.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2_5", + "accent": "australian", + "locale": "en-AU", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/IKne3meq5aSn9XLyUdCD/102de6f2-22ed-43e0-a1f1-111fa75c5481.mp3" + }, + { + "language": "en", + "model_id": "eleven_multilingual_v2", + "accent": "australian", + "locale": "en-AU", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/IKne3meq5aSn9XLyUdCD/102de6f2-22ed-43e0-a1f1-111fa75c5481.mp3" + }, + { + "language": "en", + "model_id": "promade_v1", + "accent": "australian", + "locale": "en-AU", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/IKne3meq5aSn9XLyUdCD/102de6f2-22ed-43e0-a1f1-111fa75c5481.mp3" + }, + { + "language": "en", + "model_id": "eleven_v2_5_flash", + "accent": "australian", + "locale": "en-AU", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/IKne3meq5aSn9XLyUdCD/102de6f2-22ed-43e0-a1f1-111fa75c5481.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2_5", + "accent": "australian", + "locale": "en-AU", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/IKne3meq5aSn9XLyUdCD/102de6f2-22ed-43e0-a1f1-111fa75c5481.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2", + "accent": "australian", + "locale": "en-AU", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/IKne3meq5aSn9XLyUdCD/102de6f2-22ed-43e0-a1f1-111fa75c5481.mp3" + }, + { + "language": "zh", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "cmn-CN", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/IKne3meq5aSn9XLyUdCD/51392837-4691-4e9c-a11d-658848033ace.mp3" + }, + { + "language": "pt", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": null, + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/IKne3meq5aSn9XLyUdCD/f1d38c1a-b69a-44f5-9d91-76d17dcce479.mp3" + }, + { + "language": "fil", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "fil-PH", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/IKne3meq5aSn9XLyUdCD/7eae8500-ea92-47c1-95fc-394cf3bc45d2.mp3" + }, + { + "language": "es", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": null, + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/IKne3meq5aSn9XLyUdCD/52f3846a-eee1-43e4-bcd1-0280f20fe202.mp3" + } + ], + "safety_control": null, + "voice_verification": { + "requires_verification": false, + "is_verified": false, + "verification_failures": [], + "verification_attempts_count": 0, + "language": null, + "verification_attempts": null + }, + "permission_on_resource": null, + "is_owner": false, + "is_legacy": false, + "is_mixed": false, + "favorited_at_unix": null, + "created_at_unix": null + }, + { + "voice_id": "JBFqnCBsd6RMkjVDRZzb", + "name": "George", + "samples": null, + "category": "premade", + "fine_tuning": { + "is_allowed_to_fine_tune": true, + "state": { + "eleven_turbo_v2": "fine_tuned", + "eleven_v2_flash": "fine_tuned", + "eleven_v2_5_flash": "fine_tuned" + }, + "verification_failures": [], + "verification_attempts_count": 0, + "manual_verification_requested": false, + "language": "en", + "progress": { + "eleven_v2_flash": 1, + "eleven_v2_5_flash": 1 + }, + "message": { + "eleven_turbo_v2": "", + "eleven_v2_flash": "Done!", + "eleven_v2_5_flash": "Done!" + }, + "dataset_duration_seconds": null, + "verification_attempts": null, + "slice_ids": null, + "manual_verification": null, + "max_verification_attempts": 5, + "next_max_verification_attempts_reset_unix_ms": 1700000000000 + }, + "labels": { + "accent": "british", + "descriptive": "mature", + "age": "middle_aged", + "gender": "male", + "language": "en", + "use_case": "narrative_story" + }, + "description": "Warm resonance that instantly captivates listeners.", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/JBFqnCBsd6RMkjVDRZzb/e6206d1a-0721-4787-aafb-06a6e705cac5.mp3", + "available_for_tiers": [], + "settings": null, + "sharing": null, + "high_quality_base_model_ids": [ + "eleven_v2_flash", + "eleven_flash_v2", + "eleven_turbo_v2_5", + "eleven_multilingual_v2", + "eleven_v2_5_flash", + "eleven_flash_v2_5", + "eleven_turbo_v2" + ], + "verified_languages": [ + { + "language": "en", + "model_id": "eleven_v2_flash", + "accent": "british", + "locale": "en-GB", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/JBFqnCBsd6RMkjVDRZzb/e6206d1a-0721-4787-aafb-06a6e705cac5.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2", + "accent": "british", + "locale": "en-GB", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/JBFqnCBsd6RMkjVDRZzb/e6206d1a-0721-4787-aafb-06a6e705cac5.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2_5", + "accent": "british", + "locale": "en-GB", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/JBFqnCBsd6RMkjVDRZzb/e6206d1a-0721-4787-aafb-06a6e705cac5.mp3" + }, + { + "language": "en", + "model_id": "eleven_multilingual_v2", + "accent": "british", + "locale": "en-GB", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/JBFqnCBsd6RMkjVDRZzb/e6206d1a-0721-4787-aafb-06a6e705cac5.mp3" + }, + { + "language": "en", + "model_id": "eleven_v2_5_flash", + "accent": "british", + "locale": "en-GB", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/JBFqnCBsd6RMkjVDRZzb/e6206d1a-0721-4787-aafb-06a6e705cac5.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2_5", + "accent": "british", + "locale": "en-GB", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/JBFqnCBsd6RMkjVDRZzb/e6206d1a-0721-4787-aafb-06a6e705cac5.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2", + "accent": "british", + "locale": "en-GB", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/JBFqnCBsd6RMkjVDRZzb/e6206d1a-0721-4787-aafb-06a6e705cac5.mp3" + }, + { + "language": "fr", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "fr-FR", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/JBFqnCBsd6RMkjVDRZzb/6096acce-e18f-4e95-a8e3-bb1c0a27624e.mp3" + }, + { + "language": "ar", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": null, + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/JBFqnCBsd6RMkjVDRZzb/0ece09f9-7d3e-4031-af75-936aa0cda577.mp3" + }, + { + "language": "ja", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "ja-JP", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/JBFqnCBsd6RMkjVDRZzb/709a894a-d0d1-46d7-9c10-3b140e3a69f2.mp3" + }, + { + "language": "cs", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "cs-CZ", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/JBFqnCBsd6RMkjVDRZzb/4347a4c3-142a-4490-9777-00671ef3855c.mp3" + }, + { + "language": "fil", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "fil-PH", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/JBFqnCBsd6RMkjVDRZzb/924cfaf5-c7db-49fe-b835-7d37ca424314.mp3" + }, + { + "language": "es", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": null, + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/JBFqnCBsd6RMkjVDRZzb/eae50a0d-5a39-4795-9b1e-1d58f7f87e63.mp3" + }, + { + "language": "hi", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "hi-IN", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/JBFqnCBsd6RMkjVDRZzb/15c58de3-5d6c-461a-8111-c473fd185573.mp3" + } + ], + "safety_control": null, + "voice_verification": { + "requires_verification": false, + "is_verified": false, + "verification_failures": [], + "verification_attempts_count": 0, + "language": null, + "verification_attempts": null + }, + "permission_on_resource": null, + "is_owner": false, + "is_legacy": false, + "is_mixed": false, + "favorited_at_unix": null, + "created_at_unix": null + }, + { + "voice_id": "N2lVS1w4EtoT3dr4eOWO", + "name": "Callum", + "samples": null, + "category": "premade", + "fine_tuning": { + "is_allowed_to_fine_tune": true, + "state": { + "eleven_flash_v2_5": "fine_tuned", + "eleven_turbo_v2": "fine_tuned", + "eleven_flash_v2": "fine_tuned", + "eleven_v2_flash": "fine_tuned", + "eleven_v2_5_flash": "fine_tuned" + }, + "verification_failures": [], + "verification_attempts_count": 0, + "manual_verification_requested": false, + "language": "en", + "progress": { + "eleven_flash_v2_5": 1, + "eleven_v2_flash": 1, + "eleven_flash_v2": 1, + "eleven_v2_5_flash": 1 + }, + "message": { + "eleven_flash_v2_5": "Done!", + "eleven_turbo_v2": "", + "eleven_flash_v2": "Done!", + "eleven_v2_flash": "Done!", + "eleven_v2_5_flash": "Done!" + }, + "dataset_duration_seconds": null, + "verification_attempts": null, + "slice_ids": null, + "manual_verification": null, + "max_verification_attempts": 5, + "next_max_verification_attempts_reset_unix_ms": 1700000000000 + }, + "labels": { + "accent": "", + "age": "middle_aged", + "language": "en", + "gender": "male", + "use_case": "characters" + }, + "description": "Deceptively gravelly, yet unsettling edge.", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/N2lVS1w4EtoT3dr4eOWO/ac833bd8-ffda-4938-9ebc-b0f99ca25481.mp3", + "available_for_tiers": [], + "settings": null, + "sharing": null, + "high_quality_base_model_ids": [ + "eleven_v2_flash", + "eleven_flash_v2", + "eleven_turbo_v2_5", + "eleven_multilingual_v2", + "eleven_multilingual_v1", + "eleven_v2_5_flash", + "eleven_flash_v2_5", + "eleven_turbo_v2" + ], + "verified_languages": [ + { + "language": "en", + "model_id": "eleven_v2_flash", + "accent": null, + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/N2lVS1w4EtoT3dr4eOWO/ac833bd8-ffda-4938-9ebc-b0f99ca25481.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2", + "accent": null, + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/N2lVS1w4EtoT3dr4eOWO/ac833bd8-ffda-4938-9ebc-b0f99ca25481.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2_5", + "accent": null, + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/N2lVS1w4EtoT3dr4eOWO/ac833bd8-ffda-4938-9ebc-b0f99ca25481.mp3" + }, + { + "language": "en", + "model_id": "eleven_multilingual_v2", + "accent": null, + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/N2lVS1w4EtoT3dr4eOWO/ac833bd8-ffda-4938-9ebc-b0f99ca25481.mp3" + }, + { + "language": "en", + "model_id": "promade_v1", + "accent": null, + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/N2lVS1w4EtoT3dr4eOWO/ac833bd8-ffda-4938-9ebc-b0f99ca25481.mp3" + }, + { + "language": "en", + "model_id": "eleven_v2_5_flash", + "accent": null, + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/N2lVS1w4EtoT3dr4eOWO/ac833bd8-ffda-4938-9ebc-b0f99ca25481.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2_5", + "accent": null, + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/N2lVS1w4EtoT3dr4eOWO/ac833bd8-ffda-4938-9ebc-b0f99ca25481.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2", + "accent": null, + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/N2lVS1w4EtoT3dr4eOWO/ac833bd8-ffda-4938-9ebc-b0f99ca25481.mp3" + }, + { + "language": "fr", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "fr-FR", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/N2lVS1w4EtoT3dr4eOWO/cae55f06-da58-4810-ad48-5e6eb0fe72a9.mp3" + }, + { + "language": "hi", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "hi-IN", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/N2lVS1w4EtoT3dr4eOWO/b4465e6f-051d-4e0b-b588-617ff34de35b.mp3" + } + ], + "safety_control": null, + "voice_verification": { + "requires_verification": false, + "is_verified": false, + "verification_failures": [], + "verification_attempts_count": 0, + "language": null, + "verification_attempts": null + }, + "permission_on_resource": null, + "is_owner": false, + "is_legacy": false, + "is_mixed": false, + "favorited_at_unix": null, + "created_at_unix": null + }, + { + "voice_id": "SAz9YHcvj6GT2YYXdXww", + "name": "River", + "samples": null, + "category": "premade", + "fine_tuning": { + "is_allowed_to_fine_tune": true, + "state": { + "eleven_multilingual_v2": "fine_tuned", + "eleven_turbo_v2_5": "fine_tuned", + "eleven_flash_v2_5": "fine_tuned", + "eleven_v2_flash": "fine_tuned", + "eleven_v2_5_flash": "fine_tuned", + "eleven_multilingual_sts_v2": "fine_tuned", + "eleven_flash_v2": "fine_tuned", + "eleven_turbo_v2": "fine_tuned" + }, + "verification_failures": [], + "verification_attempts_count": 0, + "manual_verification_requested": false, + "language": "en", + "progress": { + "eleven_flash_v2_5": 1, + "eleven_v2_flash": 1, + "eleven_flash_v2": 1, + "eleven_v2_5_flash": 1 + }, + "message": { + "eleven_flash_v2_5": "Done!", + "eleven_v2_flash": "Done!", + "eleven_flash_v2": "Done!", + "eleven_v2_5_flash": "Done!" + }, + "dataset_duration_seconds": null, + "verification_attempts": null, + "slice_ids": null, + "manual_verification": null, + "max_verification_attempts": 5, + "next_max_verification_attempts_reset_unix_ms": 1700000000000 + }, + "labels": { + "accent": "american", + "descriptive": "calm", + "age": "middle_aged", + "gender": "neutral", + "language": "en", + "use_case": "conversational" + }, + "description": "A relaxed, neutral voice ready for narrations or conversational projects.", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/SAz9YHcvj6GT2YYXdXww/e6c95f0b-2227-491a-b3d7-2249240decb7.mp3", + "available_for_tiers": [], + "settings": null, + "sharing": null, + "high_quality_base_model_ids": [ + "eleven_v2_flash", + "eleven_flash_v2", + "eleven_turbo_v2_5", + "eleven_multilingual_sts_v2", + "eleven_multilingual_v2", + "eleven_v2_5_flash", + "eleven_flash_v2_5", + "eleven_turbo_v2" + ], + "verified_languages": [ + { + "language": "en", + "model_id": "eleven_v2_flash", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/SAz9YHcvj6GT2YYXdXww/e6c95f0b-2227-491a-b3d7-2249240decb7.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/SAz9YHcvj6GT2YYXdXww/e6c95f0b-2227-491a-b3d7-2249240decb7.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2_5", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/SAz9YHcvj6GT2YYXdXww/e6c95f0b-2227-491a-b3d7-2249240decb7.mp3" + }, + { + "language": "en", + "model_id": "eleven_multilingual_sts_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/SAz9YHcvj6GT2YYXdXww/e6c95f0b-2227-491a-b3d7-2249240decb7.mp3" + }, + { + "language": "en", + "model_id": "eleven_multilingual_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/SAz9YHcvj6GT2YYXdXww/e6c95f0b-2227-491a-b3d7-2249240decb7.mp3" + }, + { + "language": "en", + "model_id": "eleven_v2_5_flash", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/SAz9YHcvj6GT2YYXdXww/e6c95f0b-2227-491a-b3d7-2249240decb7.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2_5", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/SAz9YHcvj6GT2YYXdXww/e6c95f0b-2227-491a-b3d7-2249240decb7.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/SAz9YHcvj6GT2YYXdXww/e6c95f0b-2227-491a-b3d7-2249240decb7.mp3" + }, + { + "language": "it", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "it-IT", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/SAz9YHcvj6GT2YYXdXww/62da5f17-c5cb-48bb-ad7c-e0b7623d16cc.mp3" + }, + { + "language": "fr", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "fr-FR", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/SAz9YHcvj6GT2YYXdXww/cd628aed-b6a3-463a-b96f-1e7eebd34f04.mp3" + }, + { + "language": "pt", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": null, + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/SAz9YHcvj6GT2YYXdXww/81a2500f-c016-4ca1-a9b9-09ab065a084f.mp3" + }, + { + "language": "zh", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "cmn-CN", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/SAz9YHcvj6GT2YYXdXww/cf733b36-9256-4224-9890-20c67ada259c.mp3" + } + ], + "safety_control": null, + "voice_verification": { + "requires_verification": false, + "is_verified": false, + "verification_failures": [], + "verification_attempts_count": 0, + "language": null, + "verification_attempts": null + }, + "permission_on_resource": null, + "is_owner": false, + "is_legacy": false, + "is_mixed": false, + "favorited_at_unix": null, + "created_at_unix": null + }, + { + "voice_id": "SOYHLrjzK2X1ezoPC6cr", + "name": "Harry", + "samples": null, + "category": "premade", + "fine_tuning": { + "is_allowed_to_fine_tune": true, + "state": { + "eleven_flash_v2_5": "fine_tuned", + "eleven_turbo_v2": "fine_tuned", + "eleven_flash_v2": "fine_tuned", + "eleven_v2_flash": "fine_tuned", + "eleven_v2_5_flash": "fine_tuned" + }, + "verification_failures": [], + "verification_attempts_count": 0, + "manual_verification_requested": false, + "language": "en", + "progress": { + "eleven_flash_v2_5": 1, + "eleven_v2_flash": 1, + "eleven_flash_v2": 1, + "eleven_v2_5_flash": 1 + }, + "message": { + "eleven_multilingual_v2": "", + "eleven_turbo_v2_5": "", + "eleven_flash_v2_5": "Done!", + "eleven_v2_flash": "Done!", + "eleven_v2_5_flash": "Done!", + "eleven_turbo_v2": "", + "eleven_flash_v2": "Done!" + }, + "dataset_duration_seconds": null, + "verification_attempts": null, + "slice_ids": null, + "manual_verification": null, + "max_verification_attempts": 5, + "next_max_verification_attempts_reset_unix_ms": 1700000000000 + }, + "labels": { + "accent": "american", + "descriptive": "rough", + "age": "young", + "gender": "male", + "language": "en", + "use_case": "characters_animation" + }, + "description": "An animated warrior ready to charge forward.", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/SOYHLrjzK2X1ezoPC6cr/86d178f6-f4b6-4e0e-85be-3de19f490794.mp3", + "available_for_tiers": [], + "settings": null, + "sharing": null, + "high_quality_base_model_ids": [ + "eleven_v2_flash", + "eleven_flash_v2", + "eleven_turbo_v2_5", + "eleven_multilingual_v2", + "eleven_multilingual_v1", + "eleven_v2_5_flash", + "eleven_flash_v2_5", + "eleven_turbo_v2" + ], + "verified_languages": [ + { + "language": "en", + "model_id": "eleven_v2_flash", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/SOYHLrjzK2X1ezoPC6cr/86d178f6-f4b6-4e0e-85be-3de19f490794.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/SOYHLrjzK2X1ezoPC6cr/86d178f6-f4b6-4e0e-85be-3de19f490794.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2_5", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/SOYHLrjzK2X1ezoPC6cr/86d178f6-f4b6-4e0e-85be-3de19f490794.mp3" + }, + { + "language": "en", + "model_id": "eleven_multilingual_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/SOYHLrjzK2X1ezoPC6cr/86d178f6-f4b6-4e0e-85be-3de19f490794.mp3" + }, + { + "language": "en", + "model_id": "promade_v1", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/SOYHLrjzK2X1ezoPC6cr/86d178f6-f4b6-4e0e-85be-3de19f490794.mp3" + }, + { + "language": "en", + "model_id": "eleven_v2_5_flash", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/SOYHLrjzK2X1ezoPC6cr/86d178f6-f4b6-4e0e-85be-3de19f490794.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2_5", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/SOYHLrjzK2X1ezoPC6cr/86d178f6-f4b6-4e0e-85be-3de19f490794.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/SOYHLrjzK2X1ezoPC6cr/86d178f6-f4b6-4e0e-85be-3de19f490794.mp3" + } + ], + "safety_control": null, + "voice_verification": { + "requires_verification": false, + "is_verified": false, + "verification_failures": [], + "verification_attempts_count": 0, + "language": null, + "verification_attempts": null + }, + "permission_on_resource": null, + "is_owner": false, + "is_legacy": false, + "is_mixed": false, + "favorited_at_unix": null, + "created_at_unix": null + }, + { + "voice_id": "TX3LPaxmHKxFdv7VOQHJ", + "name": "Liam", + "samples": null, + "category": "premade", + "fine_tuning": { + "is_allowed_to_fine_tune": true, + "state": { + "eleven_turbo_v2": "fine_tuned", + "eleven_v2_flash": "fine_tuned", + "eleven_v2_5_flash": "fine_tuned" + }, + "verification_failures": [], + "verification_attempts_count": 0, + "manual_verification_requested": false, + "language": "en", + "progress": { + "eleven_v2_flash": 1, + "eleven_v2_5_flash": 1 + }, + "message": { + "eleven_turbo_v2": "", + "eleven_v2_flash": "Done!", + "eleven_v2_5_flash": "Done!" + }, + "dataset_duration_seconds": null, + "verification_attempts": null, + "slice_ids": null, + "manual_verification": null, + "max_verification_attempts": 5, + "next_max_verification_attempts_reset_unix_ms": 1700000000000 + }, + "labels": { + "accent": "american", + "descriptive": "confident", + "age": "young", + "gender": "male", + "language": "en", + "use_case": "social_media" + }, + "description": "A young adult with energy and warmth - suitable for reels and shorts.", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/TX3LPaxmHKxFdv7VOQHJ/63148076-6363-42db-aea8-31424308b92c.mp3", + "available_for_tiers": [], + "settings": null, + "sharing": null, + "high_quality_base_model_ids": [ + "eleven_v2_flash", + "eleven_flash_v2", + "eleven_turbo_v2_5", + "eleven_multilingual_v2", + "eleven_multilingual_v1", + "eleven_v2_5_flash", + "eleven_flash_v2_5", + "eleven_turbo_v2" + ], + "verified_languages": [ + { + "language": "en", + "model_id": "eleven_v2_flash", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/TX3LPaxmHKxFdv7VOQHJ/63148076-6363-42db-aea8-31424308b92c.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/TX3LPaxmHKxFdv7VOQHJ/63148076-6363-42db-aea8-31424308b92c.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2_5", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/TX3LPaxmHKxFdv7VOQHJ/63148076-6363-42db-aea8-31424308b92c.mp3" + }, + { + "language": "en", + "model_id": "eleven_multilingual_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/TX3LPaxmHKxFdv7VOQHJ/63148076-6363-42db-aea8-31424308b92c.mp3" + }, + { + "language": "en", + "model_id": "promade_v1", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/TX3LPaxmHKxFdv7VOQHJ/63148076-6363-42db-aea8-31424308b92c.mp3" + }, + { + "language": "en", + "model_id": "eleven_v2_5_flash", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/TX3LPaxmHKxFdv7VOQHJ/63148076-6363-42db-aea8-31424308b92c.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2_5", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/TX3LPaxmHKxFdv7VOQHJ/63148076-6363-42db-aea8-31424308b92c.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/TX3LPaxmHKxFdv7VOQHJ/63148076-6363-42db-aea8-31424308b92c.mp3" + }, + { + "language": "de", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "de-DE", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/TX3LPaxmHKxFdv7VOQHJ/9d63d255-b011-4231-a945-fd5a64d94bfc.mp3" + }, + { + "language": "pt", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": null, + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/TX3LPaxmHKxFdv7VOQHJ/56d7e6ac-b450-48e0-ba68-ff47921b7241.mp3" + }, + { + "language": "cs", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "cs-CZ", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/TX3LPaxmHKxFdv7VOQHJ/e87b9bfb-9aee-4106-ad72-81b6982dea22.mp3" + }, + { + "language": "pl", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "pl-PL", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/TX3LPaxmHKxFdv7VOQHJ/0100273d-0f0e-4560-9803-84af8f7e8809.mp3" + }, + { + "language": "tr", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "tr-TR", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/TX3LPaxmHKxFdv7VOQHJ/172d9bf5-8094-4438-b06f-b382ead09a2f.mp3" + }, + { + "language": "hi", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "hi-IN", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/TX3LPaxmHKxFdv7VOQHJ/437fbcd7-782a-42c0-b813-307a2e5089d6.mp3" + } + ], + "safety_control": null, + "voice_verification": { + "requires_verification": false, + "is_verified": false, + "verification_failures": [], + "verification_attempts_count": 0, + "language": null, + "verification_attempts": null + }, + "permission_on_resource": null, + "is_owner": false, + "is_legacy": false, + "is_mixed": false, + "favorited_at_unix": null, + "created_at_unix": null + }, + { + "voice_id": "Xb7hH8MSUJpSbSDYk0k2", + "name": "Alice", + "samples": null, + "category": "premade", + "fine_tuning": { + "is_allowed_to_fine_tune": true, + "state": { + "eleven_flash_v2_5": "fine_tuned", + "eleven_turbo_v2": "fine_tuned", + "eleven_flash_v2": "fine_tuned", + "eleven_v2_flash": "fine_tuned", + "eleven_v2_5_flash": "fine_tuned" + }, + "verification_failures": [], + "verification_attempts_count": 0, + "manual_verification_requested": false, + "language": "en", + "progress": { + "eleven_flash_v2_5": 1, + "eleven_v2_flash": 1, + "eleven_flash_v2": 1, + "eleven_v2_5_flash": 1 + }, + "message": { + "eleven_flash_v2_5": "Done!", + "eleven_turbo_v2": "", + "eleven_flash_v2": "Done!", + "eleven_v2_flash": "Done!", + "eleven_v2_5_flash": "Done!" + }, + "dataset_duration_seconds": null, + "verification_attempts": null, + "slice_ids": null, + "manual_verification": null, + "max_verification_attempts": 5, + "next_max_verification_attempts_reset_unix_ms": 1700000000000 + }, + "labels": { + "accent": "british", + "descriptive": "professional", + "age": "middle_aged", + "gender": "female", + "language": "en", + "use_case": "advertisement" + }, + "description": "Clear and engaging, friendly woman with a British accent suitable for e-learning.", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/Xb7hH8MSUJpSbSDYk0k2/d10f7534-11f6-41fe-a012-2de1e482d336.mp3", + "available_for_tiers": [], + "settings": null, + "sharing": null, + "high_quality_base_model_ids": [ + "eleven_v2_flash", + "eleven_flash_v2", + "eleven_turbo_v2_5", + "eleven_multilingual_v2", + "eleven_v2_5_flash", + "eleven_flash_v2_5", + "eleven_turbo_v2" + ], + "verified_languages": [ + { + "language": "en", + "model_id": "eleven_v2_flash", + "accent": "british", + "locale": "en-GB", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/Xb7hH8MSUJpSbSDYk0k2/d10f7534-11f6-41fe-a012-2de1e482d336.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2", + "accent": "british", + "locale": "en-GB", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/Xb7hH8MSUJpSbSDYk0k2/d10f7534-11f6-41fe-a012-2de1e482d336.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2_5", + "accent": "british", + "locale": "en-GB", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/Xb7hH8MSUJpSbSDYk0k2/d10f7534-11f6-41fe-a012-2de1e482d336.mp3" + }, + { + "language": "en", + "model_id": "eleven_multilingual_v2", + "accent": "british", + "locale": "en-GB", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/Xb7hH8MSUJpSbSDYk0k2/d10f7534-11f6-41fe-a012-2de1e482d336.mp3" + }, + { + "language": "en", + "model_id": "eleven_v2_5_flash", + "accent": "british", + "locale": "en-GB", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/Xb7hH8MSUJpSbSDYk0k2/d10f7534-11f6-41fe-a012-2de1e482d336.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2_5", + "accent": "british", + "locale": "en-GB", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/Xb7hH8MSUJpSbSDYk0k2/d10f7534-11f6-41fe-a012-2de1e482d336.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2", + "accent": "british", + "locale": "en-GB", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/Xb7hH8MSUJpSbSDYk0k2/d10f7534-11f6-41fe-a012-2de1e482d336.mp3" + }, + { + "language": "it", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "it-IT", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/Xb7hH8MSUJpSbSDYk0k2/5cb52c82-8152-47f0-a959-58df75b33fac.mp3" + }, + { + "language": "fr", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "fr-FR", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/Xb7hH8MSUJpSbSDYk0k2/8078faa3-8ac4-4e55-b9ae-2d43a17fba42.mp3" + }, + { + "language": "ar", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": null, + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/Xb7hH8MSUJpSbSDYk0k2/0d220e32-be6e-42b5-b478-38dd287887c8.mp3" + }, + { + "language": "ja", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "ja-JP", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/Xb7hH8MSUJpSbSDYk0k2/290e5e0e-485a-4206-9f86-b687eed71132.mp3" + }, + { + "language": "pl", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "pl-PL", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/Xb7hH8MSUJpSbSDYk0k2/bed01e1d-3dec-4c78-bb58-c3e7299cec23.mp3" + }, + { + "language": "hi", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "hi-IN", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/Xb7hH8MSUJpSbSDYk0k2/063f6922-9fc5-44d7-b9ca-d5b0ed6eeb98.mp3" + } + ], + "safety_control": null, + "voice_verification": { + "requires_verification": false, + "is_verified": false, + "verification_failures": [], + "verification_attempts_count": 0, + "language": null, + "verification_attempts": null + }, + "permission_on_resource": null, + "is_owner": false, + "is_legacy": false, + "is_mixed": false, + "favorited_at_unix": null, + "created_at_unix": null + }, + { + "voice_id": "XrExE9yKIg1WjnnlVkGX", + "name": "Matilda", + "samples": null, + "category": "premade", + "fine_tuning": { + "is_allowed_to_fine_tune": true, + "state": { + "eleven_turbo_v2": "fine_tuned", + "eleven_v2_flash": "fine_tuned", + "eleven_v2_5_flash": "fine_tuned" + }, + "verification_failures": [], + "verification_attempts_count": 0, + "manual_verification_requested": false, + "language": "en", + "progress": { + "eleven_v2_flash": 1, + "eleven_v2_5_flash": 1 + }, + "message": { + "eleven_turbo_v2": "", + "eleven_v2_flash": "Done!", + "eleven_v2_5_flash": "Done!" + }, + "dataset_duration_seconds": null, + "verification_attempts": null, + "slice_ids": null, + "manual_verification": null, + "max_verification_attempts": 5, + "next_max_verification_attempts_reset_unix_ms": 1700000000000 + }, + "labels": { + "accent": "american", + "descriptive": "upbeat", + "age": "middle_aged", + "gender": "female", + "language": "en", + "use_case": "informative_educational" + }, + "description": "A professional woman with a pleasing alto pitch. Suitable for many use cases.", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/XrExE9yKIg1WjnnlVkGX/b930e18d-6b4d-466e-bab2-0ae97c6d8535.mp3", + "available_for_tiers": [], + "settings": null, + "sharing": null, + "high_quality_base_model_ids": [ + "eleven_v2_flash", + "eleven_flash_v2", + "eleven_turbo_v2_5", + "eleven_multilingual_v2", + "eleven_multilingual_v1", + "eleven_v2_5_flash", + "eleven_flash_v2_5", + "eleven_turbo_v2" + ], + "verified_languages": [ + { + "language": "en", + "model_id": "eleven_v2_flash", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/XrExE9yKIg1WjnnlVkGX/b930e18d-6b4d-466e-bab2-0ae97c6d8535.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/XrExE9yKIg1WjnnlVkGX/b930e18d-6b4d-466e-bab2-0ae97c6d8535.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2_5", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/XrExE9yKIg1WjnnlVkGX/b930e18d-6b4d-466e-bab2-0ae97c6d8535.mp3" + }, + { + "language": "en", + "model_id": "eleven_multilingual_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/XrExE9yKIg1WjnnlVkGX/b930e18d-6b4d-466e-bab2-0ae97c6d8535.mp3" + }, + { + "language": "en", + "model_id": "promade_v1", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/XrExE9yKIg1WjnnlVkGX/b930e18d-6b4d-466e-bab2-0ae97c6d8535.mp3" + }, + { + "language": "en", + "model_id": "eleven_v2_5_flash", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/XrExE9yKIg1WjnnlVkGX/b930e18d-6b4d-466e-bab2-0ae97c6d8535.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2_5", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/XrExE9yKIg1WjnnlVkGX/b930e18d-6b4d-466e-bab2-0ae97c6d8535.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/XrExE9yKIg1WjnnlVkGX/b930e18d-6b4d-466e-bab2-0ae97c6d8535.mp3" + }, + { + "language": "it", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "it-IT", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/XrExE9yKIg1WjnnlVkGX/68da6da6-38b0-4de9-b941-1345c4503948.mp3" + }, + { + "language": "fr", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "fr-FR", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/XrExE9yKIg1WjnnlVkGX/40f2148b-d09e-4f24-97b6-66aafef1b0bb.mp3" + }, + { + "language": "de", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "de-DE", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/XrExE9yKIg1WjnnlVkGX/9d8aab27-268f-4fea-9815-7da3938539d1.mp3" + }, + { + "language": "ar", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": null, + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/XrExE9yKIg1WjnnlVkGX/3c5bb9c4-a406-4d10-b61d-275c18e84f26.mp3" + }, + { + "language": "es", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": null, + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/XrExE9yKIg1WjnnlVkGX/20291a6d-1e7f-45e4-9d85-a764997a2fdb.mp3" + } + ], + "safety_control": null, + "voice_verification": { + "requires_verification": false, + "is_verified": false, + "verification_failures": [], + "verification_attempts_count": 0, + "language": null, + "verification_attempts": null + }, + "permission_on_resource": null, + "is_owner": false, + "is_legacy": false, + "is_mixed": false, + "favorited_at_unix": null, + "created_at_unix": null + }, + { + "voice_id": "bIHbv24MWmeRgasZH58o", + "name": "Will", + "samples": null, + "category": "premade", + "fine_tuning": { + "is_allowed_to_fine_tune": true, + "state": { + "eleven_multilingual_v2": "fine_tuned", + "eleven_turbo_v2_5": "fine_tuned", + "eleven_flash_v2_5": "fine_tuned", + "eleven_v2_flash": "fine_tuned", + "eleven_v2_5_flash": "fine_tuned", + "eleven_turbo_v2": "fine_tuned", + "eleven_flash_v2": "fine_tuned" + }, + "verification_failures": [], + "verification_attempts_count": 0, + "manual_verification_requested": false, + "language": "en", + "progress": { + "eleven_flash_v2_5": 1, + "eleven_v2_flash": 1, + "eleven_flash_v2": 1, + "eleven_v2_5_flash": 1 + }, + "message": { + "eleven_flash_v2_5": "Done!", + "eleven_v2_flash": "Done!", + "eleven_flash_v2": "Done!", + "eleven_v2_5_flash": "Done!" + }, + "dataset_duration_seconds": null, + "verification_attempts": null, + "slice_ids": null, + "manual_verification": null, + "max_verification_attempts": 5, + "next_max_verification_attempts_reset_unix_ms": 1700000000000 + }, + "labels": { + "accent": "american", + "descriptive": "chill", + "age": "young", + "gender": "male", + "language": "en", + "use_case": "conversational" + }, + "description": "Conversational and laid back.", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/bIHbv24MWmeRgasZH58o/8caf8f3d-ad29-4980-af41-53f20c72d7a4.mp3", + "available_for_tiers": [], + "settings": null, + "sharing": null, + "high_quality_base_model_ids": [ + "eleven_v2_flash", + "eleven_flash_v2", + "eleven_turbo_v2_5", + "eleven_multilingual_v2", + "eleven_v2_5_flash", + "eleven_flash_v2_5", + "eleven_turbo_v2" + ], + "verified_languages": [ + { + "language": "en", + "model_id": "eleven_v2_flash", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/bIHbv24MWmeRgasZH58o/8caf8f3d-ad29-4980-af41-53f20c72d7a4.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/bIHbv24MWmeRgasZH58o/8caf8f3d-ad29-4980-af41-53f20c72d7a4.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2_5", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/bIHbv24MWmeRgasZH58o/8caf8f3d-ad29-4980-af41-53f20c72d7a4.mp3" + }, + { + "language": "en", + "model_id": "eleven_multilingual_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/bIHbv24MWmeRgasZH58o/8caf8f3d-ad29-4980-af41-53f20c72d7a4.mp3" + }, + { + "language": "en", + "model_id": "eleven_v2_5_flash", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/bIHbv24MWmeRgasZH58o/8caf8f3d-ad29-4980-af41-53f20c72d7a4.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2_5", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/bIHbv24MWmeRgasZH58o/8caf8f3d-ad29-4980-af41-53f20c72d7a4.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/bIHbv24MWmeRgasZH58o/8caf8f3d-ad29-4980-af41-53f20c72d7a4.mp3" + }, + { + "language": "fr", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "fr-FR", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/bIHbv24MWmeRgasZH58o/a46e8450-1b81-4370-adbc-f6b504a409ad.mp3" + }, + { + "language": "de", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "de-DE", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/bIHbv24MWmeRgasZH58o/20efefbb-9e19-4808-97f1-9c7ae0eebf7b.mp3" + }, + { + "language": "pt", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": null, + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/bIHbv24MWmeRgasZH58o/8e6ace43-9e5a-413d-a491-2ec365e0a2ae.mp3" + }, + { + "language": "zh", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "cmn-CN", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/bIHbv24MWmeRgasZH58o/2c7ea680-0d76-4ac5-a77a-765e59417560.mp3" + }, + { + "language": "cs", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "cs-CZ", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/bIHbv24MWmeRgasZH58o/b6b630a8-eda6-4972-a527-bfcde1df0b7c.mp3" + }, + { + "language": "fil", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "fil-PH", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/bIHbv24MWmeRgasZH58o/7890ca34-065a-4d2f-a2db-2102909c96a4.mp3" + }, + { + "language": "sk", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "sk-SK", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/bIHbv24MWmeRgasZH58o/3dc86617-878a-4964-a464-3b9d39113d2a.mp3" + }, + { + "language": "es", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": null, + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/bIHbv24MWmeRgasZH58o/9b17b1ba-98f6-4c6d-9da7-dc03a76bc50c.mp3" + }, + { + "language": "sv", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "sv-SE", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/bIHbv24MWmeRgasZH58o/090d5fe3-c80a-4990-b536-e83f33d23fe1.mp3" + } + ], + "safety_control": null, + "voice_verification": { + "requires_verification": false, + "is_verified": false, + "verification_failures": [], + "verification_attempts_count": 0, + "language": null, + "verification_attempts": null + }, + "permission_on_resource": null, + "is_owner": false, + "is_legacy": false, + "is_mixed": false, + "favorited_at_unix": null, + "created_at_unix": null + }, + { + "voice_id": "cgSgspJ2msm6clMCkdW9", + "name": "Jessica", + "samples": null, + "category": "premade", + "fine_tuning": { + "is_allowed_to_fine_tune": true, + "state": { + "eleven_multilingual_v2": "fine_tuned", + "eleven_turbo_v2_5": "fine_tuned", + "eleven_flash_v2_5": "fine_tuned", + "eleven_v2_flash": "fine_tuned", + "eleven_v2_5_flash": "fine_tuned", + "eleven_turbo_v2": "fine_tuned", + "eleven_flash_v2": "fine_tuned" + }, + "verification_failures": [], + "verification_attempts_count": 0, + "manual_verification_requested": false, + "language": "en", + "progress": { + "eleven_flash_v2_5": 1, + "eleven_v2_flash": 1, + "eleven_flash_v2": 1, + "eleven_v2_5_flash": 1 + }, + "message": { + "eleven_flash_v2_5": "Done!", + "eleven_v2_flash": "Done!", + "eleven_flash_v2": "Done!", + "eleven_v2_5_flash": "Done!" + }, + "dataset_duration_seconds": null, + "verification_attempts": null, + "slice_ids": null, + "manual_verification": null, + "max_verification_attempts": 5, + "next_max_verification_attempts_reset_unix_ms": 1700000000000 + }, + "labels": { + "accent": "american", + "descriptive": "cute", + "age": "young", + "gender": "female", + "language": "en", + "use_case": "conversational" + }, + "description": "Young and popular, this playful American female voice is perfect for trendy content.", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/cgSgspJ2msm6clMCkdW9/56a97bf8-b69b-448f-846c-c3a11683d45a.mp3", + "available_for_tiers": [], + "settings": null, + "sharing": null, + "high_quality_base_model_ids": [ + "eleven_v2_flash", + "eleven_flash_v2", + "eleven_turbo_v2_5", + "eleven_multilingual_v2", + "eleven_v2_5_flash", + "eleven_flash_v2_5", + "eleven_turbo_v2" + ], + "verified_languages": [ + { + "language": "en", + "model_id": "eleven_v2_flash", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/cgSgspJ2msm6clMCkdW9/56a97bf8-b69b-448f-846c-c3a11683d45a.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/cgSgspJ2msm6clMCkdW9/56a97bf8-b69b-448f-846c-c3a11683d45a.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2_5", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/cgSgspJ2msm6clMCkdW9/56a97bf8-b69b-448f-846c-c3a11683d45a.mp3" + }, + { + "language": "en", + "model_id": "eleven_multilingual_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/cgSgspJ2msm6clMCkdW9/56a97bf8-b69b-448f-846c-c3a11683d45a.mp3" + }, + { + "language": "en", + "model_id": "eleven_v2_5_flash", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/cgSgspJ2msm6clMCkdW9/56a97bf8-b69b-448f-846c-c3a11683d45a.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2_5", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/cgSgspJ2msm6clMCkdW9/56a97bf8-b69b-448f-846c-c3a11683d45a.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/cgSgspJ2msm6clMCkdW9/56a97bf8-b69b-448f-846c-c3a11683d45a.mp3" + }, + { + "language": "fr", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "fr-FR", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/cgSgspJ2msm6clMCkdW9/83ed5b34-be48-4473-93f8-58633129bc87.mp3" + }, + { + "language": "ar", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": null, + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/cgSgspJ2msm6clMCkdW9/114425d8-26e7-4b3d-aa31-52ab8bbdcbed.mp3" + }, + { + "language": "ja", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "ja-JP", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/cgSgspJ2msm6clMCkdW9/a4011375-88c2-4469-a61b-96b0fb239caf.mp3" + }, + { + "language": "zh", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "cmn-CN", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/cgSgspJ2msm6clMCkdW9/6f4a6924-34c9-465a-9017-707f7e823e24.mp3" + }, + { + "language": "de", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "de-DE", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/cgSgspJ2msm6clMCkdW9/eb773c99-fcf2-4f0c-ace5-84dc43880c34.mp3" + }, + { + "language": "cs", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "cs-CZ", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/cgSgspJ2msm6clMCkdW9/9fdd6daa-383a-47b8-97be-fbec0cfbe4e2.mp3" + }, + { + "language": "hi", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "hi-IN", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/cgSgspJ2msm6clMCkdW9/3a9a4248-9eb3-4e12-8823-f3766c3fd48f.mp3" + } + ], + "safety_control": null, + "voice_verification": { + "requires_verification": false, + "is_verified": false, + "verification_failures": [], + "verification_attempts_count": 0, + "language": null, + "verification_attempts": null + }, + "permission_on_resource": null, + "is_owner": false, + "is_legacy": false, + "is_mixed": false, + "favorited_at_unix": null, + "created_at_unix": null + }, + { + "voice_id": "cjVigY5qzO86Huf0OWal", + "name": "Eric", + "samples": null, + "category": "premade", + "fine_tuning": { + "is_allowed_to_fine_tune": true, + "state": { + "eleven_multilingual_v2": "fine_tuned", + "eleven_turbo_v2_5": "fine_tuned", + "eleven_flash_v2_5": "fine_tuned", + "eleven_v2_flash": "fine_tuned", + "eleven_v2_5_flash": "fine_tuned", + "eleven_turbo_v2": "fine_tuned", + "eleven_flash_v2": "fine_tuned" + }, + "verification_failures": [], + "verification_attempts_count": 0, + "manual_verification_requested": false, + "language": "en", + "progress": { + "eleven_flash_v2_5": 1, + "eleven_v2_flash": 1, + "eleven_flash_v2": 1, + "eleven_v2_5_flash": 1 + }, + "message": { + "eleven_flash_v2_5": "Done!", + "eleven_v2_flash": "Done!", + "eleven_flash_v2": "Done!", + "eleven_v2_5_flash": "Done!" + }, + "dataset_duration_seconds": null, + "verification_attempts": null, + "slice_ids": null, + "manual_verification": null, + "max_verification_attempts": 5, + "next_max_verification_attempts_reset_unix_ms": 1700000000000 + }, + "labels": { + "accent": "american", + "descriptive": "classy", + "age": "middle_aged", + "gender": "male", + "language": "en", + "use_case": "conversational" + }, + "description": "A smooth tenor pitch from a man in his 40s - perfect for agentic use cases.", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/cjVigY5qzO86Huf0OWal/d098fda0-6456-4030-b3d8-63aa048c9070.mp3", + "available_for_tiers": [], + "settings": null, + "sharing": null, + "high_quality_base_model_ids": [ + "eleven_v2_flash", + "eleven_flash_v2", + "eleven_turbo_v2_5", + "eleven_multilingual_v2", + "eleven_v2_5_flash", + "eleven_flash_v2_5", + "eleven_turbo_v2" + ], + "verified_languages": [ + { + "language": "en", + "model_id": "eleven_v2_flash", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/cjVigY5qzO86Huf0OWal/d098fda0-6456-4030-b3d8-63aa048c9070.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/cjVigY5qzO86Huf0OWal/d098fda0-6456-4030-b3d8-63aa048c9070.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2_5", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/cjVigY5qzO86Huf0OWal/d098fda0-6456-4030-b3d8-63aa048c9070.mp3" + }, + { + "language": "en", + "model_id": "eleven_multilingual_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/cjVigY5qzO86Huf0OWal/d098fda0-6456-4030-b3d8-63aa048c9070.mp3" + }, + { + "language": "en", + "model_id": "eleven_v2_5_flash", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/cjVigY5qzO86Huf0OWal/d098fda0-6456-4030-b3d8-63aa048c9070.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2_5", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/cjVigY5qzO86Huf0OWal/d098fda0-6456-4030-b3d8-63aa048c9070.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/cjVigY5qzO86Huf0OWal/d098fda0-6456-4030-b3d8-63aa048c9070.mp3" + }, + { + "language": "fr", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "fr-FR", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/cjVigY5qzO86Huf0OWal/4c076868-22c6-42a6-9edd-b836f6a33f9f.mp3" + }, + { + "language": "pt", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": null, + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/cjVigY5qzO86Huf0OWal/c893545f-603a-4023-ae26-0b779ab9e8c2.mp3" + }, + { + "language": "de", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "de-DE", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/cjVigY5qzO86Huf0OWal/e8e9e810-3ef3-4992-a61f-4a43279b6909.mp3" + }, + { + "language": "sk", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "sk-SK", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/cjVigY5qzO86Huf0OWal/99655517-0f65-49b4-8d88-bd2a40821e65.mp3" + }, + { + "language": "es", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": null, + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/cjVigY5qzO86Huf0OWal/4d56a844-3fc5-4048-b8d9-daff582c2746.mp3" + } + ], + "safety_control": null, + "voice_verification": { + "requires_verification": false, + "is_verified": false, + "verification_failures": [], + "verification_attempts_count": 0, + "language": null, + "verification_attempts": null + }, + "permission_on_resource": null, + "is_owner": false, + "is_legacy": false, + "is_mixed": false, + "favorited_at_unix": null, + "created_at_unix": null + }, + { + "voice_id": "iP95p4xoKVk53GoZ742B", + "name": "Chris", + "samples": null, + "category": "premade", + "fine_tuning": { + "is_allowed_to_fine_tune": true, + "state": { + "eleven_flash_v2_5": "fine_tuned", + "eleven_turbo_v2": "fine_tuned", + "eleven_flash_v2": "fine_tuned", + "eleven_v2_flash": "fine_tuned", + "eleven_v2_5_flash": "fine_tuned" + }, + "verification_failures": [], + "verification_attempts_count": 0, + "manual_verification_requested": false, + "language": "en", + "progress": { + "eleven_flash_v2_5": 1, + "eleven_v2_flash": 1, + "eleven_flash_v2": 1, + "eleven_v2_5_flash": 1 + }, + "message": { + "eleven_flash_v2_5": "Done!", + "eleven_turbo_v2": "", + "eleven_flash_v2": "Done!", + "eleven_v2_flash": "Done!", + "eleven_v2_5_flash": "Done!" + }, + "dataset_duration_seconds": null, + "verification_attempts": null, + "slice_ids": null, + "manual_verification": null, + "max_verification_attempts": 5, + "next_max_verification_attempts_reset_unix_ms": 1700000000000 + }, + "labels": { + "accent": "american", + "descriptive": "casual", + "age": "middle_aged", + "gender": "male", + "language": "en", + "use_case": "conversational" + }, + "description": "Natural and real, this down-to-earth voice is great across many use-cases.", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/iP95p4xoKVk53GoZ742B/3f4bde72-cc48-40dd-829f-57fbf906f4d7.mp3", + "available_for_tiers": [], + "settings": null, + "sharing": null, + "high_quality_base_model_ids": [ + "eleven_v2_flash", + "eleven_flash_v2", + "eleven_turbo_v2_5", + "eleven_multilingual_v2", + "eleven_v2_5_flash", + "eleven_flash_v2_5", + "eleven_turbo_v2" + ], + "verified_languages": [ + { + "language": "en", + "model_id": "eleven_v2_flash", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/iP95p4xoKVk53GoZ742B/3f4bde72-cc48-40dd-829f-57fbf906f4d7.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/iP95p4xoKVk53GoZ742B/3f4bde72-cc48-40dd-829f-57fbf906f4d7.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2_5", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/iP95p4xoKVk53GoZ742B/3f4bde72-cc48-40dd-829f-57fbf906f4d7.mp3" + }, + { + "language": "en", + "model_id": "eleven_multilingual_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/iP95p4xoKVk53GoZ742B/3f4bde72-cc48-40dd-829f-57fbf906f4d7.mp3" + }, + { + "language": "en", + "model_id": "eleven_v2_5_flash", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/iP95p4xoKVk53GoZ742B/3f4bde72-cc48-40dd-829f-57fbf906f4d7.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2_5", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/iP95p4xoKVk53GoZ742B/3f4bde72-cc48-40dd-829f-57fbf906f4d7.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/iP95p4xoKVk53GoZ742B/3f4bde72-cc48-40dd-829f-57fbf906f4d7.mp3" + }, + { + "language": "fr", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "fr-FR", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/iP95p4xoKVk53GoZ742B/34ab53c0-7f77-4624-a26b-65b58394ea69.mp3" + }, + { + "language": "ar", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": null, + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/iP95p4xoKVk53GoZ742B/ffdde76f-4afa-4933-94fc-6c015b4b497e.mp3" + }, + { + "language": "pt", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": null, + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/iP95p4xoKVk53GoZ742B/00131b8d-38d7-4f63-91ed-91ddbe227a7d.mp3" + }, + { + "language": "sv", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "sv-SE", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/iP95p4xoKVk53GoZ742B/8710d1a0-bea3-41c9-a051-e5a4593f6a32.mp3" + }, + { + "language": "hi", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "hi-IN", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/iP95p4xoKVk53GoZ742B/a0a92736-9321-4bbc-9677-c84b84d3f30b.mp3" + } + ], + "safety_control": null, + "voice_verification": { + "requires_verification": false, + "is_verified": false, + "verification_failures": [], + "verification_attempts_count": 0, + "language": null, + "verification_attempts": null + }, + "permission_on_resource": null, + "is_owner": false, + "is_legacy": false, + "is_mixed": false, + "favorited_at_unix": null, + "created_at_unix": null + }, + { + "voice_id": "nPczCjzI2devNBz1zQrb", + "name": "Brian", + "samples": null, + "category": "premade", + "fine_tuning": { + "is_allowed_to_fine_tune": true, + "state": { + "eleven_flash_v2_5": "fine_tuned", + "eleven_turbo_v2": "fine_tuned", + "eleven_flash_v2": "fine_tuned", + "eleven_v2_flash": "fine_tuned", + "eleven_v2_5_flash": "fine_tuned" + }, + "verification_failures": [], + "verification_attempts_count": 0, + "manual_verification_requested": false, + "language": "en", + "progress": { + "eleven_flash_v2_5": 1, + "eleven_v2_flash": 1, + "eleven_flash_v2": 1, + "eleven_v2_5_flash": 1 + }, + "message": { + "eleven_flash_v2_5": "Done!", + "eleven_turbo_v2": "", + "eleven_flash_v2": "Done!", + "eleven_v2_flash": "Done!", + "eleven_v2_5_flash": "Done!" + }, + "dataset_duration_seconds": null, + "verification_attempts": null, + "slice_ids": null, + "manual_verification": null, + "max_verification_attempts": 5, + "next_max_verification_attempts_reset_unix_ms": 1700000000000 + }, + "labels": { + "accent": "american", + "descriptive": "classy", + "age": "middle_aged", + "gender": "male", + "language": "en", + "use_case": "social_media" + }, + "description": "Middle-aged man with a resonant and comforting tone. Great for narrations and advertisements.", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/nPczCjzI2devNBz1zQrb/2dd3e72c-4fd3-42f1-93ea-abc5d4e5aa1d.mp3", + "available_for_tiers": [], + "settings": null, + "sharing": null, + "high_quality_base_model_ids": [ + "eleven_v2_flash", + "eleven_flash_v2", + "eleven_turbo_v2_5", + "eleven_multilingual_v2", + "eleven_v2_5_flash", + "eleven_flash_v2_5", + "eleven_turbo_v2" + ], + "verified_languages": [ + { + "language": "en", + "model_id": "eleven_v2_flash", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/nPczCjzI2devNBz1zQrb/2dd3e72c-4fd3-42f1-93ea-abc5d4e5aa1d.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/nPczCjzI2devNBz1zQrb/2dd3e72c-4fd3-42f1-93ea-abc5d4e5aa1d.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2_5", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/nPczCjzI2devNBz1zQrb/2dd3e72c-4fd3-42f1-93ea-abc5d4e5aa1d.mp3" + }, + { + "language": "en", + "model_id": "eleven_multilingual_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/nPczCjzI2devNBz1zQrb/2dd3e72c-4fd3-42f1-93ea-abc5d4e5aa1d.mp3" + }, + { + "language": "en", + "model_id": "eleven_v2_5_flash", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/nPczCjzI2devNBz1zQrb/2dd3e72c-4fd3-42f1-93ea-abc5d4e5aa1d.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2_5", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/nPczCjzI2devNBz1zQrb/2dd3e72c-4fd3-42f1-93ea-abc5d4e5aa1d.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/nPczCjzI2devNBz1zQrb/2dd3e72c-4fd3-42f1-93ea-abc5d4e5aa1d.mp3" + }, + { + "language": "ar", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": null, + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/nPczCjzI2devNBz1zQrb/e56be0c3-fc89-4529-8248-9726d42175fb.mp3" + }, + { + "language": "zh", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "cmn-CN", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/nPczCjzI2devNBz1zQrb/0bfb8e30-e0e8-44d9-9276-22af13da50b3.mp3" + }, + { + "language": "pt", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": null, + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/nPczCjzI2devNBz1zQrb/7c88e63a-f321-40d6-ac25-899559a3ff26.mp3" + }, + { + "language": "de", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "de-DE", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/nPczCjzI2devNBz1zQrb/0b33b286-75f0-404f-bcec-68a56e6b37e8.mp3" + }, + { + "language": "nl", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "nl-NL", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/nPczCjzI2devNBz1zQrb/d3e8efb2-0c52-4288-85d7-4fde1ea4b9cf.mp3" + }, + { + "language": "sk", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "sk-SK", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/nPczCjzI2devNBz1zQrb/f743b7c8-71b8-447a-9744-d66d11dcabac.mp3" + }, + { + "language": "ro", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "ro-RO", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/nPczCjzI2devNBz1zQrb/75b05b25-29ce-44b8-bbc4-f42600da8c5c.mp3" + }, + { + "language": "hi", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "hi-IN", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/nPczCjzI2devNBz1zQrb/945c1b51-4743-43ae-b0e7-7cab7e08a85e.mp3" + } + ], + "safety_control": null, + "voice_verification": { + "requires_verification": false, + "is_verified": false, + "verification_failures": [], + "verification_attempts_count": 0, + "language": null, + "verification_attempts": null + }, + "permission_on_resource": null, + "is_owner": false, + "is_legacy": false, + "is_mixed": false, + "favorited_at_unix": null, + "created_at_unix": null + }, + { + "voice_id": "onwK4e9ZLuTAKqWW03F9", + "name": "Daniel", + "samples": null, + "category": "premade", + "fine_tuning": { + "is_allowed_to_fine_tune": true, + "state": { + "eleven_flash_v2_5": "fine_tuned", + "eleven_turbo_v2": "fine_tuned", + "eleven_flash_v2": "fine_tuned", + "eleven_v2_flash": "fine_tuned", + "eleven_v2_5_flash": "fine_tuned" + }, + "verification_failures": [], + "verification_attempts_count": 0, + "manual_verification_requested": false, + "language": "en", + "progress": { + "eleven_flash_v2_5": 1, + "eleven_v2_flash": 1, + "eleven_flash_v2": 1, + "eleven_v2_5_flash": 1 + }, + "message": { + "eleven_flash_v2_5": "Done!", + "eleven_turbo_v2": "", + "eleven_flash_v2": "Done!", + "eleven_v2_flash": "Done!", + "eleven_v2_5_flash": "Done!" + }, + "dataset_duration_seconds": null, + "verification_attempts": null, + "slice_ids": null, + "manual_verification": null, + "max_verification_attempts": 5, + "next_max_verification_attempts_reset_unix_ms": 1700000000000 + }, + "labels": { + "accent": "british", + "descriptive": "formal", + "age": "middle_aged", + "gender": "male", + "language": "en", + "use_case": "informative_educational" + }, + "description": "A strong voice perfect for delivering a professional broadcast or news story.", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/onwK4e9ZLuTAKqWW03F9/7eee0236-1a72-4b86-b303-5dcadc007ba9.mp3", + "available_for_tiers": [], + "settings": null, + "sharing": null, + "high_quality_base_model_ids": [ + "eleven_v2_flash", + "eleven_flash_v2", + "eleven_turbo_v2_5", + "eleven_multilingual_v2", + "eleven_multilingual_v1", + "eleven_v2_5_flash", + "eleven_flash_v2_5", + "eleven_turbo_v2" + ], + "verified_languages": [ + { + "language": "en", + "model_id": "eleven_v2_flash", + "accent": "british", + "locale": "en-GB", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/onwK4e9ZLuTAKqWW03F9/7eee0236-1a72-4b86-b303-5dcadc007ba9.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2", + "accent": "british", + "locale": "en-GB", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/onwK4e9ZLuTAKqWW03F9/7eee0236-1a72-4b86-b303-5dcadc007ba9.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2_5", + "accent": "british", + "locale": "en-GB", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/onwK4e9ZLuTAKqWW03F9/7eee0236-1a72-4b86-b303-5dcadc007ba9.mp3" + }, + { + "language": "en", + "model_id": "eleven_multilingual_v2", + "accent": "british", + "locale": "en-GB", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/onwK4e9ZLuTAKqWW03F9/7eee0236-1a72-4b86-b303-5dcadc007ba9.mp3" + }, + { + "language": "en", + "model_id": "promade_v1", + "accent": "british", + "locale": "en-GB", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/onwK4e9ZLuTAKqWW03F9/7eee0236-1a72-4b86-b303-5dcadc007ba9.mp3" + }, + { + "language": "en", + "model_id": "eleven_v2_5_flash", + "accent": "british", + "locale": "en-GB", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/onwK4e9ZLuTAKqWW03F9/7eee0236-1a72-4b86-b303-5dcadc007ba9.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2_5", + "accent": "british", + "locale": "en-GB", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/onwK4e9ZLuTAKqWW03F9/7eee0236-1a72-4b86-b303-5dcadc007ba9.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2", + "accent": "british", + "locale": "en-GB", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/onwK4e9ZLuTAKqWW03F9/7eee0236-1a72-4b86-b303-5dcadc007ba9.mp3" + }, + { + "language": "de", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "de-DE", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/onwK4e9ZLuTAKqWW03F9/7c30c661-8448-4a1e-b7b7-b5b629ec641b.mp3" + }, + { + "language": "tr", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "tr-TR", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/onwK4e9ZLuTAKqWW03F9/f56723eb-7529-4617-bc87-5cf65658e538.mp3" + } + ], + "safety_control": null, + "voice_verification": { + "requires_verification": false, + "is_verified": false, + "verification_failures": [], + "verification_attempts_count": 0, + "language": null, + "verification_attempts": null + }, + "permission_on_resource": null, + "is_owner": false, + "is_legacy": false, + "is_mixed": false, + "favorited_at_unix": null, + "created_at_unix": null + }, + { + "voice_id": "pFZP5JQG7iQjIQuC4Bku", + "name": "Lily", + "samples": null, + "category": "premade", + "fine_tuning": { + "is_allowed_to_fine_tune": true, + "state": { + "eleven_flash_v2_5": "fine_tuned", + "eleven_turbo_v2": "fine_tuned", + "eleven_flash_v2": "fine_tuned", + "eleven_v2_flash": "fine_tuned", + "eleven_v2_5_flash": "fine_tuned" + }, + "verification_failures": [], + "verification_attempts_count": 0, + "manual_verification_requested": false, + "language": "en", + "progress": { + "eleven_flash_v2_5": 1, + "eleven_v2_flash": 1, + "eleven_flash_v2": 1, + "eleven_v2_5_flash": 1 + }, + "message": { + "eleven_flash_v2_5": "Done!", + "eleven_turbo_v2": "", + "eleven_flash_v2": "Done!", + "eleven_v2_flash": "Done!", + "eleven_v2_5_flash": "Done!" + }, + "dataset_duration_seconds": null, + "verification_attempts": null, + "slice_ids": null, + "manual_verification": null, + "max_verification_attempts": 5, + "next_max_verification_attempts_reset_unix_ms": 1700000000000 + }, + "labels": { + "accent": "british", + "description": "warm", + "descriptive": "confident", + "gender": "female", + "age": "middle_aged", + "use_case": "narration" + }, + "description": "Velvety British female voice delivers news and narrations with warmth and clarity.", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/pFZP5JQG7iQjIQuC4Bku/89b68b35-b3dd-4348-a84a-a3c13a3c2b30.mp3", + "available_for_tiers": [], + "settings": null, + "sharing": null, + "high_quality_base_model_ids": [ + "eleven_v2_flash", + "eleven_flash_v2", + "eleven_turbo_v2_5", + "eleven_multilingual_v2", + "eleven_v2_5_flash", + "eleven_flash_v2_5", + "eleven_turbo_v2" + ], + "verified_languages": [ + { + "language": "it", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "it-IT", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/pFZP5JQG7iQjIQuC4Bku/b2edb800-06a3-4d47-9bb7-461c2e5af7b2.mp3" + }, + { + "language": "de", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "de-DE", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/pFZP5JQG7iQjIQuC4Bku/0c5c2b73-34b6-4d17-ae2f-f4e4cb7b0636.mp3" + }, + { + "language": "zh", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "cmn-CN", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/pFZP5JQG7iQjIQuC4Bku/288da6a0-85aa-4705-b033-73d5304cdbaa.mp3" + }, + { + "language": "cs", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "cs-CZ", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/pFZP5JQG7iQjIQuC4Bku/f13ad751-dcab-45d0-9b3d-cb8b3b9e3f1d.mp3" + }, + { + "language": "nl", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "nl-NL", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/pFZP5JQG7iQjIQuC4Bku/86353d12-c42f-4e3e-afc2-a574c7030884.mp3" + }, + { + "language": "pl", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "pl-PL", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/pFZP5JQG7iQjIQuC4Bku/646f864e-fe42-42b2-a757-3da7b80275c2.mp3" + } + ], + "safety_control": null, + "voice_verification": { + "requires_verification": false, + "is_verified": false, + "verification_failures": [], + "verification_attempts_count": 0, + "language": null, + "verification_attempts": null + }, + "permission_on_resource": null, + "is_owner": false, + "is_legacy": false, + "is_mixed": false, + "favorited_at_unix": null, + "created_at_unix": null + }, + { + "voice_id": "pqHfZKP75CvOlQylNhV4", + "name": "Bill", + "samples": null, + "category": "premade", + "fine_tuning": { + "is_allowed_to_fine_tune": true, + "state": { + "eleven_flash_v2_5": "fine_tuned", + "eleven_turbo_v2": "fine_tuned", + "eleven_flash_v2": "fine_tuned", + "eleven_v2_flash": "fine_tuned", + "eleven_v2_5_flash": "fine_tuned" + }, + "verification_failures": [], + "verification_attempts_count": 0, + "manual_verification_requested": false, + "language": "en", + "progress": { + "eleven_flash_v2_5": 1, + "eleven_v2_flash": 1, + "eleven_flash_v2": 1, + "eleven_v2_5_flash": 1 + }, + "message": { + "eleven_flash_v2_5": "Done!", + "eleven_turbo_v2": "", + "eleven_flash_v2": "Done!", + "eleven_v2_flash": "Done!", + "eleven_v2_5_flash": "Done!" + }, + "dataset_duration_seconds": null, + "verification_attempts": null, + "slice_ids": null, + "manual_verification": null, + "max_verification_attempts": 5, + "next_max_verification_attempts_reset_unix_ms": 1700000000000 + }, + "labels": { + "accent": "american", + "descriptive": "crisp", + "age": "old", + "gender": "male", + "language": "en", + "use_case": "advertisement" + }, + "description": "Friendly and comforting voice ready to narrate your stories.", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/pqHfZKP75CvOlQylNhV4/d782b3ff-84ba-4029-848c-acf01285524d.mp3", + "available_for_tiers": [], + "settings": null, + "sharing": null, + "high_quality_base_model_ids": [ + "eleven_v2_flash", + "eleven_flash_v2", + "eleven_turbo_v2_5", + "eleven_multilingual_v2", + "eleven_v2_5_flash", + "eleven_flash_v2_5", + "eleven_turbo_v2" + ], + "verified_languages": [ + { + "language": "en", + "model_id": "eleven_v2_flash", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/pqHfZKP75CvOlQylNhV4/d782b3ff-84ba-4029-848c-acf01285524d.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/pqHfZKP75CvOlQylNhV4/d782b3ff-84ba-4029-848c-acf01285524d.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2_5", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/pqHfZKP75CvOlQylNhV4/d782b3ff-84ba-4029-848c-acf01285524d.mp3" + }, + { + "language": "en", + "model_id": "eleven_multilingual_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/pqHfZKP75CvOlQylNhV4/d782b3ff-84ba-4029-848c-acf01285524d.mp3" + }, + { + "language": "en", + "model_id": "eleven_v2_5_flash", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/pqHfZKP75CvOlQylNhV4/d782b3ff-84ba-4029-848c-acf01285524d.mp3" + }, + { + "language": "en", + "model_id": "eleven_flash_v2_5", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/pqHfZKP75CvOlQylNhV4/d782b3ff-84ba-4029-848c-acf01285524d.mp3" + }, + { + "language": "en", + "model_id": "eleven_turbo_v2", + "accent": "american", + "locale": "en-US", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/pqHfZKP75CvOlQylNhV4/d782b3ff-84ba-4029-848c-acf01285524d.mp3" + }, + { + "language": "fr", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "fr-FR", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/pqHfZKP75CvOlQylNhV4/ef978e66-26c2-446e-94fc-81b4362d71b1.mp3" + }, + { + "language": "ar", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": null, + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/pqHfZKP75CvOlQylNhV4/617b7973-2e00-462e-bcd9-dc324db17ecc.mp3" + }, + { + "language": "zh", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "cmn-CN", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/pqHfZKP75CvOlQylNhV4/3e232368-c1ea-4548-a41d-048c8406a645.mp3" + }, + { + "language": "de", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "de-DE", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/pqHfZKP75CvOlQylNhV4/a1eee806-7c72-46c4-9270-dc9256ddffe6.mp3" + }, + { + "language": "cs", + "model_id": "eleven_multilingual_v2", + "accent": "standard", + "locale": "cs-CZ", + "preview_url": "https://storage.googleapis.com/eleven-public-prod/premade/voices/pqHfZKP75CvOlQylNhV4/bf99c000-ca7f-4445-847c-b01e00ec063b.mp3" + } + ], + "safety_control": null, + "voice_verification": { + "requires_verification": false, + "is_verified": false, + "verification_failures": [], + "verification_attempts_count": 0, + "language": null, + "verification_attempts": null + }, + "permission_on_resource": null, + "is_owner": false, + "is_legacy": false, + "is_mixed": false, + "favorited_at_unix": null, + "created_at_unix": null + } + ] +} \ No newline at end of file diff --git a/packages/kbot/src/main.ts b/packages/kbot/src/main.ts index 84f2858e..8e1b20e2 100644 --- a/packages/kbot/src/main.ts +++ b/packages/kbot/src/main.ts @@ -16,6 +16,7 @@ import { run } from './commands/run.js' import { transcribeCommand, TranscribeOptionsSchema } from './commands/transcribe.js' import { imageCommand, ImageOptionsSchema } from './commands/images.js' +import { ttsCommand, TTSOptionsSchema } from './commands/tts.js' export const logger: any = createLogger('llm-tools') @@ -61,6 +62,12 @@ yargs(hideBin(process.argv)) (yargs) => toYargs(yargs, TranscribeOptionsSchema(), yargOptions), transcribeCommand ) + .command( + 'tts', + 'Convert text to speech using ElevenLabs', + (yargs) => toYargs(yargs, TTSOptionsSchema(), yargOptions), + ttsCommand + ) .command( 'types', 'Generate types', diff --git a/packages/kbot/tests/unit/audio/tts.test.ts b/packages/kbot/tests/unit/audio/tts.test.ts new file mode 100644 index 00000000..ea375979 --- /dev/null +++ b/packages/kbot/tests/unit/audio/tts.test.ts @@ -0,0 +1,194 @@ +import { describe, it, expect, afterAll, beforeAll } from 'vitest' +import * as path from 'node:path' +import * as fs from 'node:fs' +import { sync as exists } from "@polymech/fs/exists" +import { sync as write } from "@polymech/fs/write" + +import { ttsCommand } from '../../../src/commands/tts.js' +import { generateSpeech } from '../../../src/lib/tts-elevenlabs.js' +import { getLogger } from '../../../src/index.js' + +const TEST_DATA_DIR = './tests/unit/audio' +const TEST_TIMEOUT = 60000 // Increased timeout for API call + +describe('TTS Command', () => { + + const testTextFile = path.resolve(path.join(TEST_DATA_DIR, 'test-text.txt')) + const promptOutputFile = path.resolve(path.join(TEST_DATA_DIR, 'prompt-speech.mp3')) + const fileOutputFile = path.resolve(path.join(TEST_DATA_DIR, 'file-speech.mp3')) + + const cleanupFiles = () => { + if (fs.existsSync(promptOutputFile)) { + fs.unlinkSync(promptOutputFile) + } + if (fs.existsSync(fileOutputFile)) { + fs.unlinkSync(fileOutputFile) + } + if (fs.existsSync(testTextFile)) { + fs.unlinkSync(testTextFile) + } + } + + beforeAll(() => { + if (!fs.existsSync(TEST_DATA_DIR)) { + fs.mkdirSync(TEST_DATA_DIR, { recursive: true }); + } + cleanupFiles() + + // Create test text file + write(testTextFile, 'Hello, this is a test of the text-to-speech functionality. The quick brown fox jumps over the lazy dog.') + }) + + afterAll(cleanupFiles) + + it('should generate speech from a prompt and save it to a file', async () => { + const options = { + prompt: 'Hello world, this is a test of ElevenLabs text-to-speech integration.', + dst: promptOutputFile, + logLevel: 2, + voiceId: 'JBFqnCBsd6RMkjVDRZzb', + outputFormat: 'mp3_44100_128' as const, + modelId: 'eleven_multilingual_v2', + dry: false // Set to true to skip actual API call + } + + await ttsCommand(options) + + if (!options.dry) { + expect(exists(promptOutputFile)).toBe('file') + // Check that the file has some content + const stats = fs.statSync(promptOutputFile) + expect(stats.size).toBeGreaterThan(0) + } + + }, TEST_TIMEOUT) + + it('should generate speech from a text file and save it to a file', async () => { + const options = { + include: [testTextFile], + dst: fileOutputFile, + logLevel: 2, + voiceId: 'JBFqnCBsd6RMkjVDRZzb', + outputFormat: 'mp3_44100_128' as const, + modelId: 'eleven_multilingual_v2', + dry: false // Set to true to skip actual API call + } + + await ttsCommand(options) + + if (!options.dry) { + expect(exists(fileOutputFile)).toBe('file') + // Check that the file has some content + const stats = fs.statSync(fileOutputFile) + expect(stats.size).toBeGreaterThan(0) + } + + }, TEST_TIMEOUT) + + it('should handle different output formats', async () => { + const pcmOutputFile = path.resolve(path.join(TEST_DATA_DIR, 'test-pcm.wav')) + + const options = { + prompt: 'Testing PCM output format', + dst: pcmOutputFile, + logLevel: 2, + voiceId: 'JBFqnCBsd6RMkjVDRZzb', + outputFormat: 'pcm_44100' as const, + modelId: 'eleven_multilingual_v2', + dry: true // Use dry run to avoid API call + } + + await ttsCommand(options) + + // In dry run, file won't be created, but command should not throw + expect(true).toBe(true) + + // Cleanup + if (fs.existsSync(pcmOutputFile)) { + fs.unlinkSync(pcmOutputFile) + } + + }, TEST_TIMEOUT) + + it('should handle voice settings parameters', async () => { + const voiceSettingsFile = path.resolve(path.join(TEST_DATA_DIR, 'voice-settings-test.mp3')) + + const options = { + prompt: 'Testing voice settings with stability and similarity boost', + dst: voiceSettingsFile, + logLevel: 2, + voiceId: 'JBFqnCBsd6RMkjVDRZzb', + outputFormat: 'mp3_44100_128' as const, + modelId: 'eleven_multilingual_v2', + stability: 0.75, + similarityBoost: 0.8, + style: 0.5, + useSpeakerBoost: true, + dry: true // Use dry run to avoid API call + } + + await ttsCommand(options) + + // In dry run, file won't be created, but command should not throw + expect(true).toBe(true) + + // Cleanup + if (fs.existsSync(voiceSettingsFile)) { + fs.unlinkSync(voiceSettingsFile) + } + + }, TEST_TIMEOUT) + + it('should validate required parameters', async () => { + // Test missing text content + const options = { + dst: 'test-output.mp3', + logLevel: 2, + } + + // This should handle the error gracefully + await expect(async () => { + await ttsCommand(options) + }).not.toThrow() + + }) + + it('should validate missing destination', async () => { + // Test missing destination + const options = { + prompt: 'Test text', + logLevel: 2, + } + + // This should handle the error gracefully + await expect(async () => { + await ttsCommand(options) + }).not.toThrow() + + }) + + // Test the lib function directly + it('should test the generateSpeech lib function with mock', async () => { + const logger = getLogger({ logLevel: 2 }) + + // This test will fail without a real API key, but we can test the structure + const options = { + text: 'Hello, testing the lib function directly', + voiceId: 'JBFqnCBsd6RMkjVDRZzb', + outputFormat: 'mp3_44100_128' as const, + modelId: 'eleven_multilingual_v2', + logger, + api_key: 'test-key' // This will fail but we can catch the error + } + + try { + await generateSpeech(options) + // If this succeeds, great! + expect(true).toBe(true) + } catch (error: any) { + // Expected to fail without real API key + expect(error.message).toContain('API key') + } + + }) +}) \ No newline at end of file