feat(web-test): add ElevenLabs TTS provider

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-03-03 11:15:36 +03:00
parent a8d8007846
commit 5bccca2475
3 changed files with 55 additions and 1 deletions
+13 -1
View File
@@ -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;
}
}
+18
View File
@@ -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.
## Полный пример
Типовая структура озвученного сценария: