Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,93 @@
# `sound-generation`
ElevenLabs implementation of `@suaveplan/voice`'s `SoundEffectEngine`
interface. Posts a JSON body to `POST /v1/sound-generation` and returns
the generated audio as raw bytes.
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Generative sound effects are an ElevenLabs strength but the
`/v1/sound-generation` endpoint has its own request shape with
snake_case fields and ElevenLabs-specific knobs (`prompt_influence`,
`loop`). This adapter maps the `SoundEffectRequest` shape
(camelCase, with optional duration / prompt-influence / loop / model id /
output format) onto the wire body and remaps every error onto the
`@suaveplan/voice` domain. Application code stays portable across
providers; only this file knows the upstream conventions.
## Features
- One method, `generate(request)`, returning the raw audio bytes plus
the requested format (defaulting to `mp3_44100_128`).
- Optional `durationSeconds` (0.5–30s typical), `loop`,
`promptInfluence` (0..1), `modelId`, and `outputFormat` are forwarded
when defined and omitted otherwise.
- Surfaces the upstream `x-request-id` on the result.
- Errors are remapped: 401 → `ProviderNotConfiguredError`, 429 →
`ProviderRateLimitedError` (with `retryAfterMs`), 5xx →
`SoundEffectGenerationFailedError`.
- Built-in retry / backoff inherited from the shared
`ElevenLabsClient`.
## Usage: Basic Example
```ts
import { createElevenLabsAdapters } from "@suaveplan/third-party-elevenlabs";
const { soundEffects } = createElevenLabsAdapters({ apiKey: KEY });
const { audio } = await soundEffects.generate({ text: "ocean waves at dusk" });
await Bun.write("waves.mp3", audio);
```
## Usage: Advanced Example
```ts
import {
ElevenLabsClient,
ElevenLabsSoundEffectEngine,
} from "@suaveplan/third-party-elevenlabs";
const eng = new ElevenLabsSoundEffectEngine(
new ElevenLabsClient({ apiKey: KEY, timeoutMs: 60_000 })
);
const ctrl = new AbortController();
const result = await eng.generate({
text: "thunderclap followed by rain",
durationSeconds: 8,
loop: false,
promptInfluence: 0.7,
modelId: "sound_v2",
outputFormat: "wav_44100",
signal: ctrl.signal,
});
console.log(`got ${result.audio.byteLength} bytes`, result.requestId);
```
## API Reference
- `class ElevenLabsSoundEffectEngine implements SoundEffectEngine`
- `providerName: "elevenlabs"`
- `generate(request: SoundEffectRequest): Promise<SoundEffectResult>`
- returns `{ audio, format, requestId? }`.
Throws: `ProviderNotConfiguredError`, `ProviderRateLimitedError`,
`SoundEffectGenerationFailedError`.
## Implementation Notes
- The `format` on the result reflects the **requested** format, not
necessarily the encoded output — ElevenLabs may return a different
format if it rejects the request. Inspect the response bytes / use a
metadata reader if you need ground truth.
- `prompt_influence` defaults to ElevenLabs's server-side default when
omitted (commonly 0.3); set explicitly to 0–1 for deterministic
control.
- `text` is sent verbatim — there is no client-side validation. Empty
text will be rejected upstream as a 422.
- The adapter inherits retry, timeout, and observability events from the
shared `ElevenLabsClient`. Configure them on the client, not here.