mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-07-06 03:08:57 +03:00
feat(web-test): add ElevenLabs TTS provider
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -216,6 +216,18 @@ For OpenAI-compatible provider:
|
||||
}
|
||||
```
|
||||
|
||||
For ElevenLabs:
|
||||
```json
|
||||
{
|
||||
"tts": {
|
||||
"provider": "elevenlabs",
|
||||
"apiKey": "sk_...",
|
||||
"voice": "JBFqnCBsd6RMkjVDRZzb"
|
||||
}
|
||||
}
|
||||
```
|
||||
Note: `voice` is the ElevenLabs voice ID (not a name). Default model: `eleven_multilingual_v2` (supports Russian and other languages).
|
||||
|
||||
### `showCaption()` speech parameter
|
||||
|
||||
The `speech` option controls what text is narrated (vs displayed):
|
||||
@@ -236,7 +248,7 @@ Generate TTS and merge audio with video. Call after `stopRecording()`.
|
||||
|-----------|------|-------------|
|
||||
| `videoPath` | `string` | Path to the recorded MP4 file |
|
||||
| `opts.captions` | `Array` | Explicit captions (default: from last recording or `.captions.json`) |
|
||||
| `opts.provider` | `string` | `'edge'` (default) or `'openai'` |
|
||||
| `opts.provider` | `string` | `'edge'` (default), `'openai'`, or `'elevenlabs'` |
|
||||
| `opts.voice` | `string` | Voice name (provider-specific) |
|
||||
| `opts.apiKey` | `string` | API key (for openai) |
|
||||
| `opts.apiUrl` | `string` | Endpoint (for openai) |
|
||||
|
||||
@@ -3154,10 +3154,34 @@ async function openaiTtsProvider(text, outputPath, opts = {}) {
|
||||
writeFileSync(outputPath, buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* ElevenLabs TTS provider. Requires apiKey.
|
||||
* @param {string} text — text to synthesize
|
||||
* @param {string} outputPath — path for the output mp3 file
|
||||
* @param {object} opts — { apiKey, apiUrl, voice, model }
|
||||
*/
|
||||
async function elevenlabsTtsProvider(text, outputPath, opts = {}) {
|
||||
const voiceId = opts.voice || 'JBFqnCBsd6RMkjVDRZzb'; // George
|
||||
const apiUrl = opts.apiUrl || `https://api.elevenlabs.io/v1/text-to-speech/${voiceId}`;
|
||||
if (!opts.apiKey) throw new Error('ElevenLabs TTS requires apiKey');
|
||||
const resp = await fetch(apiUrl, {
|
||||
method: 'POST',
|
||||
headers: { 'xi-api-key': opts.apiKey, 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
text,
|
||||
model_id: opts.model || 'eleven_multilingual_v2',
|
||||
}),
|
||||
});
|
||||
if (!resp.ok) throw new Error(`ElevenLabs TTS error ${resp.status}: ${await resp.text()}`);
|
||||
const buf = Buffer.from(await resp.arrayBuffer());
|
||||
writeFileSync(outputPath, buf);
|
||||
}
|
||||
|
||||
/** Get TTS provider function by name. */
|
||||
function getTtsProvider(name) {
|
||||
switch (name) {
|
||||
case 'openai': return openaiTtsProvider;
|
||||
case 'elevenlabs': return elevenlabsTtsProvider;
|
||||
case 'edge': default: return edgeTtsProvider;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,6 +225,24 @@ await showCaption('Технические детали', { speech: false });
|
||||
|
||||
Голоса: `alloy`, `echo`, `fable`, `onyx`, `nova`, `shimmer`.
|
||||
|
||||
Поле `apiUrl` позволяет подключить любой OpenAI-совместимый сервис.
|
||||
|
||||
### ElevenLabs (платный)
|
||||
|
||||
Высокое качество синтеза, мультиязычная модель поддерживает русский.
|
||||
|
||||
```json
|
||||
{
|
||||
"tts": {
|
||||
"provider": "elevenlabs",
|
||||
"apiKey": "sk_...",
|
||||
"voice": "JBFqnCBsd6RMkjVDRZzb"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`voice` — это ID голоса из библиотеки ElevenLabs (не имя). Список голосов — в личном кабинете ElevenLabs. Требуется платный тариф для использования через API.
|
||||
|
||||
## Полный пример
|
||||
|
||||
Типовая структура озвученного сценария:
|
||||
|
||||
Reference in New Issue
Block a user