@effect-uai/elevenlabs 0.12.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ElevenLabsMusicGenerator.d.mts +1 -3
- package/dist/ElevenLabsMusicGenerator.d.mts.map +1 -1
- package/dist/ElevenLabsMusicGenerator.mjs +6 -4
- package/dist/ElevenLabsMusicGenerator.mjs.map +1 -1
- package/dist/ElevenLabsMusicGenerator.test.d.mts +1 -1
- package/dist/ElevenLabsMusicGenerator.test.mjs +10 -6
- package/dist/ElevenLabsMusicGenerator.test.mjs.map +1 -1
- package/dist/ElevenLabsSynthesizer.d.mts +4 -7
- package/dist/ElevenLabsSynthesizer.d.mts.map +1 -1
- package/dist/ElevenLabsSynthesizer.mjs +1 -1
- package/dist/ElevenLabsSynthesizer.mjs.map +1 -1
- package/dist/ElevenLabsTranscriber.d.mts +5 -9
- package/dist/ElevenLabsTranscriber.d.mts.map +1 -1
- package/dist/ElevenLabsTranscriber.mjs +1 -1
- package/dist/ElevenLabsTranscriber.mjs.map +1 -1
- package/dist/ElevenLabsTranscriber.test.d.mts +1 -1
- package/dist/ElevenLabsTranscriber.test.mjs +10 -5
- package/dist/ElevenLabsTranscriber.test.mjs.map +1 -1
- package/dist/codec.d.mts +4 -6
- package/dist/codec.d.mts.map +1 -1
- package/dist/codec.mjs +1 -1
- package/dist/codec.mjs.map +1 -1
- package/dist/codec.test.d.mts +1 -1
- package/dist/codec.test.mjs +19 -13
- package/dist/codec.test.mjs.map +1 -1
- package/dist/dist-C0AvqZTC.mjs +145 -0
- package/dist/dist-C0AvqZTC.mjs.map +1 -0
- package/dist/{magic-string.es-CaWgF-3p.mjs → magic-string.es-CUAnjKYC.mjs} +14 -13
- package/dist/{magic-string.es-CaWgF-3p.mjs.map → magic-string.es-CUAnjKYC.mjs.map} +1 -1
- package/dist/models.d.mts.map +1 -1
- package/dist/{musicCodec-CZni1gAQ.d.mts → musicCodec-DjmvNC4W.d.mts} +1 -2
- package/dist/musicCodec-DjmvNC4W.d.mts.map +1 -0
- package/dist/musicCodec.d.mts +1 -1
- package/dist/musicCodec.mjs.map +1 -1
- package/dist/realtimeStt.d.mts +0 -1
- package/dist/realtimeStt.d.mts.map +1 -1
- package/dist/realtimeStt.mjs.map +1 -1
- package/dist/realtimeTts.d.mts +2 -2
- package/dist/realtimeTts.d.mts.map +1 -1
- package/dist/realtimeTts.mjs.map +1 -1
- package/dist/region.d.mts.map +1 -1
- package/dist/region.mjs.map +1 -1
- package/dist/region.test.d.mts +1 -1
- package/dist/region.test.mjs +1 -1
- package/dist/region.test.mjs.map +1 -1
- package/dist/{dist-CWoAuwS9.mjs → test.DNmyFkvJ-N3QqMRwZ.mjs} +257 -381
- package/dist/test.DNmyFkvJ-N3QqMRwZ.mjs.map +1 -0
- package/package.json +5 -5
- package/src/ElevenLabsMusicGenerator.ts +7 -10
- package/src/ElevenLabsSynthesizer.ts +10 -13
- package/src/ElevenLabsTranscriber.ts +5 -8
- package/src/realtimeStt.ts +12 -14
- package/dist/dist-CWoAuwS9.mjs.map +0 -1
- package/dist/musicCodec-CZni1gAQ.d.mts.map +0 -1
- /package/dist/{chunk-uyGKjUfl.mjs → rolldown-runtime-EAsCxrDo.mjs} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ElevenLabsMusicModel } from "./models.mjs";
|
|
2
|
-
import { t as ElevenLabsCompositionPlan } from "./musicCodec-
|
|
2
|
+
import { t as ElevenLabsCompositionPlan } from "./musicCodec-DjmvNC4W.mjs";
|
|
3
3
|
import { ElevenLabsRegion } from "./region.mjs";
|
|
4
4
|
import { Context, Duration, Effect, Layer, Redacted, Stream } from "effect";
|
|
5
5
|
import { HttpClient } from "effect/unstable/http";
|
|
@@ -7,8 +7,6 @@ import { CommonGenerateMusicRequest, CommonStreamGenerateMusicRequest, GenerateR
|
|
|
7
7
|
import { MusicGenerator } from "@effect-uai/core/MusicGenerator";
|
|
8
8
|
import * as AiError from "@effect-uai/core/AiError";
|
|
9
9
|
import { AudioChunk } from "@effect-uai/core/Audio";
|
|
10
|
-
|
|
11
|
-
//#region src/ElevenLabsMusicGenerator.d.ts
|
|
12
10
|
declare namespace ElevenLabsMusicGenerator_d_exports {
|
|
13
11
|
export { Config, CreateCompositionPlanRequest, ElevenLabsMusicGenerateRequest, ElevenLabsMusicGenerator, ElevenLabsMusicGeneratorService, layer, make };
|
|
14
12
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ElevenLabsMusicGenerator.d.mts","names":[],"sources":["../src/ElevenLabsMusicGenerator.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"ElevenLabsMusicGenerator.d.mts","names":[],"sources":["../src/ElevenLabsMusicGenerator.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA6CY,iCAAiC,KAAK;WACvC,QAAQ;WACR,kBAAkB;WAClB;WACA;WACA;;KAGC;WACD;WACA,WAAW,SAAS;WACpB,wBAAwB;WACxB,QAAQ;;KAGP;WACD,WACP,SAAS,mCACN,OAAO,OAAO,gBAAgB,QAAQ;WAClC,mBACP,SAAS,mCACN,OAAO,OAAO,YAAY,QAAQ;WAC9B,uBAAuB,GAAG,GACjC,OAAO,OAAO,OAAO,mBAAmB,GAAG,IAC3C,SAAS,qCACN,OAAO,OAAO,kBAAkB,QAAQ,UAAU,GAAG;;;;;;WAMjD,wBACP,SAAS,iCACN,OAAO,OAAO,2BAA2B,QAAQ;;;cAG3C,iCAAiC;KAKlC;WACD,QAAQ,SAAS;WACjB;WACA,SAAS;;cA8NP,OAAI,KACV,WACJ,OAAO,OAAO,wCAAwC,WAAW;;;;;;;;;cAqBvD,QAAK,KACX,WACJ,MAAM,MAAM,2BAA2B,uBAAuB,WAAW"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as __exportAll } from "./
|
|
1
|
+
import { n as __exportAll } from "./rolldown-runtime-EAsCxrDo.mjs";
|
|
2
2
|
import { defaultFormat, formatToOutputSlug } from "./codec.mjs";
|
|
3
3
|
import { decodeCompositionPlan, warnDroppedPromptModeHints, wireCompositionPlan } from "./musicCodec.mjs";
|
|
4
4
|
import { resolveHost } from "./region.mjs";
|
|
@@ -113,7 +113,7 @@ const generateImpl = (cfg) => (request) => Effect.gen(function* () {
|
|
|
113
113
|
const buffer = yield* response.arrayBuffer.pipe(Effect.mapError(musicTransportFailure));
|
|
114
114
|
const bytes = new Uint8Array(buffer);
|
|
115
115
|
const songId = response.headers["song_id"] ?? response.headers["x-song-id"];
|
|
116
|
-
|
|
116
|
+
const result = {
|
|
117
117
|
audio: {
|
|
118
118
|
format,
|
|
119
119
|
bytes
|
|
@@ -121,7 +121,8 @@ const generateImpl = (cfg) => (request) => Effect.gen(function* () {
|
|
|
121
121
|
provider: "elevenlabs-music",
|
|
122
122
|
...typeof songId === "string" && { songId },
|
|
123
123
|
...request.signWithC2pa === true && { watermark: "c2pa" }
|
|
124
|
-
}
|
|
124
|
+
};
|
|
125
|
+
return singleVariant(result);
|
|
125
126
|
});
|
|
126
127
|
const streamGenerationImpl = (cfg) => (request) => Stream.unwrap(Effect.gen(function* () {
|
|
127
128
|
const client = yield* HttpClient.HttpClient;
|
|
@@ -158,7 +159,8 @@ const createCompositionPlanImpl = (cfg) => (request) => Effect.gen(function* ()
|
|
|
158
159
|
const text = yield* response.text.pipe(Effect.orElseSucceed(() => ""));
|
|
159
160
|
return yield* Effect.fail(musicHttpStatusError(response.status, text));
|
|
160
161
|
}
|
|
161
|
-
|
|
162
|
+
const json = yield* response.json.pipe(Effect.mapError(musicTransportFailure));
|
|
163
|
+
return decodeCompositionPlan(json);
|
|
162
164
|
});
|
|
163
165
|
const make = (cfg) => Effect.map(HttpClient.HttpClient, (client) => ({
|
|
164
166
|
generate: (request) => generateImpl(cfg)(request).pipe(Effect.provideService(HttpClient.HttpClient, client)),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ElevenLabsMusicGenerator.mjs","names":[],"sources":["../src/ElevenLabsMusicGenerator.ts"],"sourcesContent":["import { Context, Duration, Effect, Layer, Redacted, Stream } from \"effect\"\nimport { HttpClient, HttpClientRequest } from \"effect/unstable/http\"\nimport * as AiError from \"@effect-uai/core/AiError\"\nimport type { AudioChunk, AudioFormat } from \"@effect-uai/core/Audio\"\nimport type {\n CommonGenerateMusicRequest,\n CommonStreamGenerateMusicRequest,\n GenerateResult,\n MusicResult,\n MusicSessionInput,\n MusicStreamEvent,\n} from \"@effect-uai/core/Music\"\nimport { singleVariant } from \"@effect-uai/core/Music\"\nimport { MusicGenerator, type MusicGeneratorService } from \"@effect-uai/core/MusicGenerator\"\nimport { defaultFormat, formatToOutputSlug } from \"./codec.js\"\nimport type { ElevenLabsMusicModel } from \"./models.js\"\nimport {\n decodeCompositionPlan,\n type ElevenLabsCompositionPlan,\n warnDroppedPromptModeHints,\n wireCompositionPlan,\n} from \"./musicCodec.js\"\nimport { type ElevenLabsRegion, resolveHost } from \"./region.js\"\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/**\n * ElevenLabs-typed music request. Narrows `model` to\n * `ElevenLabsMusicModel` and adds provider-specific extras:\n *\n * - `compositionPlan` — switch from prompt mode to plan mode. Mutually\n * exclusive with `prompt` on the wire.\n * - `forceInstrumental` — skip vocals. ElevenLabs has no `instrumental`\n * on the cross-provider Common request (the field was removed in\n * v0.7 because it has wildly different semantics per provider); the\n * typed surface restores it.\n * - `signWithC2pa` — opt-in C2PA Content Credentials, MP3 output only.\n * - `respectSectionsDurations` — composition-plan mode only. False\n * trades section-duration accuracy for quality + latency.\n *\n * Setting `compositionPlan` with a non-empty `prompt`, or with\n * `duration`, fails `InvalidRequest` at the codec layer.\n */\nexport type ElevenLabsMusicGenerateRequest = Omit<CommonGenerateMusicRequest, \"model\"> & {\n readonly model?: ElevenLabsMusicModel\n readonly compositionPlan?: ElevenLabsCompositionPlan\n readonly forceInstrumental?: boolean\n readonly signWithC2pa?: boolean\n readonly respectSectionsDurations?: boolean\n}\n\nexport type CreateCompositionPlanRequest = {\n readonly prompt: string\n readonly duration?: Duration.Duration\n readonly sourceCompositionPlan?: ElevenLabsCompositionPlan\n readonly model?: ElevenLabsMusicModel\n}\n\nexport type ElevenLabsMusicGeneratorService = {\n readonly generate: (\n request: ElevenLabsMusicGenerateRequest,\n ) => Effect.Effect<GenerateResult, AiError.AiError>\n readonly streamGeneration: (\n request: ElevenLabsMusicGenerateRequest,\n ) => Stream.Stream<AudioChunk, AiError.AiError>\n readonly streamGenerationFrom: <E, R>(\n input: Stream.Stream<MusicSessionInput, E, R>,\n request: CommonStreamGenerateMusicRequest,\n ) => Stream.Stream<MusicStreamEvent, AiError.AiError | E, R>\n /**\n * Free endpoint (rate-limited, no credit cost): turn a prompt into a\n * structured `MusicPrompt` plan. Feed the result back into\n * `generate` / `streamGeneration` via `compositionPlan`.\n */\n readonly createCompositionPlan: (\n request: CreateCompositionPlanRequest,\n ) => Effect.Effect<ElevenLabsCompositionPlan, AiError.AiError>\n}\n\nexport class ElevenLabsMusicGenerator extends Context.Service<\n ElevenLabsMusicGenerator,\n ElevenLabsMusicGeneratorService\n>()(\"@betalyra/effect-uai/providers/elevenlabs/ElevenLabsMusicGenerator\") {}\n\nexport type Config = {\n readonly apiKey: Redacted.Redacted\n readonly baseUrl?: string\n readonly region?: ElevenLabsRegion\n}\n\nconst DEFAULT_MODEL: ElevenLabsMusicModel = \"music_v1\"\n\n// ---------------------------------------------------------------------------\n// HTTP errors (music namespace; reuses the same status taxonomy)\n// ---------------------------------------------------------------------------\n\nconst musicTransportFailure = (cause: unknown): AiError.AiError =>\n new AiError.Unavailable({ provider: \"elevenlabs-music\", raw: cause })\n\nconst musicHttpStatusError = (status: number, body: string): AiError.AiError => {\n if (status === 429) return new AiError.RateLimited({ provider: \"elevenlabs-music\", raw: body })\n if (status === 408 || status === 504)\n return new AiError.Timeout({ provider: \"elevenlabs-music\", raw: body })\n if (status === 401)\n return new AiError.AuthFailed({ provider: \"elevenlabs-music\", subtype: \"auth\", raw: body })\n if (status === 403)\n return new AiError.AuthFailed({\n provider: \"elevenlabs-music\",\n subtype: \"permission\",\n raw: body,\n })\n if (status === 402)\n return new AiError.AuthFailed({\n provider: \"elevenlabs-music\",\n subtype: \"billing\",\n raw: body,\n })\n if (status >= 500)\n return new AiError.Unavailable({ provider: \"elevenlabs-music\", status, raw: body })\n return new AiError.InvalidRequest({ provider: \"elevenlabs-music\", raw: body })\n}\n\n// ---------------------------------------------------------------------------\n// Wire body\n// ---------------------------------------------------------------------------\n\n/**\n * Build the JSON body for `/v1/music` (sync + stream share the body).\n *\n * Mutual exclusion: `compositionPlan` and prompt-mode fields cannot\n * coexist. When `compositionPlan` is set, `prompt` must be empty and\n * `duration` must be unset (section durations live on the plan).\n */\nconst buildBody = (request: ElevenLabsMusicGenerateRequest) =>\n Effect.gen(function* () {\n const model = request.model ?? DEFAULT_MODEL\n if (request.compositionPlan !== undefined) {\n if (request.prompt.length > 0) {\n return yield* Effect.fail(\n new AiError.InvalidRequest({\n provider: \"elevenlabs-music\",\n param: \"prompt\",\n raw: \"`prompt` and `compositionPlan` are mutually exclusive. Pass one or the other (compositionPlan carries its own per-section lyrics and styles).\",\n }),\n )\n }\n if (request.duration !== undefined) {\n return yield* Effect.fail(\n new AiError.InvalidRequest({\n provider: \"elevenlabs-music\",\n param: \"duration\",\n raw: \"`duration` is ignored when `compositionPlan` is set; section durations live on the plan. Remove `duration`.\",\n }),\n )\n }\n return {\n composition_plan: wireCompositionPlan(request.compositionPlan),\n model_id: model,\n ...(request.seed !== undefined && { seed: request.seed }),\n ...(request.forceInstrumental !== undefined && {\n force_instrumental: request.forceInstrumental,\n }),\n ...(request.respectSectionsDurations !== undefined && {\n respect_sections_durations: request.respectSectionsDurations,\n }),\n ...(request.signWithC2pa !== undefined && { sign_with_c2pa: request.signWithC2pa }),\n }\n }\n yield* warnDroppedPromptModeHints(request as CommonGenerateMusicRequest)\n return {\n prompt: request.prompt,\n model_id: model,\n ...(request.duration !== undefined && {\n music_length_ms: Duration.toMillis(request.duration),\n }),\n ...(request.seed !== undefined && { seed: request.seed }),\n ...(request.forceInstrumental !== undefined && {\n force_instrumental: request.forceInstrumental,\n }),\n ...(request.signWithC2pa !== undefined && { sign_with_c2pa: request.signWithC2pa }),\n }\n })\n\nconst buildMusicHttpRequest = (\n cfg: Config,\n request: ElevenLabsMusicGenerateRequest,\n path: \"\" | \"/stream\",\n) =>\n Effect.gen(function* () {\n const format: AudioFormat = request.outputFormat ?? defaultFormat\n const slug = yield* formatToOutputSlug(format)\n const body = yield* buildBody(request)\n const url = `${resolveHost(cfg)}/music${path}?output_format=${slug}`\n const httpRequest = HttpClientRequest.post(url).pipe(\n HttpClientRequest.setHeader(\"xi-api-key\", Redacted.value(cfg.apiKey)),\n HttpClientRequest.bodyJsonUnsafe(body),\n )\n return { httpRequest, format }\n })\n\n// ---------------------------------------------------------------------------\n// Service implementation\n// ---------------------------------------------------------------------------\n\nconst generateImpl =\n (cfg: Config) =>\n (\n request: ElevenLabsMusicGenerateRequest,\n ): Effect.Effect<GenerateResult, AiError.AiError, HttpClient.HttpClient> =>\n Effect.gen(function* () {\n const client = yield* HttpClient.HttpClient\n const { httpRequest, format } = yield* buildMusicHttpRequest(cfg, request, \"\")\n const response = yield* client\n .execute(httpRequest)\n .pipe(Effect.mapError(musicTransportFailure))\n if (response.status >= 400) {\n const text = yield* response.text.pipe(Effect.orElseSucceed(() => \"\"))\n return yield* Effect.fail(musicHttpStatusError(response.status, text))\n }\n const buffer = yield* response.arrayBuffer.pipe(Effect.mapError(musicTransportFailure))\n const bytes = new Uint8Array(buffer)\n const songId = response.headers[\"song_id\"] ?? response.headers[\"x-song-id\"]\n const result: MusicResult = {\n audio: { format, bytes },\n provider: \"elevenlabs-music\",\n ...(typeof songId === \"string\" && { songId }),\n ...(request.signWithC2pa === true && { watermark: \"c2pa\" as const }),\n }\n return singleVariant(result)\n })\n\nconst streamGenerationImpl =\n (cfg: Config) =>\n (\n request: ElevenLabsMusicGenerateRequest,\n ): Stream.Stream<AudioChunk, AiError.AiError, HttpClient.HttpClient> =>\n Stream.unwrap(\n Effect.gen(function* () {\n const client = yield* HttpClient.HttpClient\n const { httpRequest } = yield* buildMusicHttpRequest(cfg, request, \"/stream\")\n const response = yield* client\n .execute(httpRequest)\n .pipe(Effect.mapError(musicTransportFailure))\n if (response.status >= 400) {\n const text = yield* response.text.pipe(Effect.orElseSucceed(() => \"\"))\n return Stream.fail(musicHttpStatusError(response.status, text))\n }\n return response.stream.pipe(\n Stream.mapError(musicTransportFailure),\n Stream.map((bytes): AudioChunk => ({ bytes })),\n )\n }),\n )\n\n/**\n * ElevenLabs music has no bidirectional session at the wire level.\n * Layer does not register `MusicInteractiveSession`, so callers using\n * `MusicGenerator.streamGenerationFrom` get a compile-time error\n * before this runtime fallback fires.\n */\nconst streamGenerationFromUnsupported = <E, R>(\n _input: Stream.Stream<MusicSessionInput, E, R>,\n _request: CommonStreamGenerateMusicRequest,\n): Stream.Stream<MusicStreamEvent, AiError.AiError | E, R> =>\n Stream.fail(\n new AiError.Unsupported({\n provider: \"elevenlabs-music\",\n capability: \"streamGenerationFrom\",\n reason:\n \"ElevenLabs music has no bidirectional session. Use `streamGeneration` for chunked output, or `createCompositionPlan` + `generate` for structured plans.\",\n }),\n )\n\nconst createCompositionPlanImpl =\n (cfg: Config) =>\n (\n request: CreateCompositionPlanRequest,\n ): Effect.Effect<ElevenLabsCompositionPlan, AiError.AiError, HttpClient.HttpClient> =>\n Effect.gen(function* () {\n const client = yield* HttpClient.HttpClient\n const body = {\n prompt: request.prompt,\n model_id: request.model ?? DEFAULT_MODEL,\n ...(request.duration !== undefined && {\n music_length_ms: Duration.toMillis(request.duration),\n }),\n ...(request.sourceCompositionPlan !== undefined && {\n source_composition_plan: wireCompositionPlan(request.sourceCompositionPlan),\n }),\n }\n const httpRequest = HttpClientRequest.post(`${resolveHost(cfg)}/music/plan`).pipe(\n HttpClientRequest.setHeader(\"xi-api-key\", Redacted.value(cfg.apiKey)),\n HttpClientRequest.bodyJsonUnsafe(body),\n )\n const response = yield* client\n .execute(httpRequest)\n .pipe(Effect.mapError(musicTransportFailure))\n if (response.status >= 400) {\n const text = yield* response.text.pipe(Effect.orElseSucceed(() => \"\"))\n return yield* Effect.fail(musicHttpStatusError(response.status, text))\n }\n const json = yield* response.json.pipe(Effect.mapError(musicTransportFailure))\n return decodeCompositionPlan(json)\n })\n\n// ---------------------------------------------------------------------------\n// Constructors\n// ---------------------------------------------------------------------------\n\nexport const make = (\n cfg: Config,\n): Effect.Effect<ElevenLabsMusicGeneratorService, never, HttpClient.HttpClient> =>\n Effect.map(HttpClient.HttpClient, (client) => ({\n generate: (request) =>\n generateImpl(cfg)(request).pipe(Effect.provideService(HttpClient.HttpClient, client)),\n streamGeneration: (request) =>\n streamGenerationImpl(cfg)(request).pipe(Stream.provideService(HttpClient.HttpClient, client)),\n streamGenerationFrom: streamGenerationFromUnsupported,\n createCompositionPlan: (request) =>\n createCompositionPlanImpl(cfg)(request).pipe(\n Effect.provideService(HttpClient.HttpClient, client),\n ),\n }))\n\n/**\n * Layer that registers the provider-specific `ElevenLabsMusicGenerator`\n * tag and the generic `MusicGenerator` tag.\n *\n * Does NOT register `MusicInteractiveSession`. ElevenLabs music has no\n * bidirectional wire endpoint; `streamGenerationFrom` against this\n * Layer alone fails to typecheck.\n */\nexport const layer = (\n cfg: Config,\n): Layer.Layer<ElevenLabsMusicGenerator | MusicGenerator, never, HttpClient.HttpClient> =>\n Layer.merge(\n Layer.effect(ElevenLabsMusicGenerator, make(cfg)),\n Layer.effect(\n MusicGenerator,\n Effect.map(\n make(cfg),\n (s): MusicGeneratorService => ({\n generate: (req: CommonGenerateMusicRequest) =>\n s.generate({ ...req, model: req.model as ElevenLabsMusicModel }),\n streamGeneration: (req: CommonStreamGenerateMusicRequest) =>\n s.streamGeneration({ ...req, model: req.model as ElevenLabsMusicModel }),\n streamGenerationFrom: s.streamGenerationFrom,\n }),\n ),\n ),\n )\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ElevenLabsMusicGenerator.mjs","names":[],"sources":["../src/ElevenLabsMusicGenerator.ts"],"sourcesContent":["import { Context, Duration, Effect, Layer, Redacted, Stream } from \"effect\"\nimport { HttpClient, HttpClientRequest } from \"effect/unstable/http\"\nimport * as AiError from \"@effect-uai/core/AiError\"\nimport type { AudioChunk, AudioFormat } from \"@effect-uai/core/Audio\"\nimport type {\n CommonGenerateMusicRequest,\n CommonStreamGenerateMusicRequest,\n GenerateResult,\n MusicResult,\n MusicSessionInput,\n MusicStreamEvent,\n} from \"@effect-uai/core/Music\"\nimport { singleVariant } from \"@effect-uai/core/Music\"\nimport { MusicGenerator, type MusicGeneratorService } from \"@effect-uai/core/MusicGenerator\"\nimport { defaultFormat, formatToOutputSlug } from \"./codec.js\"\nimport type { ElevenLabsMusicModel } from \"./models.js\"\nimport {\n decodeCompositionPlan,\n type ElevenLabsCompositionPlan,\n warnDroppedPromptModeHints,\n wireCompositionPlan,\n} from \"./musicCodec.js\"\nimport { type ElevenLabsRegion, resolveHost } from \"./region.js\"\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/**\n * ElevenLabs-typed music request. Narrows `model` to\n * `ElevenLabsMusicModel` and adds provider-specific extras:\n *\n * - `compositionPlan` — switch from prompt mode to plan mode. Mutually\n * exclusive with `prompt` on the wire.\n * - `forceInstrumental` — skip vocals. ElevenLabs has no `instrumental`\n * on the cross-provider Common request (the field was removed in\n * v0.7 because it has wildly different semantics per provider); the\n * typed surface restores it.\n * - `signWithC2pa` — opt-in C2PA Content Credentials, MP3 output only.\n * - `respectSectionsDurations` — composition-plan mode only. False\n * trades section-duration accuracy for quality + latency.\n *\n * Setting `compositionPlan` with a non-empty `prompt`, or with\n * `duration`, fails `InvalidRequest` at the codec layer.\n */\nexport type ElevenLabsMusicGenerateRequest = Omit<CommonGenerateMusicRequest, \"model\"> & {\n readonly model?: ElevenLabsMusicModel\n readonly compositionPlan?: ElevenLabsCompositionPlan\n readonly forceInstrumental?: boolean\n readonly signWithC2pa?: boolean\n readonly respectSectionsDurations?: boolean\n}\n\nexport type CreateCompositionPlanRequest = {\n readonly prompt: string\n readonly duration?: Duration.Duration\n readonly sourceCompositionPlan?: ElevenLabsCompositionPlan\n readonly model?: ElevenLabsMusicModel\n}\n\nexport type ElevenLabsMusicGeneratorService = {\n readonly generate: (\n request: ElevenLabsMusicGenerateRequest,\n ) => Effect.Effect<GenerateResult, AiError.AiError>\n readonly streamGeneration: (\n request: ElevenLabsMusicGenerateRequest,\n ) => Stream.Stream<AudioChunk, AiError.AiError>\n readonly streamGenerationFrom: <E, R>(\n input: Stream.Stream<MusicSessionInput, E, R>,\n request: CommonStreamGenerateMusicRequest,\n ) => Stream.Stream<MusicStreamEvent, AiError.AiError | E, R>\n /**\n * Free endpoint (rate-limited, no credit cost): turn a prompt into a\n * structured `MusicPrompt` plan. Feed the result back into\n * `generate` / `streamGeneration` via `compositionPlan`.\n */\n readonly createCompositionPlan: (\n request: CreateCompositionPlanRequest,\n ) => Effect.Effect<ElevenLabsCompositionPlan, AiError.AiError>\n}\n\nexport class ElevenLabsMusicGenerator extends Context.Service<\n ElevenLabsMusicGenerator,\n ElevenLabsMusicGeneratorService\n>()(\"@betalyra/effect-uai/providers/elevenlabs/ElevenLabsMusicGenerator\") {}\n\nexport type Config = {\n readonly apiKey: Redacted.Redacted\n readonly baseUrl?: string\n readonly region?: ElevenLabsRegion\n}\n\nconst DEFAULT_MODEL: ElevenLabsMusicModel = \"music_v1\"\n\n// ---------------------------------------------------------------------------\n// HTTP errors (music namespace; reuses the same status taxonomy)\n// ---------------------------------------------------------------------------\n\nconst musicTransportFailure = (cause: unknown): AiError.AiError =>\n new AiError.Unavailable({ provider: \"elevenlabs-music\", raw: cause })\n\nconst musicHttpStatusError = (status: number, body: string): AiError.AiError => {\n if (status === 429) return new AiError.RateLimited({ provider: \"elevenlabs-music\", raw: body })\n if (status === 408 || status === 504)\n return new AiError.Timeout({ provider: \"elevenlabs-music\", raw: body })\n if (status === 401)\n return new AiError.AuthFailed({ provider: \"elevenlabs-music\", subtype: \"auth\", raw: body })\n if (status === 403)\n return new AiError.AuthFailed({\n provider: \"elevenlabs-music\",\n subtype: \"permission\",\n raw: body,\n })\n if (status === 402)\n return new AiError.AuthFailed({\n provider: \"elevenlabs-music\",\n subtype: \"billing\",\n raw: body,\n })\n if (status >= 500)\n return new AiError.Unavailable({ provider: \"elevenlabs-music\", status, raw: body })\n return new AiError.InvalidRequest({ provider: \"elevenlabs-music\", raw: body })\n}\n\n// ---------------------------------------------------------------------------\n// Wire body\n// ---------------------------------------------------------------------------\n\n/**\n * Build the JSON body for `/v1/music` (sync + stream share the body).\n *\n * Mutual exclusion: `compositionPlan` and prompt-mode fields cannot\n * coexist. When `compositionPlan` is set, `prompt` must be empty and\n * `duration` must be unset (section durations live on the plan).\n */\nconst buildBody = (request: ElevenLabsMusicGenerateRequest) =>\n Effect.gen(function* () {\n const model = request.model ?? DEFAULT_MODEL\n if (request.compositionPlan !== undefined) {\n if (request.prompt.length > 0) {\n return yield* Effect.fail(\n new AiError.InvalidRequest({\n provider: \"elevenlabs-music\",\n param: \"prompt\",\n raw: \"`prompt` and `compositionPlan` are mutually exclusive. Pass one or the other (compositionPlan carries its own per-section lyrics and styles).\",\n }),\n )\n }\n if (request.duration !== undefined) {\n return yield* Effect.fail(\n new AiError.InvalidRequest({\n provider: \"elevenlabs-music\",\n param: \"duration\",\n raw: \"`duration` is ignored when `compositionPlan` is set; section durations live on the plan. Remove `duration`.\",\n }),\n )\n }\n return {\n composition_plan: wireCompositionPlan(request.compositionPlan),\n model_id: model,\n ...(request.seed !== undefined && { seed: request.seed }),\n ...(request.forceInstrumental !== undefined && {\n force_instrumental: request.forceInstrumental,\n }),\n ...(request.respectSectionsDurations !== undefined && {\n respect_sections_durations: request.respectSectionsDurations,\n }),\n ...(request.signWithC2pa !== undefined && { sign_with_c2pa: request.signWithC2pa }),\n }\n }\n yield* warnDroppedPromptModeHints(request as CommonGenerateMusicRequest)\n return {\n prompt: request.prompt,\n model_id: model,\n ...(request.duration !== undefined && {\n music_length_ms: Duration.toMillis(request.duration),\n }),\n ...(request.seed !== undefined && { seed: request.seed }),\n ...(request.forceInstrumental !== undefined && {\n force_instrumental: request.forceInstrumental,\n }),\n ...(request.signWithC2pa !== undefined && { sign_with_c2pa: request.signWithC2pa }),\n }\n })\n\nconst buildMusicHttpRequest = (\n cfg: Config,\n request: ElevenLabsMusicGenerateRequest,\n path: \"\" | \"/stream\",\n) =>\n Effect.gen(function* () {\n const format: AudioFormat = request.outputFormat ?? defaultFormat\n const slug = yield* formatToOutputSlug(format)\n const body = yield* buildBody(request)\n const url = `${resolveHost(cfg)}/music${path}?output_format=${slug}`\n const httpRequest = HttpClientRequest.post(url).pipe(\n HttpClientRequest.setHeader(\"xi-api-key\", Redacted.value(cfg.apiKey)),\n HttpClientRequest.bodyJsonUnsafe(body),\n )\n return { httpRequest, format }\n })\n\n// ---------------------------------------------------------------------------\n// Service implementation\n// ---------------------------------------------------------------------------\n\nconst generateImpl =\n (cfg: Config) =>\n (\n request: ElevenLabsMusicGenerateRequest,\n ): Effect.Effect<GenerateResult, AiError.AiError, HttpClient.HttpClient> =>\n Effect.gen(function* () {\n const client = yield* HttpClient.HttpClient\n const { httpRequest, format } = yield* buildMusicHttpRequest(cfg, request, \"\")\n const response = yield* client\n .execute(httpRequest)\n .pipe(Effect.mapError(musicTransportFailure))\n if (response.status >= 400) {\n const text = yield* response.text.pipe(Effect.orElseSucceed(() => \"\"))\n return yield* Effect.fail(musicHttpStatusError(response.status, text))\n }\n const buffer = yield* response.arrayBuffer.pipe(Effect.mapError(musicTransportFailure))\n const bytes = new Uint8Array(buffer)\n const songId = response.headers[\"song_id\"] ?? response.headers[\"x-song-id\"]\n const result: MusicResult = {\n audio: { format, bytes },\n provider: \"elevenlabs-music\",\n ...(typeof songId === \"string\" && { songId }),\n ...(request.signWithC2pa === true && { watermark: \"c2pa\" as const }),\n }\n return singleVariant(result)\n })\n\nconst streamGenerationImpl =\n (cfg: Config) =>\n (\n request: ElevenLabsMusicGenerateRequest,\n ): Stream.Stream<AudioChunk, AiError.AiError, HttpClient.HttpClient> =>\n Stream.unwrap(\n Effect.gen(function* () {\n const client = yield* HttpClient.HttpClient\n const { httpRequest } = yield* buildMusicHttpRequest(cfg, request, \"/stream\")\n const response = yield* client\n .execute(httpRequest)\n .pipe(Effect.mapError(musicTransportFailure))\n if (response.status >= 400) {\n const text = yield* response.text.pipe(Effect.orElseSucceed(() => \"\"))\n return Stream.fail(musicHttpStatusError(response.status, text))\n }\n return response.stream.pipe(\n Stream.mapError(musicTransportFailure),\n Stream.map((bytes): AudioChunk => ({ bytes })),\n )\n }),\n )\n\n/**\n * ElevenLabs music has no bidirectional session at the wire level.\n * Layer does not register `MusicInteractiveSession`, so callers using\n * `MusicGenerator.streamGenerationFrom` get a compile-time error\n * before this runtime fallback fires.\n */\nconst streamGenerationFromUnsupported = <E, R>(\n _input: Stream.Stream<MusicSessionInput, E, R>,\n _request: CommonStreamGenerateMusicRequest,\n): Stream.Stream<MusicStreamEvent, AiError.AiError | E, R> =>\n Stream.fail(\n new AiError.Unsupported({\n provider: \"elevenlabs-music\",\n capability: \"streamGenerationFrom\",\n reason:\n \"ElevenLabs music has no bidirectional session. Use `streamGeneration` for chunked output, or `createCompositionPlan` + `generate` for structured plans.\",\n }),\n )\n\nconst createCompositionPlanImpl =\n (cfg: Config) =>\n (\n request: CreateCompositionPlanRequest,\n ): Effect.Effect<ElevenLabsCompositionPlan, AiError.AiError, HttpClient.HttpClient> =>\n Effect.gen(function* () {\n const client = yield* HttpClient.HttpClient\n const body = {\n prompt: request.prompt,\n model_id: request.model ?? DEFAULT_MODEL,\n ...(request.duration !== undefined && {\n music_length_ms: Duration.toMillis(request.duration),\n }),\n ...(request.sourceCompositionPlan !== undefined && {\n source_composition_plan: wireCompositionPlan(request.sourceCompositionPlan),\n }),\n }\n const httpRequest = HttpClientRequest.post(`${resolveHost(cfg)}/music/plan`).pipe(\n HttpClientRequest.setHeader(\"xi-api-key\", Redacted.value(cfg.apiKey)),\n HttpClientRequest.bodyJsonUnsafe(body),\n )\n const response = yield* client\n .execute(httpRequest)\n .pipe(Effect.mapError(musicTransportFailure))\n if (response.status >= 400) {\n const text = yield* response.text.pipe(Effect.orElseSucceed(() => \"\"))\n return yield* Effect.fail(musicHttpStatusError(response.status, text))\n }\n const json = yield* response.json.pipe(Effect.mapError(musicTransportFailure))\n return decodeCompositionPlan(json)\n })\n\n// ---------------------------------------------------------------------------\n// Constructors\n// ---------------------------------------------------------------------------\n\nexport const make = (\n cfg: Config,\n): Effect.Effect<ElevenLabsMusicGeneratorService, never, HttpClient.HttpClient> =>\n Effect.map(HttpClient.HttpClient, (client) => ({\n generate: (request) =>\n generateImpl(cfg)(request).pipe(Effect.provideService(HttpClient.HttpClient, client)),\n streamGeneration: (request) =>\n streamGenerationImpl(cfg)(request).pipe(Stream.provideService(HttpClient.HttpClient, client)),\n streamGenerationFrom: streamGenerationFromUnsupported,\n createCompositionPlan: (request) =>\n createCompositionPlanImpl(cfg)(request).pipe(\n Effect.provideService(HttpClient.HttpClient, client),\n ),\n }))\n\n/**\n * Layer that registers the provider-specific `ElevenLabsMusicGenerator`\n * tag and the generic `MusicGenerator` tag.\n *\n * Does NOT register `MusicInteractiveSession`. ElevenLabs music has no\n * bidirectional wire endpoint; `streamGenerationFrom` against this\n * Layer alone fails to typecheck.\n */\nexport const layer = (\n cfg: Config,\n): Layer.Layer<ElevenLabsMusicGenerator | MusicGenerator, never, HttpClient.HttpClient> =>\n Layer.merge(\n Layer.effect(ElevenLabsMusicGenerator, make(cfg)),\n Layer.effect(\n MusicGenerator,\n Effect.map(make(cfg), (s): MusicGeneratorService => ({\n generate: (req: CommonGenerateMusicRequest) =>\n s.generate({ ...req, model: req.model as ElevenLabsMusicModel }),\n streamGeneration: (req: CommonStreamGenerateMusicRequest) =>\n s.streamGeneration({ ...req, model: req.model as ElevenLabsMusicModel }),\n streamGenerationFrom: s.streamGenerationFrom,\n })),\n ),\n )\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export {}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as describe, r as it, t as globalExpect } from "./test.DNmyFkvJ-N3QqMRwZ.mjs";
|
|
2
|
+
import { t as import_dist } from "./dist-C0AvqZTC.mjs";
|
|
2
3
|
import { ElevenLabsMusicGenerator, layer } from "./ElevenLabsMusicGenerator.mjs";
|
|
3
4
|
import { Duration, Effect, Layer, Redacted, Stream } from "effect";
|
|
4
5
|
import { FetchHttpClient } from "effect/unstable/http";
|
|
@@ -27,16 +28,18 @@ describe("ElevenLabsMusicGenerator Layer (compile-time)", () => {
|
|
|
27
28
|
model: "music_v1",
|
|
28
29
|
prompt: ""
|
|
29
30
|
}));
|
|
30
|
-
|
|
31
|
+
const provided = Stream.runDrain(events).pipe(Effect.provide(live));
|
|
32
|
+
(0, import_dist.expectTypeOf)(provided).toEqualTypeOf();
|
|
31
33
|
});
|
|
32
34
|
it("sync `generate` returns GenerateResult and requires no marker", () => {
|
|
33
|
-
|
|
35
|
+
const gen = MusicGenerator$1.generate({
|
|
34
36
|
model: "music_v1",
|
|
35
37
|
prompt: "house"
|
|
36
|
-
}).pipe(Effect.provide(live))
|
|
38
|
+
}).pipe(Effect.provide(live));
|
|
39
|
+
(0, import_dist.expectTypeOf)(gen).toEqualTypeOf();
|
|
37
40
|
});
|
|
38
41
|
it("typed request accepts compositionPlan, forceInstrumental, signWithC2pa", () => {
|
|
39
|
-
|
|
42
|
+
const _req = {
|
|
40
43
|
model: "music_v1",
|
|
41
44
|
prompt: "",
|
|
42
45
|
compositionPlan: {
|
|
@@ -52,7 +55,8 @@ describe("ElevenLabsMusicGenerator Layer (compile-time)", () => {
|
|
|
52
55
|
},
|
|
53
56
|
forceInstrumental: true,
|
|
54
57
|
signWithC2pa: true
|
|
55
|
-
}
|
|
58
|
+
};
|
|
59
|
+
globalExpect(_req).toBeDefined();
|
|
56
60
|
});
|
|
57
61
|
});
|
|
58
62
|
describe("ElevenLabsMusicGenerator codec validation (runtime, no HTTP)", () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ElevenLabsMusicGenerator.test.mjs","names":["ElevenLabsMusicGenerator.layer","MusicGenerator"],"sources":["../src/ElevenLabsMusicGenerator.test.ts"],"sourcesContent":["import { Duration, Effect, Layer, Redacted, Stream } from \"effect\"\nimport { FetchHttpClient } from \"effect/unstable/http\"\nimport { describe, expect, expectTypeOf, it } from \"vitest\"\nimport type * as AiError from \"@effect-uai/core/AiError\"\nimport type { GenerateResult } from \"@effect-uai/core/Music\"\nimport { promptsInput } from \"@effect-uai/core/Music\"\nimport * as MusicGenerator from \"@effect-uai/core/MusicGenerator\"\nimport * as ElevenLabsMusicGenerator from \"./ElevenLabsMusicGenerator.js\"\n\nconst cfg: ElevenLabsMusicGenerator.Config = { apiKey: Redacted.make(\"test-key\") }\nconst live = Layer.provide(ElevenLabsMusicGenerator.layer(cfg), FetchHttpClient.layer)\n\ndescribe(\"ElevenLabsMusicGenerator capability guards (runtime)\", () => {\n it(\"streamGenerationFrom returns an Unsupported stream\", async () => {\n const program = ElevenLabsMusicGenerator.ElevenLabsMusicGenerator.use((s) =>\n Stream.runDrain(\n s.streamGenerationFrom(Stream.fromIterable([promptsInput([{ text: \"x\" }])]), {\n model: \"music_v1\",\n prompt: \"\",\n }),\n ),\n )\n const exit = await Effect.runPromiseExit(program.pipe(Effect.provide(live)))\n expect(exit._tag).toBe(\"Failure\")\n if (exit._tag === \"Failure\") {\n expect(JSON.stringify(exit.cause)).toContain(\"Unsupported\")\n expect(JSON.stringify(exit.cause)).toContain(\"streamGenerationFrom\")\n }\n })\n})\n\ndescribe(\"ElevenLabsMusicGenerator Layer (compile-time)\", () => {\n it(\"leaves `MusicInteractiveSession` unsatisfied via the generic surface\", () => {\n const inputs = Stream.fromIterable([promptsInput([{ text: \"techno\" }])])\n const events = inputs.pipe(\n MusicGenerator.streamGenerationFrom({ model: \"music_v1\", prompt: \"\" }),\n )\n const provided = Stream.runDrain(events).pipe(Effect.provide(live))\n expectTypeOf(provided).toEqualTypeOf<\n Effect.Effect<void, AiError.AiError, MusicGenerator.MusicInteractiveSession>\n >()\n })\n\n it(\"sync `generate` returns GenerateResult and requires no marker\", () => {\n const gen = MusicGenerator.generate({ model: \"music_v1\", prompt: \"house\" }).pipe(\n Effect.provide(live),\n )\n expectTypeOf(gen).toEqualTypeOf<Effect.Effect<GenerateResult, AiError.AiError, never>>()\n })\n\n it(\"typed request accepts compositionPlan, forceInstrumental, signWithC2pa\", () => {\n const _req: ElevenLabsMusicGenerator.ElevenLabsMusicGenerateRequest = {\n model: \"music_v1\",\n prompt: \"\",\n compositionPlan: {\n positiveGlobalStyles: [\"lo-fi\", \"warm\"],\n negativeGlobalStyles: [\"distorted\"],\n sections: [\n {\n sectionName: \"Intro\",\n positiveLocalStyles: [\"piano\"],\n negativeLocalStyles: [],\n duration: Duration.seconds(15),\n lines: [],\n },\n ],\n },\n forceInstrumental: true,\n signWithC2pa: true,\n }\n expect(_req).toBeDefined()\n })\n})\n\ndescribe(\"ElevenLabsMusicGenerator codec validation (runtime, no HTTP)\", () => {\n it(\"rejects compositionPlan + non-empty prompt\", async () => {\n const program = ElevenLabsMusicGenerator.ElevenLabsMusicGenerator.use((s) =>\n s.generate({\n model: \"music_v1\",\n prompt: \"house\",\n compositionPlan: {\n positiveGlobalStyles: [],\n negativeGlobalStyles: [],\n sections: [],\n },\n }),\n )\n const exit = await Effect.runPromiseExit(program.pipe(Effect.provide(live)))\n expect(exit._tag).toBe(\"Failure\")\n if (exit._tag === \"Failure\") {\n expect(JSON.stringify(exit.cause)).toContain(\"InvalidRequest\")\n expect(JSON.stringify(exit.cause)).toContain(\"mutually exclusive\")\n }\n })\n\n it(\"rejects compositionPlan + duration\", async () => {\n const program = ElevenLabsMusicGenerator.ElevenLabsMusicGenerator.use((s) =>\n s.generate({\n model: \"music_v1\",\n prompt: \"\",\n duration: Duration.seconds(30),\n compositionPlan: {\n positiveGlobalStyles: [],\n negativeGlobalStyles: [],\n sections: [],\n },\n }),\n )\n const exit = await Effect.runPromiseExit(program.pipe(Effect.provide(live)))\n expect(exit._tag).toBe(\"Failure\")\n if (exit._tag === \"Failure\") {\n expect(JSON.stringify(exit.cause)).toContain(\"InvalidRequest\")\n expect(JSON.stringify(exit.cause)).toContain(\"`duration` is ignored\")\n }\n })\n})\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"ElevenLabsMusicGenerator.test.mjs","names":["ElevenLabsMusicGenerator.layer","MusicGenerator"],"sources":["../src/ElevenLabsMusicGenerator.test.ts"],"sourcesContent":["import { Duration, Effect, Layer, Redacted, Stream } from \"effect\"\nimport { FetchHttpClient } from \"effect/unstable/http\"\nimport { describe, expect, expectTypeOf, it } from \"vitest\"\nimport type * as AiError from \"@effect-uai/core/AiError\"\nimport type { GenerateResult } from \"@effect-uai/core/Music\"\nimport { promptsInput } from \"@effect-uai/core/Music\"\nimport * as MusicGenerator from \"@effect-uai/core/MusicGenerator\"\nimport * as ElevenLabsMusicGenerator from \"./ElevenLabsMusicGenerator.js\"\n\nconst cfg: ElevenLabsMusicGenerator.Config = { apiKey: Redacted.make(\"test-key\") }\nconst live = Layer.provide(ElevenLabsMusicGenerator.layer(cfg), FetchHttpClient.layer)\n\ndescribe(\"ElevenLabsMusicGenerator capability guards (runtime)\", () => {\n it(\"streamGenerationFrom returns an Unsupported stream\", async () => {\n const program = ElevenLabsMusicGenerator.ElevenLabsMusicGenerator.use((s) =>\n Stream.runDrain(\n s.streamGenerationFrom(Stream.fromIterable([promptsInput([{ text: \"x\" }])]), {\n model: \"music_v1\",\n prompt: \"\",\n }),\n ),\n )\n const exit = await Effect.runPromiseExit(program.pipe(Effect.provide(live)))\n expect(exit._tag).toBe(\"Failure\")\n if (exit._tag === \"Failure\") {\n expect(JSON.stringify(exit.cause)).toContain(\"Unsupported\")\n expect(JSON.stringify(exit.cause)).toContain(\"streamGenerationFrom\")\n }\n })\n})\n\ndescribe(\"ElevenLabsMusicGenerator Layer (compile-time)\", () => {\n it(\"leaves `MusicInteractiveSession` unsatisfied via the generic surface\", () => {\n const inputs = Stream.fromIterable([promptsInput([{ text: \"techno\" }])])\n const events = inputs.pipe(\n MusicGenerator.streamGenerationFrom({ model: \"music_v1\", prompt: \"\" }),\n )\n const provided = Stream.runDrain(events).pipe(Effect.provide(live))\n expectTypeOf(provided).toEqualTypeOf<\n Effect.Effect<void, AiError.AiError, MusicGenerator.MusicInteractiveSession>\n >()\n })\n\n it(\"sync `generate` returns GenerateResult and requires no marker\", () => {\n const gen = MusicGenerator.generate({ model: \"music_v1\", prompt: \"house\" }).pipe(\n Effect.provide(live),\n )\n expectTypeOf(gen).toEqualTypeOf<Effect.Effect<GenerateResult, AiError.AiError, never>>()\n })\n\n it(\"typed request accepts compositionPlan, forceInstrumental, signWithC2pa\", () => {\n const _req: ElevenLabsMusicGenerator.ElevenLabsMusicGenerateRequest = {\n model: \"music_v1\",\n prompt: \"\",\n compositionPlan: {\n positiveGlobalStyles: [\"lo-fi\", \"warm\"],\n negativeGlobalStyles: [\"distorted\"],\n sections: [\n {\n sectionName: \"Intro\",\n positiveLocalStyles: [\"piano\"],\n negativeLocalStyles: [],\n duration: Duration.seconds(15),\n lines: [],\n },\n ],\n },\n forceInstrumental: true,\n signWithC2pa: true,\n }\n expect(_req).toBeDefined()\n })\n})\n\ndescribe(\"ElevenLabsMusicGenerator codec validation (runtime, no HTTP)\", () => {\n it(\"rejects compositionPlan + non-empty prompt\", async () => {\n const program = ElevenLabsMusicGenerator.ElevenLabsMusicGenerator.use((s) =>\n s.generate({\n model: \"music_v1\",\n prompt: \"house\",\n compositionPlan: {\n positiveGlobalStyles: [],\n negativeGlobalStyles: [],\n sections: [],\n },\n }),\n )\n const exit = await Effect.runPromiseExit(program.pipe(Effect.provide(live)))\n expect(exit._tag).toBe(\"Failure\")\n if (exit._tag === \"Failure\") {\n expect(JSON.stringify(exit.cause)).toContain(\"InvalidRequest\")\n expect(JSON.stringify(exit.cause)).toContain(\"mutually exclusive\")\n }\n })\n\n it(\"rejects compositionPlan + duration\", async () => {\n const program = ElevenLabsMusicGenerator.ElevenLabsMusicGenerator.use((s) =>\n s.generate({\n model: \"music_v1\",\n prompt: \"\",\n duration: Duration.seconds(30),\n compositionPlan: {\n positiveGlobalStyles: [],\n negativeGlobalStyles: [],\n sections: [],\n },\n }),\n )\n const exit = await Effect.runPromiseExit(program.pipe(Effect.provide(live)))\n expect(exit._tag).toBe(\"Failure\")\n if (exit._tag === \"Failure\") {\n expect(JSON.stringify(exit.cause)).toContain(\"InvalidRequest\")\n expect(JSON.stringify(exit.cause)).toContain(\"`duration` is ignored\")\n }\n })\n})\n"],"mappings":";;;;;;;;AASA,MAAM,MAAuC,EAAE,QAAQ,SAAS,KAAK,UAAU,EAAE;AACjF,MAAM,OAAO,MAAM,QAAQA,MAA+B,GAAG,GAAG,gBAAgB,KAAK;AAErF,SAAS,8DAA8D;CACrE,GAAG,sDAAsD,YAAY;EACnE,MAAM,UAAA,yBAA4D,KAAK,MACrE,OAAO,SACL,EAAE,qBAAqB,OAAO,aAAa,CAAC,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG;GAC3E,OAAO;GACP,QAAQ;EACV,CAAC,CACH,CACF;EACA,MAAM,OAAO,MAAM,OAAO,eAAe,QAAQ,KAAK,OAAO,QAAQ,IAAI,CAAC,CAAC;EAC3E,aAAO,KAAK,IAAI,CAAC,CAAC,KAAK,SAAS;EAChC,IAAI,KAAK,SAAS,WAAW;GAC3B,aAAO,KAAK,UAAU,KAAK,KAAK,CAAC,CAAC,CAAC,UAAU,aAAa;GAC1D,aAAO,KAAK,UAAU,KAAK,KAAK,CAAC,CAAC,CAAC,UAAU,sBAAsB;EACrE;CACF,CAAC;AACH,CAAC;AAED,SAAS,uDAAuD;CAC9D,GAAG,8EAA8E;EAE/E,MAAM,SADS,OAAO,aAAa,CAAC,aAAa,CAAC,EAAE,MAAM,SAAS,CAAC,CAAC,CAAC,CAClD,CAAC,CAAC,KACpBC,iBAAe,qBAAqB;GAAE,OAAO;GAAY,QAAQ;EAAG,CAAC,CACvE;EACA,MAAM,WAAW,OAAO,SAAS,MAAM,CAAC,CAAC,KAAK,OAAO,QAAQ,IAAI,CAAC;EAClE,CAAA,GAAA,YAAA,aAAA,CAAa,QAAQ,CAAC,CAAC,cAErB;CACJ,CAAC;CAED,GAAG,uEAAuE;EACxE,MAAM,MAAMA,iBAAe,SAAS;GAAE,OAAO;GAAY,QAAQ;EAAQ,CAAC,CAAC,CAAC,KAC1E,OAAO,QAAQ,IAAI,CACrB;EACA,CAAA,GAAA,YAAA,aAAA,CAAa,GAAG,CAAC,CAAC,cAAqE;CACzF,CAAC;CAED,GAAG,gFAAgF;EACjF,MAAM,OAAgE;GACpE,OAAO;GACP,QAAQ;GACR,iBAAiB;IACf,sBAAsB,CAAC,SAAS,MAAM;IACtC,sBAAsB,CAAC,WAAW;IAClC,UAAU,CACR;KACE,aAAa;KACb,qBAAqB,CAAC,OAAO;KAC7B,qBAAqB,CAAC;KACtB,UAAU,SAAS,QAAQ,EAAE;KAC7B,OAAO,CAAC;IACV,CACF;GACF;GACA,mBAAmB;GACnB,cAAc;EAChB;EACA,aAAO,IAAI,CAAC,CAAC,YAAY;CAC3B,CAAC;AACH,CAAC;AAED,SAAS,sEAAsE;CAC7E,GAAG,8CAA8C,YAAY;EAC3D,MAAM,UAAA,yBAA4D,KAAK,MACrE,EAAE,SAAS;GACT,OAAO;GACP,QAAQ;GACR,iBAAiB;IACf,sBAAsB,CAAC;IACvB,sBAAsB,CAAC;IACvB,UAAU,CAAC;GACb;EACF,CAAC,CACH;EACA,MAAM,OAAO,MAAM,OAAO,eAAe,QAAQ,KAAK,OAAO,QAAQ,IAAI,CAAC,CAAC;EAC3E,aAAO,KAAK,IAAI,CAAC,CAAC,KAAK,SAAS;EAChC,IAAI,KAAK,SAAS,WAAW;GAC3B,aAAO,KAAK,UAAU,KAAK,KAAK,CAAC,CAAC,CAAC,UAAU,gBAAgB;GAC7D,aAAO,KAAK,UAAU,KAAK,KAAK,CAAC,CAAC,CAAC,UAAU,oBAAoB;EACnE;CACF,CAAC;CAED,GAAG,sCAAsC,YAAY;EACnD,MAAM,UAAA,yBAA4D,KAAK,MACrE,EAAE,SAAS;GACT,OAAO;GACP,QAAQ;GACR,UAAU,SAAS,QAAQ,EAAE;GAC7B,iBAAiB;IACf,sBAAsB,CAAC;IACvB,sBAAsB,CAAC;IACvB,UAAU,CAAC;GACb;EACF,CAAC,CACH;EACA,MAAM,OAAO,MAAM,OAAO,eAAe,QAAQ,KAAK,OAAO,QAAQ,IAAI,CAAC,CAAC;EAC3E,aAAO,KAAK,IAAI,CAAC,CAAC,KAAK,SAAS;EAChC,IAAI,KAAK,SAAS,WAAW;GAC3B,aAAO,KAAK,UAAU,KAAK,KAAK,CAAC,CAAC,CAAC,UAAU,gBAAgB;GAC7D,aAAO,KAAK,UAAU,KAAK,KAAK,CAAC,CAAC,CAAC,UAAU,uBAAuB;EACtE;CACF,CAAC;AACH,CAAC"}
|
|
@@ -6,10 +6,7 @@ import { HttpClient } from "effect/unstable/http";
|
|
|
6
6
|
import * as AiError from "@effect-uai/core/AiError";
|
|
7
7
|
import * as Socket from "effect/unstable/socket/Socket";
|
|
8
8
|
import { CommonStreamSynthesizeRequest, CommonSynthesizeDialogueRequest, CommonSynthesizeRequest, MultiSpeakerTts, SpeechSynthesizer, SpeechSynthesizerService, TtsIncrementalText } from "@effect-uai/core/SpeechSynthesizer";
|
|
9
|
-
import * as _$_effect_uai_core_Audio0 from "@effect-uai/core/Audio";
|
|
10
9
|
import { AudioBlob, AudioChunk } from "@effect-uai/core/Audio";
|
|
11
|
-
|
|
12
|
-
//#region src/ElevenLabsSynthesizer.d.ts
|
|
13
10
|
declare namespace ElevenLabsSynthesizer_d_exports {
|
|
14
11
|
export { Config, ElevenLabsSynthesizeRequest, ElevenLabsSynthesizer, ElevenLabsSynthesizerService, layer, make };
|
|
15
12
|
}
|
|
@@ -49,13 +46,13 @@ type Config = {
|
|
|
49
46
|
};
|
|
50
47
|
declare const make: (cfg: Config) => Effect.Effect<{
|
|
51
48
|
synthesize: (r: ElevenLabsSynthesizeRequest) => Effect.Effect<{
|
|
52
|
-
format:
|
|
49
|
+
format: import("@effect-uai/core/Audio").AudioFormat;
|
|
53
50
|
bytes: Uint8Array<ArrayBuffer>;
|
|
54
51
|
}, AiError.AiError, never>;
|
|
55
52
|
streamSynthesis: (r: ElevenLabsSynthesizeRequest) => Stream.Stream<AudioChunk, AiError.AiError, never>;
|
|
56
|
-
streamSynthesisFrom: <E, R>(textIn: Stream.Stream<string, E, R>, request: CommonStreamSynthesizeRequest) => Stream.Stream<AudioChunk, AiError.AiError
|
|
53
|
+
streamSynthesisFrom: <E, R>(textIn: Stream.Stream<string, E, R>, request: CommonStreamSynthesizeRequest) => Stream.Stream<AudioChunk, E | AiError.AiError, Exclude<R, Socket.WebSocketConstructor>>;
|
|
57
54
|
synthesizeDialogue: (request: CommonSynthesizeDialogueRequest) => Effect.Effect<{
|
|
58
|
-
format:
|
|
55
|
+
format: import("@effect-uai/core/Audio").AudioFormat;
|
|
59
56
|
bytes: Uint8Array<ArrayBuffer>;
|
|
60
57
|
}, AiError.AiError, never>;
|
|
61
58
|
streamSynthesizeDialogue: (request: CommonSynthesizeDialogueRequest) => Stream.Stream<AudioChunk, AiError.AiError, never>;
|
|
@@ -69,7 +66,7 @@ declare const make: (cfg: Config) => Effect.Effect<{
|
|
|
69
66
|
* `Socket.layerWebSocketConstructorGlobal` and an `HttpClient` Layer
|
|
70
67
|
* at the call site.
|
|
71
68
|
*/
|
|
72
|
-
declare const layer: (cfg: Config) => Layer.Layer<ElevenLabsSynthesizer |
|
|
69
|
+
declare const layer: (cfg: Config) => Layer.Layer<ElevenLabsSynthesizer | MultiSpeakerTts | SpeechSynthesizer | TtsIncrementalText, never, HttpClient.HttpClient | Socket.WebSocketConstructor>;
|
|
73
70
|
//#endregion
|
|
74
71
|
export { Config, ElevenLabsSynthesizeRequest, ElevenLabsSynthesizer, ElevenLabsSynthesizerService, layer, make, ElevenLabsSynthesizer_d_exports as t };
|
|
75
72
|
//# sourceMappingURL=ElevenLabsSynthesizer.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ElevenLabsSynthesizer.d.mts","names":[],"sources":["../src/ElevenLabsSynthesizer.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"ElevenLabsSynthesizer.d.mts","names":[],"sources":["../src/ElevenLabsSynthesizer.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;KA4CY,8BAA8B,KAAK;WACpC,OAAO;WACP,SAAS;WACT,gBAAgB;WAChB;WACA;WACA;WACA,kCAAkC,cAAc;;KAG/C;WACD,aAAa,GAAG,gCAAgC,OAAO,OAAO,WAAW,QAAQ;WACjF,kBACP,GAAG,gCACA,OAAO,OAAO,YAAY,QAAQ;WAC9B,qBAAqB;WACrB,oBAAoB;WACpB,0BAA0B;;;cAGxB,8BAA8B;KAK/B;WACD,QAAQ,SAAS;WACjB;WACA,SAAS;;cAqIP,OAAI,KAAS,WAAM,OAAA;;;;;;;;;;;;UAsB5B,WAAA,aAAA,OAAA;;;;;;;;;;cAWS,QAAK,KAAS,WAAM,MAAA,MAAA,wBAAA,kBAAA,oBAAA,2BAAA,WAAA,aAAA,OAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as __exportAll } from "./
|
|
1
|
+
import { n as __exportAll } from "./rolldown-runtime-EAsCxrDo.mjs";
|
|
2
2
|
import { defaultFormat, formatToOutputSlug, httpStatusError, rejectInlinePronunciations, transportFailure, wirePronunciationLocators, wireVoiceSettings } from "./codec.mjs";
|
|
3
3
|
import { resolveHost } from "./region.mjs";
|
|
4
4
|
import { streamSynthesis } from "./realtimeTts.mjs";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ElevenLabsSynthesizer.mjs","names":["realtimeStream"],"sources":["../src/ElevenLabsSynthesizer.ts"],"sourcesContent":["import { Context, Effect, Layer, Redacted, Stream } from \"effect\"\nimport { HttpClient, HttpClientRequest } from \"effect/unstable/http\"\nimport * as Socket from \"effect/unstable/socket/Socket\"\nimport type * as AiError from \"@effect-uai/core/AiError\"\nimport type { AudioBlob, AudioChunk } from \"@effect-uai/core/Audio\"\nimport {\n type CommonStreamSynthesizeRequest,\n type CommonSynthesizeDialogueRequest,\n type CommonSynthesizeRequest,\n MultiSpeakerTts,\n SpeechSynthesizer,\n type SpeechSynthesizerService,\n TtsIncrementalText,\n} from \"@effect-uai/core/SpeechSynthesizer\"\nimport {\n defaultFormat,\n formatToOutputSlug,\n httpStatusError,\n type PronunciationDictionaryLocator,\n rejectInlinePronunciations,\n transportFailure,\n type VoiceSettings,\n wirePronunciationLocators,\n wireVoiceSettings,\n} from \"./codec.js\"\nimport type { ElevenLabsTtsModel, ElevenLabsVoiceId } from \"./models.js\"\nimport { streamSynthesis as realtimeStream } from \"./realtimeTts.js\"\nimport { type ElevenLabsRegion, resolveHost } from \"./region.js\"\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/**\n * ElevenLabs-typed synthesize request. `voiceSettings` exposes the\n * provider's prosody/timbre controls; `seed` makes generation\n * deterministic; `previousText` / `nextText` thread context across\n * sequential calls for natural prosody.\n *\n * `pronunciationDictionaryLocators` references pre-provisioned\n * pronunciation dictionaries by ID. Inline `pronunciations` (IPA) on\n * the Common request are not supported by ElevenLabs and fail\n * `Unsupported`; use a dictionary for phonetic control.\n */\nexport type ElevenLabsSynthesizeRequest = Omit<CommonSynthesizeRequest, \"model\" | \"voiceId\"> & {\n readonly model: ElevenLabsTtsModel\n readonly voiceId: ElevenLabsVoiceId\n readonly voiceSettings?: VoiceSettings\n readonly seed?: number\n readonly previousText?: string\n readonly nextText?: string\n readonly pronunciationDictionaryLocators?: ReadonlyArray<PronunciationDictionaryLocator>\n}\n\nexport type ElevenLabsSynthesizerService = {\n readonly synthesize: (r: ElevenLabsSynthesizeRequest) => Effect.Effect<AudioBlob, AiError.AiError>\n readonly streamSynthesis: (\n r: ElevenLabsSynthesizeRequest,\n ) => Stream.Stream<AudioChunk, AiError.AiError>\n readonly streamSynthesisFrom: SpeechSynthesizerService[\"streamSynthesisFrom\"]\n readonly synthesizeDialogue: SpeechSynthesizerService[\"synthesizeDialogue\"]\n readonly streamSynthesizeDialogue: SpeechSynthesizerService[\"streamSynthesizeDialogue\"]\n}\n\nexport class ElevenLabsSynthesizer extends Context.Service<\n ElevenLabsSynthesizer,\n ElevenLabsSynthesizerService\n>()(\"@betalyra/effect-uai/providers/elevenlabs/ElevenLabsSynthesizer\") {}\n\nexport type Config = {\n readonly apiKey: Redacted.Redacted\n readonly baseUrl?: string\n readonly region?: ElevenLabsRegion\n}\n\n// ---------------------------------------------------------------------------\n// Codec — request → JSON body\n// ---------------------------------------------------------------------------\n\nconst buildBody = (r: ElevenLabsSynthesizeRequest) => ({\n text: r.text,\n model_id: r.model,\n ...(r.languageCode !== undefined && { language_code: r.languageCode }),\n ...(r.seed !== undefined && { seed: r.seed }),\n ...(r.previousText !== undefined && { previous_text: r.previousText }),\n ...(r.nextText !== undefined && { next_text: r.nextText }),\n ...wirePronunciationLocators(r.pronunciationDictionaryLocators),\n ...(r.voiceSettings !== undefined && { voice_settings: wireVoiceSettings(r.voiceSettings) }),\n})\n\n// ---------------------------------------------------------------------------\n// Dialogue — POST /v1/text-to-dialogue (+ /stream variant)\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_DIALOGUE_MODEL = \"eleven_v3\"\n\nconst buildDialogueBody = (r: CommonSynthesizeDialogueRequest) => ({\n inputs: r.turns.map((t) => ({\n voice_id: t.voiceId,\n text: t.text,\n })),\n model_id: r.model ?? DEFAULT_DIALOGUE_MODEL,\n ...(r.languageCode !== undefined && { language_code: r.languageCode }),\n})\n\nconst buildDialogueHttpRequest = (\n cfg: Config,\n r: CommonSynthesizeDialogueRequest,\n path: \"\" | \"/stream\",\n) =>\n Effect.gen(function* () {\n const format = r.outputFormat ?? defaultFormat\n const slug = yield* formatToOutputSlug(format)\n const url = `${resolveHost(cfg)}/text-to-dialogue${path}?output_format=${slug}`\n const httpRequest = HttpClientRequest.post(url).pipe(\n HttpClientRequest.setHeader(\"xi-api-key\", Redacted.value(cfg.apiKey)),\n HttpClientRequest.bodyJsonUnsafe(buildDialogueBody(r)),\n )\n return { httpRequest, format }\n })\n\nconst synthesizeDialogueImpl = (cfg: Config) => (request: CommonSynthesizeDialogueRequest) =>\n Effect.gen(function* () {\n yield* rejectInlinePronunciations(request.pronunciations)\n const client = yield* HttpClient.HttpClient\n const { httpRequest, format } = yield* buildDialogueHttpRequest(cfg, request, \"\")\n const response = yield* client.execute(httpRequest).pipe(Effect.mapError(transportFailure))\n if (response.status >= 400) {\n const text = yield* response.text.pipe(Effect.orElseSucceed(() => \"\"))\n return yield* Effect.fail(httpStatusError(response.status, text))\n }\n const bytes = yield* response.arrayBuffer.pipe(Effect.mapError(transportFailure))\n return { format, bytes: new Uint8Array(bytes) } satisfies AudioBlob\n })\n\nconst streamSynthesizeDialogueImpl = (cfg: Config) => (request: CommonSynthesizeDialogueRequest) =>\n Stream.unwrap(\n Effect.gen(function* () {\n yield* rejectInlinePronunciations(request.pronunciations)\n const client = yield* HttpClient.HttpClient\n const { httpRequest } = yield* buildDialogueHttpRequest(cfg, request, \"/stream\")\n const response = yield* client.execute(httpRequest).pipe(Effect.mapError(transportFailure))\n if (response.status >= 400) {\n const text = yield* response.text.pipe(Effect.orElseSucceed(() => \"\"))\n return Stream.fail(httpStatusError(response.status, text))\n }\n return response.stream.pipe(\n Stream.mapError(transportFailure),\n Stream.map((bytes): AudioChunk => ({ bytes })),\n )\n }),\n )\n\n// ---------------------------------------------------------------------------\n// HTTP plumbing (sync + chunked-HTTP streaming)\n// ---------------------------------------------------------------------------\n\nconst buildHttpRequest = (cfg: Config, r: ElevenLabsSynthesizeRequest, path: \"\" | \"/stream\") =>\n Effect.gen(function* () {\n const format = r.outputFormat ?? defaultFormat\n const slug = yield* formatToOutputSlug(format)\n const url = `${resolveHost(cfg)}/text-to-speech/${r.voiceId}${path}?output_format=${slug}`\n const httpRequest = HttpClientRequest.post(url).pipe(\n HttpClientRequest.setHeader(\"xi-api-key\", Redacted.value(cfg.apiKey)),\n HttpClientRequest.bodyJsonUnsafe(buildBody(r)),\n )\n return { httpRequest, format }\n })\n\nconst synthesizeImpl = (cfg: Config) => (request: ElevenLabsSynthesizeRequest) =>\n Effect.gen(function* () {\n yield* rejectInlinePronunciations(request.pronunciations)\n const client = yield* HttpClient.HttpClient\n const { httpRequest, format } = yield* buildHttpRequest(cfg, request, \"\")\n const response = yield* client.execute(httpRequest).pipe(Effect.mapError(transportFailure))\n if (response.status >= 400) {\n const text = yield* response.text.pipe(Effect.orElseSucceed(() => \"\"))\n return yield* Effect.fail(httpStatusError(response.status, text))\n }\n const bytes = yield* response.arrayBuffer.pipe(Effect.mapError(transportFailure))\n return { format, bytes: new Uint8Array(bytes) } satisfies AudioBlob\n })\n\nconst streamSynthesisImpl = (cfg: Config) => (request: ElevenLabsSynthesizeRequest) =>\n Stream.unwrap(\n Effect.gen(function* () {\n yield* rejectInlinePronunciations(request.pronunciations)\n const client = yield* HttpClient.HttpClient\n const { httpRequest } = yield* buildHttpRequest(cfg, request, \"/stream\")\n const response = yield* client.execute(httpRequest).pipe(Effect.mapError(transportFailure))\n if (response.status >= 400) {\n const text = yield* response.text.pipe(Effect.orElseSucceed(() => \"\"))\n return Stream.fail(httpStatusError(response.status, text))\n }\n return response.stream.pipe(\n Stream.mapError(transportFailure),\n Stream.map((bytes): AudioChunk => ({ bytes })),\n )\n }),\n )\n\n// ---------------------------------------------------------------------------\n// Constructors\n// ---------------------------------------------------------------------------\n\nexport const make = (cfg: Config) =>\n Effect.gen(function* () {\n const client = yield* HttpClient.HttpClient\n const ctor = yield* Socket.WebSocketConstructor\n return {\n synthesize: (r) =>\n synthesizeImpl(cfg)(r).pipe(Effect.provideService(HttpClient.HttpClient, client)),\n streamSynthesis: (r) =>\n streamSynthesisImpl(cfg)(r).pipe(Stream.provideService(HttpClient.HttpClient, client)),\n streamSynthesisFrom: (textIn, request) =>\n realtimeStream(cfg)(textIn, request as ElevenLabsSynthesizeRequest).pipe(\n Stream.provideService(Socket.WebSocketConstructor, ctor),\n ),\n synthesizeDialogue: (request) =>\n synthesizeDialogueImpl(cfg)(request).pipe(\n Effect.provideService(HttpClient.HttpClient, client),\n ),\n streamSynthesizeDialogue: (request) =>\n streamSynthesizeDialogueImpl(cfg)(request).pipe(\n Stream.provideService(HttpClient.HttpClient, client),\n ),\n } satisfies ElevenLabsSynthesizerService\n })\n\n/**\n * Layer registers `ElevenLabsSynthesizer`, the generic\n * `SpeechSynthesizer`, the `TtsIncrementalText` marker (incremental\n * text-in via `/stream-input` WebSocket), **and `MultiSpeakerTts`** —\n * multi-speaker dialogue is wired to `POST /v1/text-to-dialogue`\n * (sync) and `/v1/text-to-dialogue/stream` (chunked). Provide\n * `Socket.layerWebSocketConstructorGlobal` and an `HttpClient` Layer\n * at the call site.\n */\nexport const layer = (cfg: Config) =>\n Layer.mergeAll(\n Layer.effect(ElevenLabsSynthesizer, make(cfg)),\n Layer.effect(\n SpeechSynthesizer,\n Effect.map(\n make(cfg),\n (s): SpeechSynthesizerService => ({\n synthesize: (req: CommonSynthesizeRequest) =>\n s.synthesize(req as ElevenLabsSynthesizeRequest),\n streamSynthesis: (req: CommonSynthesizeRequest) =>\n s.streamSynthesis(req as ElevenLabsSynthesizeRequest),\n streamSynthesisFrom: (textIn, req: CommonStreamSynthesizeRequest) =>\n s.streamSynthesisFrom(textIn, req),\n synthesizeDialogue: s.synthesizeDialogue,\n streamSynthesizeDialogue: s.streamSynthesizeDialogue,\n }),\n ),\n ),\n Layer.succeed(TtsIncrementalText, undefined),\n Layer.succeed(MultiSpeakerTts, undefined),\n )\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ElevenLabsSynthesizer.mjs","names":["realtimeStream"],"sources":["../src/ElevenLabsSynthesizer.ts"],"sourcesContent":["import { Context, Effect, Layer, Redacted, Stream } from \"effect\"\nimport { HttpClient, HttpClientRequest } from \"effect/unstable/http\"\nimport * as Socket from \"effect/unstable/socket/Socket\"\nimport type * as AiError from \"@effect-uai/core/AiError\"\nimport type { AudioBlob, AudioChunk } from \"@effect-uai/core/Audio\"\nimport {\n type CommonStreamSynthesizeRequest,\n type CommonSynthesizeDialogueRequest,\n type CommonSynthesizeRequest,\n MultiSpeakerTts,\n SpeechSynthesizer,\n type SpeechSynthesizerService,\n TtsIncrementalText,\n} from \"@effect-uai/core/SpeechSynthesizer\"\nimport {\n defaultFormat,\n formatToOutputSlug,\n httpStatusError,\n type PronunciationDictionaryLocator,\n rejectInlinePronunciations,\n transportFailure,\n type VoiceSettings,\n wirePronunciationLocators,\n wireVoiceSettings,\n} from \"./codec.js\"\nimport type { ElevenLabsTtsModel, ElevenLabsVoiceId } from \"./models.js\"\nimport { streamSynthesis as realtimeStream } from \"./realtimeTts.js\"\nimport { type ElevenLabsRegion, resolveHost } from \"./region.js\"\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/**\n * ElevenLabs-typed synthesize request. `voiceSettings` exposes the\n * provider's prosody/timbre controls; `seed` makes generation\n * deterministic; `previousText` / `nextText` thread context across\n * sequential calls for natural prosody.\n *\n * `pronunciationDictionaryLocators` references pre-provisioned\n * pronunciation dictionaries by ID. Inline `pronunciations` (IPA) on\n * the Common request are not supported by ElevenLabs and fail\n * `Unsupported`; use a dictionary for phonetic control.\n */\nexport type ElevenLabsSynthesizeRequest = Omit<CommonSynthesizeRequest, \"model\" | \"voiceId\"> & {\n readonly model: ElevenLabsTtsModel\n readonly voiceId: ElevenLabsVoiceId\n readonly voiceSettings?: VoiceSettings\n readonly seed?: number\n readonly previousText?: string\n readonly nextText?: string\n readonly pronunciationDictionaryLocators?: ReadonlyArray<PronunciationDictionaryLocator>\n}\n\nexport type ElevenLabsSynthesizerService = {\n readonly synthesize: (r: ElevenLabsSynthesizeRequest) => Effect.Effect<AudioBlob, AiError.AiError>\n readonly streamSynthesis: (\n r: ElevenLabsSynthesizeRequest,\n ) => Stream.Stream<AudioChunk, AiError.AiError>\n readonly streamSynthesisFrom: SpeechSynthesizerService[\"streamSynthesisFrom\"]\n readonly synthesizeDialogue: SpeechSynthesizerService[\"synthesizeDialogue\"]\n readonly streamSynthesizeDialogue: SpeechSynthesizerService[\"streamSynthesizeDialogue\"]\n}\n\nexport class ElevenLabsSynthesizer extends Context.Service<\n ElevenLabsSynthesizer,\n ElevenLabsSynthesizerService\n>()(\"@betalyra/effect-uai/providers/elevenlabs/ElevenLabsSynthesizer\") {}\n\nexport type Config = {\n readonly apiKey: Redacted.Redacted\n readonly baseUrl?: string\n readonly region?: ElevenLabsRegion\n}\n\n// ---------------------------------------------------------------------------\n// Codec — request → JSON body\n// ---------------------------------------------------------------------------\n\nconst buildBody = (r: ElevenLabsSynthesizeRequest) => ({\n text: r.text,\n model_id: r.model,\n ...(r.languageCode !== undefined && { language_code: r.languageCode }),\n ...(r.seed !== undefined && { seed: r.seed }),\n ...(r.previousText !== undefined && { previous_text: r.previousText }),\n ...(r.nextText !== undefined && { next_text: r.nextText }),\n ...wirePronunciationLocators(r.pronunciationDictionaryLocators),\n ...(r.voiceSettings !== undefined && { voice_settings: wireVoiceSettings(r.voiceSettings) }),\n})\n\n// ---------------------------------------------------------------------------\n// Dialogue — POST /v1/text-to-dialogue (+ /stream variant)\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_DIALOGUE_MODEL = \"eleven_v3\"\n\nconst buildDialogueBody = (r: CommonSynthesizeDialogueRequest) => ({\n inputs: r.turns.map((t) => ({\n voice_id: t.voiceId,\n text: t.text,\n })),\n model_id: r.model ?? DEFAULT_DIALOGUE_MODEL,\n ...(r.languageCode !== undefined && { language_code: r.languageCode }),\n})\n\nconst buildDialogueHttpRequest = (\n cfg: Config,\n r: CommonSynthesizeDialogueRequest,\n path: \"\" | \"/stream\",\n) =>\n Effect.gen(function* () {\n const format = r.outputFormat ?? defaultFormat\n const slug = yield* formatToOutputSlug(format)\n const url = `${resolveHost(cfg)}/text-to-dialogue${path}?output_format=${slug}`\n const httpRequest = HttpClientRequest.post(url).pipe(\n HttpClientRequest.setHeader(\"xi-api-key\", Redacted.value(cfg.apiKey)),\n HttpClientRequest.bodyJsonUnsafe(buildDialogueBody(r)),\n )\n return { httpRequest, format }\n })\n\nconst synthesizeDialogueImpl = (cfg: Config) => (request: CommonSynthesizeDialogueRequest) =>\n Effect.gen(function* () {\n yield* rejectInlinePronunciations(request.pronunciations)\n const client = yield* HttpClient.HttpClient\n const { httpRequest, format } = yield* buildDialogueHttpRequest(cfg, request, \"\")\n const response = yield* client.execute(httpRequest).pipe(Effect.mapError(transportFailure))\n if (response.status >= 400) {\n const text = yield* response.text.pipe(Effect.orElseSucceed(() => \"\"))\n return yield* Effect.fail(httpStatusError(response.status, text))\n }\n const bytes = yield* response.arrayBuffer.pipe(Effect.mapError(transportFailure))\n return { format, bytes: new Uint8Array(bytes) } satisfies AudioBlob\n })\n\nconst streamSynthesizeDialogueImpl = (cfg: Config) => (request: CommonSynthesizeDialogueRequest) =>\n Stream.unwrap(\n Effect.gen(function* () {\n yield* rejectInlinePronunciations(request.pronunciations)\n const client = yield* HttpClient.HttpClient\n const { httpRequest } = yield* buildDialogueHttpRequest(cfg, request, \"/stream\")\n const response = yield* client.execute(httpRequest).pipe(Effect.mapError(transportFailure))\n if (response.status >= 400) {\n const text = yield* response.text.pipe(Effect.orElseSucceed(() => \"\"))\n return Stream.fail(httpStatusError(response.status, text))\n }\n return response.stream.pipe(\n Stream.mapError(transportFailure),\n Stream.map((bytes): AudioChunk => ({ bytes })),\n )\n }),\n )\n\n// ---------------------------------------------------------------------------\n// HTTP plumbing (sync + chunked-HTTP streaming)\n// ---------------------------------------------------------------------------\n\nconst buildHttpRequest = (cfg: Config, r: ElevenLabsSynthesizeRequest, path: \"\" | \"/stream\") =>\n Effect.gen(function* () {\n const format = r.outputFormat ?? defaultFormat\n const slug = yield* formatToOutputSlug(format)\n const url = `${resolveHost(cfg)}/text-to-speech/${r.voiceId}${path}?output_format=${slug}`\n const httpRequest = HttpClientRequest.post(url).pipe(\n HttpClientRequest.setHeader(\"xi-api-key\", Redacted.value(cfg.apiKey)),\n HttpClientRequest.bodyJsonUnsafe(buildBody(r)),\n )\n return { httpRequest, format }\n })\n\nconst synthesizeImpl = (cfg: Config) => (request: ElevenLabsSynthesizeRequest) =>\n Effect.gen(function* () {\n yield* rejectInlinePronunciations(request.pronunciations)\n const client = yield* HttpClient.HttpClient\n const { httpRequest, format } = yield* buildHttpRequest(cfg, request, \"\")\n const response = yield* client.execute(httpRequest).pipe(Effect.mapError(transportFailure))\n if (response.status >= 400) {\n const text = yield* response.text.pipe(Effect.orElseSucceed(() => \"\"))\n return yield* Effect.fail(httpStatusError(response.status, text))\n }\n const bytes = yield* response.arrayBuffer.pipe(Effect.mapError(transportFailure))\n return { format, bytes: new Uint8Array(bytes) } satisfies AudioBlob\n })\n\nconst streamSynthesisImpl = (cfg: Config) => (request: ElevenLabsSynthesizeRequest) =>\n Stream.unwrap(\n Effect.gen(function* () {\n yield* rejectInlinePronunciations(request.pronunciations)\n const client = yield* HttpClient.HttpClient\n const { httpRequest } = yield* buildHttpRequest(cfg, request, \"/stream\")\n const response = yield* client.execute(httpRequest).pipe(Effect.mapError(transportFailure))\n if (response.status >= 400) {\n const text = yield* response.text.pipe(Effect.orElseSucceed(() => \"\"))\n return Stream.fail(httpStatusError(response.status, text))\n }\n return response.stream.pipe(\n Stream.mapError(transportFailure),\n Stream.map((bytes): AudioChunk => ({ bytes })),\n )\n }),\n )\n\n// ---------------------------------------------------------------------------\n// Constructors\n// ---------------------------------------------------------------------------\n\nexport const make = (cfg: Config) =>\n Effect.gen(function* () {\n const client = yield* HttpClient.HttpClient\n const ctor = yield* Socket.WebSocketConstructor\n return {\n synthesize: (r) =>\n synthesizeImpl(cfg)(r).pipe(Effect.provideService(HttpClient.HttpClient, client)),\n streamSynthesis: (r) =>\n streamSynthesisImpl(cfg)(r).pipe(Stream.provideService(HttpClient.HttpClient, client)),\n streamSynthesisFrom: (textIn, request) =>\n realtimeStream(cfg)(textIn, request as ElevenLabsSynthesizeRequest).pipe(\n Stream.provideService(Socket.WebSocketConstructor, ctor),\n ),\n synthesizeDialogue: (request) =>\n synthesizeDialogueImpl(cfg)(request).pipe(\n Effect.provideService(HttpClient.HttpClient, client),\n ),\n streamSynthesizeDialogue: (request) =>\n streamSynthesizeDialogueImpl(cfg)(request).pipe(\n Stream.provideService(HttpClient.HttpClient, client),\n ),\n } satisfies ElevenLabsSynthesizerService\n })\n\n/**\n * Layer registers `ElevenLabsSynthesizer`, the generic\n * `SpeechSynthesizer`, the `TtsIncrementalText` marker (incremental\n * text-in via `/stream-input` WebSocket), **and `MultiSpeakerTts`** —\n * multi-speaker dialogue is wired to `POST /v1/text-to-dialogue`\n * (sync) and `/v1/text-to-dialogue/stream` (chunked). Provide\n * `Socket.layerWebSocketConstructorGlobal` and an `HttpClient` Layer\n * at the call site.\n */\nexport const layer = (cfg: Config) =>\n Layer.mergeAll(\n Layer.effect(ElevenLabsSynthesizer, make(cfg)),\n Layer.effect(\n SpeechSynthesizer,\n Effect.map(make(cfg), (s): SpeechSynthesizerService => ({\n synthesize: (req: CommonSynthesizeRequest) =>\n s.synthesize(req as ElevenLabsSynthesizeRequest),\n streamSynthesis: (req: CommonSynthesizeRequest) =>\n s.streamSynthesis(req as ElevenLabsSynthesizeRequest),\n streamSynthesisFrom: (textIn, req: CommonStreamSynthesizeRequest) =>\n s.streamSynthesisFrom(textIn, req),\n synthesizeDialogue: s.synthesizeDialogue,\n streamSynthesizeDialogue: s.streamSynthesizeDialogue,\n })),\n ),\n Layer.succeed(TtsIncrementalText, undefined),\n Layer.succeed(MultiSpeakerTts, undefined),\n )\n"],"mappings":"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"}
|
|
@@ -4,12 +4,8 @@ import { Context, Effect, Layer, Redacted, Schema, Stream } from "effect";
|
|
|
4
4
|
import { HttpClient } from "effect/unstable/http";
|
|
5
5
|
import * as AiError from "@effect-uai/core/AiError";
|
|
6
6
|
import * as Socket from "effect/unstable/socket/Socket";
|
|
7
|
-
import * as _$_effect_uai_core_Transcriber0 from "@effect-uai/core/Transcriber";
|
|
8
7
|
import { CommonTranscribeRequest, SttStreaming, Transcriber, TranscriberService } from "@effect-uai/core/Transcriber";
|
|
9
|
-
import * as _$_effect_uai_core_Transcript0 from "@effect-uai/core/Transcript";
|
|
10
8
|
import { TranscriptResult, WordTimestamp } from "@effect-uai/core/Transcript";
|
|
11
|
-
|
|
12
|
-
//#region src/ElevenLabsTranscriber.d.ts
|
|
13
9
|
declare namespace ElevenLabsTranscriber_d_exports {
|
|
14
10
|
export { Config, ElevenLabsTranscribeRequest, ElevenLabsTranscriber, ElevenLabsTranscriberService, layer, make };
|
|
15
11
|
}
|
|
@@ -39,12 +35,12 @@ type Config = {
|
|
|
39
35
|
};
|
|
40
36
|
declare const make: (cfg: Config) => Effect.Effect<{
|
|
41
37
|
transcribe: (r: ElevenLabsTranscribeRequest) => Effect.Effect<{
|
|
42
|
-
raw: Schema.Json;
|
|
43
|
-
words?: WordTimestamp[];
|
|
44
|
-
languageCode?: string;
|
|
45
38
|
text: string;
|
|
39
|
+
languageCode?: string;
|
|
40
|
+
words?: WordTimestamp[];
|
|
41
|
+
raw: Schema.Json;
|
|
46
42
|
}, AiError.AiError, never>;
|
|
47
|
-
streamTranscriptionFrom: <E, R>(audioIn: Stream.Stream<Uint8Array<ArrayBufferLike>, E, R>, request:
|
|
43
|
+
streamTranscriptionFrom: <E, R>(audioIn: Stream.Stream<Uint8Array<ArrayBufferLike>, E, R>, request: import("@effect-uai/core/Transcriber").CommonStreamTranscribeRequest) => Stream.Stream<import("@effect-uai/core/Transcript").TranscriptEvent, E | AiError.AiError, Exclude<Exclude<R, HttpClient.HttpClient>, Socket.WebSocketConstructor>>;
|
|
48
44
|
}, never, HttpClient.HttpClient | Socket.WebSocketConstructor>;
|
|
49
45
|
/**
|
|
50
46
|
* Layer registers `ElevenLabsTranscriber`, the generic `Transcriber`,
|
|
@@ -53,7 +49,7 @@ declare const make: (cfg: Config) => Effect.Effect<{
|
|
|
53
49
|
* `Socket.layerWebSocketConstructorGlobal` (or a custom constructor) +
|
|
54
50
|
* an `HttpClient` Layer at the call site.
|
|
55
51
|
*/
|
|
56
|
-
declare const layer: (cfg: Config) => Layer.Layer<ElevenLabsTranscriber |
|
|
52
|
+
declare const layer: (cfg: Config) => Layer.Layer<ElevenLabsTranscriber | SttStreaming | Transcriber, never, HttpClient.HttpClient | Socket.WebSocketConstructor>;
|
|
57
53
|
//#endregion
|
|
58
54
|
export { Config, ElevenLabsTranscribeRequest, ElevenLabsTranscriber, ElevenLabsTranscriberService, layer, make, ElevenLabsTranscriber_d_exports as t };
|
|
59
55
|
//# sourceMappingURL=ElevenLabsTranscriber.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ElevenLabsTranscriber.d.mts","names":[],"sources":["../src/ElevenLabsTranscriber.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"ElevenLabsTranscriber.d.mts","names":[],"sources":["../src/ElevenLabsTranscriber.ts"],"mappings":";;;;;;;;;;;;;;;;;;KA4BY,8BAA8B,KAAK;WACpC,OAAO;WACP;WACA;WACA;;KAGC;WACD,aACP,GAAG,gCACA,OAAO,OAAO,kBAAkB,QAAQ;WACpC,yBAAyB;;;cAGvB,8BAA8B;KAK/B;WACD,QAAQ,SAAS;WACjB;WACA,SAAS;;cAyGP,OAAI,KAAS,WAAM,OAAA;;;;;;;;UAa5B,WAAA,aAAA,OAAA;;;;;;;;cASS,QAAK,KAAS,WAAM,MAAA,MAAA,wBAAA,eAAA,oBAAA,WAAA,aAAA,OAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as __exportAll } from "./
|
|
1
|
+
import { n as __exportAll } from "./rolldown-runtime-EAsCxrDo.mjs";
|
|
2
2
|
import { audioToBlob, defaultFileName, httpStatusError, transportFailure } from "./codec.mjs";
|
|
3
3
|
import { resolveHost } from "./region.mjs";
|
|
4
4
|
import { streamTranscription } from "./realtimeStt.mjs";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ElevenLabsTranscriber.mjs","names":[],"sources":["../src/ElevenLabsTranscriber.ts"],"sourcesContent":["import { Context, Effect, Layer, Redacted, Schema, Stream } from \"effect\"\nimport { HttpClient, HttpClientRequest } from \"effect/unstable/http\"\nimport * as Socket from \"effect/unstable/socket/Socket\"\nimport * as AiError from \"@effect-uai/core/AiError\"\nimport * as Capabilities from \"@effect-uai/core/Capabilities\"\nimport type { TranscriptResult, WordTimestamp } from \"@effect-uai/core/Transcript\"\nimport {\n type CommonTranscribeRequest,\n SttStreaming,\n Transcriber,\n type TranscriberService,\n} from \"@effect-uai/core/Transcriber\"\nimport { audioToBlob, defaultFileName, httpStatusError, transportFailure } from \"./codec.js\"\nimport type { ElevenLabsSttModel } from \"./models.js\"\nimport { streamTranscription } from \"./realtimeStt.js\"\nimport { type ElevenLabsRegion, resolveHost } from \"./region.js\"\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/**\n * ElevenLabs-typed transcribe request. `model` narrows to\n * `ElevenLabsSttModel`. `numSpeakers` hints diarization. `audioEvents`\n * surfaces `(laughter)` / `(music)` tags inline in `text` (provider\n * default: true). `fileName` overrides the multipart upload's\n * `filename`; ElevenLabs uses the extension to detect format.\n */\nexport type ElevenLabsTranscribeRequest = Omit<CommonTranscribeRequest, \"model\"> & {\n readonly model: ElevenLabsSttModel\n readonly numSpeakers?: number\n readonly audioEvents?: boolean\n readonly fileName?: string\n}\n\nexport type ElevenLabsTranscriberService = {\n readonly transcribe: (\n r: ElevenLabsTranscribeRequest,\n ) => Effect.Effect<TranscriptResult, AiError.AiError>\n readonly streamTranscriptionFrom: TranscriberService[\"streamTranscriptionFrom\"]\n}\n\nexport class ElevenLabsTranscriber extends Context.Service<\n ElevenLabsTranscriber,\n ElevenLabsTranscriberService\n>()(\"@betalyra/effect-uai/providers/elevenlabs/ElevenLabsTranscriber\") {}\n\nexport type Config = {\n readonly apiKey: Redacted.Redacted\n readonly baseUrl?: string\n readonly region?: ElevenLabsRegion\n}\n\n// ---------------------------------------------------------------------------\n// Response schema\n// ---------------------------------------------------------------------------\n\nconst Word = Schema.Struct({\n text: Schema.String,\n start: Schema.optional(Schema.Number),\n end: Schema.optional(Schema.Number),\n type: Schema.optional(Schema.String),\n speaker_id: Schema.optional(Schema.String),\n logprob: Schema.optional(Schema.Number),\n})\n\nconst Wire = Schema.Struct({\n text: Schema.String,\n language_code: Schema.optional(Schema.String),\n language_probability: Schema.optional(Schema.Number),\n words: Schema.optional(Schema.Array(Word)),\n transcription_id: Schema.optional(Schema.String),\n})\nconst decodeWire = Schema.decodeUnknownEffect(Wire)\n\nconst toWordTimestamp = (w: typeof Word.Type): WordTimestamp | undefined =>\n w.start === undefined || w.end === undefined\n ? undefined\n : {\n text: w.text,\n startSeconds: w.start,\n endSeconds: w.end,\n ...(w.logprob !== undefined && { confidence: Math.exp(w.logprob) }),\n ...(w.speaker_id !== undefined && { speakerId: w.speaker_id }),\n }\n\n// ---------------------------------------------------------------------------\n// Multipart body\n// ---------------------------------------------------------------------------\n\nconst buildForm = (request: ElevenLabsTranscribeRequest) =>\n Effect.gen(function* () {\n const blob = yield* audioToBlob(request.audio)\n const fileName = request.fileName ?? defaultFileName(request.audio.mimeType ?? \"\")\n const form = new FormData()\n form.set(\"model_id\", request.model)\n form.set(\"file\", blob, fileName)\n if (request.language !== undefined) form.set(\"language_code\", request.language)\n if (request.diarization !== undefined)\n form.set(\"diarize\", request.diarization ? \"true\" : \"false\")\n if (request.wordTimestamps === true) form.set(\"timestamps_granularity\", \"word\")\n if (request.numSpeakers !== undefined) form.set(\"num_speakers\", String(request.numSpeakers))\n if (request.audioEvents !== undefined)\n form.set(\"tag_audio_events\", request.audioEvents ? \"true\" : \"false\")\n // Vocab biasing → Scribe `keyterms` (≤1000 terms, ≤50 chars). Each\n // term is a repeated form field (`keyterms=a&keyterms=b`), matching\n // the ElevenLabs SDK. Scribe has no free-form prompt field.\n for (const term of request.biasingTerms ?? []) form.append(\"keyterms\", term)\n yield* Capabilities.warnDroppedWhen(request.prompt, {\n provider: \"elevenlabs\",\n capability: \"prompt\",\n field: \"prompt\",\n reason: \"ElevenLabs Scribe has no free-form prompt field; bias via `biasingTerms`.\",\n })\n return form\n })\n\n// ---------------------------------------------------------------------------\n// HTTP plumbing\n// ---------------------------------------------------------------------------\n\nconst transcribeImpl = (cfg: Config) => (request: ElevenLabsTranscribeRequest) =>\n Effect.gen(function* () {\n const client = yield* HttpClient.HttpClient\n const form = yield* buildForm(request)\n const httpRequest = HttpClientRequest.post(`${resolveHost(cfg)}/speech-to-text`).pipe(\n HttpClientRequest.setHeader(\"xi-api-key\", Redacted.value(cfg.apiKey)),\n HttpClientRequest.bodyFormData(form),\n )\n const response = yield* client.execute(httpRequest).pipe(Effect.mapError(transportFailure))\n if (response.status >= 400) {\n const text = yield* response.text.pipe(Effect.orElseSucceed(() => \"\"))\n return yield* Effect.fail(httpStatusError(response.status, text))\n }\n const json = yield* response.json.pipe(Effect.mapError(transportFailure))\n const wire = yield* decodeWire(json).pipe(\n Effect.mapError(\n (cause) => new AiError.GenerationFailed({ provider: \"elevenlabs\", raw: cause }),\n ),\n )\n const words = wire.words\n ?.map(toWordTimestamp)\n .filter((w): w is WordTimestamp => w !== undefined)\n return {\n text: wire.text,\n ...(wire.language_code !== undefined && { languageCode: wire.language_code }),\n ...(words !== undefined && words.length > 0 && { words }),\n raw: json,\n } satisfies TranscriptResult\n })\n\n// ---------------------------------------------------------------------------\n// Constructors\n// ---------------------------------------------------------------------------\n\nexport const make = (cfg: Config) =>\n Effect.gen(function* () {\n const client = yield* HttpClient.HttpClient\n const ctor = yield* Socket.WebSocketConstructor\n return {\n transcribe: (r) =>\n transcribeImpl(cfg)(r).pipe(Effect.provideService(HttpClient.HttpClient, client)),\n streamTranscriptionFrom: (audioIn, request) =>\n streamTranscription(cfg)(audioIn, request).pipe(\n Stream.provideService(HttpClient.HttpClient, client),\n Stream.provideService(Socket.WebSocketConstructor, ctor),\n ),\n } satisfies ElevenLabsTranscriberService\n })\n\n/**\n * Layer registers `ElevenLabsTranscriber`, the generic `Transcriber`,\n * **and the `SttStreaming` capability marker** — `streamTranscriptionFrom`\n * is wired to the realtime WebSocket. Provide\n * `Socket.layerWebSocketConstructorGlobal` (or a custom constructor) +\n * an `HttpClient` Layer at the call site.\n */\nexport const layer = (cfg: Config) =>\n Layer.mergeAll(\n Layer.effect(ElevenLabsTranscriber, make(cfg)),\n Layer.effect(\n Transcriber,\n Effect.map(\n make(cfg),\n (s): TranscriberService => ({\n transcribe: (req: CommonTranscribeRequest) =>\n s.transcribe(req as ElevenLabsTranscribeRequest),\n streamTranscriptionFrom: s.streamTranscriptionFrom,\n }),\n ),\n ),\n Layer.succeed(SttStreaming, undefined),\n )\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ElevenLabsTranscriber.mjs","names":[],"sources":["../src/ElevenLabsTranscriber.ts"],"sourcesContent":["import { Context, Effect, Layer, Redacted, Schema, Stream } from \"effect\"\nimport { HttpClient, HttpClientRequest } from \"effect/unstable/http\"\nimport * as Socket from \"effect/unstable/socket/Socket\"\nimport * as AiError from \"@effect-uai/core/AiError\"\nimport * as Capabilities from \"@effect-uai/core/Capabilities\"\nimport type { TranscriptResult, WordTimestamp } from \"@effect-uai/core/Transcript\"\nimport {\n type CommonTranscribeRequest,\n SttStreaming,\n Transcriber,\n type TranscriberService,\n} from \"@effect-uai/core/Transcriber\"\nimport { audioToBlob, defaultFileName, httpStatusError, transportFailure } from \"./codec.js\"\nimport type { ElevenLabsSttModel } from \"./models.js\"\nimport { streamTranscription } from \"./realtimeStt.js\"\nimport { type ElevenLabsRegion, resolveHost } from \"./region.js\"\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/**\n * ElevenLabs-typed transcribe request. `model` narrows to\n * `ElevenLabsSttModel`. `numSpeakers` hints diarization. `audioEvents`\n * surfaces `(laughter)` / `(music)` tags inline in `text` (provider\n * default: true). `fileName` overrides the multipart upload's\n * `filename`; ElevenLabs uses the extension to detect format.\n */\nexport type ElevenLabsTranscribeRequest = Omit<CommonTranscribeRequest, \"model\"> & {\n readonly model: ElevenLabsSttModel\n readonly numSpeakers?: number\n readonly audioEvents?: boolean\n readonly fileName?: string\n}\n\nexport type ElevenLabsTranscriberService = {\n readonly transcribe: (\n r: ElevenLabsTranscribeRequest,\n ) => Effect.Effect<TranscriptResult, AiError.AiError>\n readonly streamTranscriptionFrom: TranscriberService[\"streamTranscriptionFrom\"]\n}\n\nexport class ElevenLabsTranscriber extends Context.Service<\n ElevenLabsTranscriber,\n ElevenLabsTranscriberService\n>()(\"@betalyra/effect-uai/providers/elevenlabs/ElevenLabsTranscriber\") {}\n\nexport type Config = {\n readonly apiKey: Redacted.Redacted\n readonly baseUrl?: string\n readonly region?: ElevenLabsRegion\n}\n\n// ---------------------------------------------------------------------------\n// Response schema\n// ---------------------------------------------------------------------------\n\nconst Word = Schema.Struct({\n text: Schema.String,\n start: Schema.optional(Schema.Number),\n end: Schema.optional(Schema.Number),\n type: Schema.optional(Schema.String),\n speaker_id: Schema.optional(Schema.String),\n logprob: Schema.optional(Schema.Number),\n})\n\nconst Wire = Schema.Struct({\n text: Schema.String,\n language_code: Schema.optional(Schema.String),\n language_probability: Schema.optional(Schema.Number),\n words: Schema.optional(Schema.Array(Word)),\n transcription_id: Schema.optional(Schema.String),\n})\nconst decodeWire = Schema.decodeUnknownEffect(Wire)\n\nconst toWordTimestamp = (w: typeof Word.Type): WordTimestamp | undefined =>\n w.start === undefined || w.end === undefined\n ? undefined\n : {\n text: w.text,\n startSeconds: w.start,\n endSeconds: w.end,\n ...(w.logprob !== undefined && { confidence: Math.exp(w.logprob) }),\n ...(w.speaker_id !== undefined && { speakerId: w.speaker_id }),\n }\n\n// ---------------------------------------------------------------------------\n// Multipart body\n// ---------------------------------------------------------------------------\n\nconst buildForm = (request: ElevenLabsTranscribeRequest) =>\n Effect.gen(function* () {\n const blob = yield* audioToBlob(request.audio)\n const fileName = request.fileName ?? defaultFileName(request.audio.mimeType ?? \"\")\n const form = new FormData()\n form.set(\"model_id\", request.model)\n form.set(\"file\", blob, fileName)\n if (request.language !== undefined) form.set(\"language_code\", request.language)\n if (request.diarization !== undefined)\n form.set(\"diarize\", request.diarization ? \"true\" : \"false\")\n if (request.wordTimestamps === true) form.set(\"timestamps_granularity\", \"word\")\n if (request.numSpeakers !== undefined) form.set(\"num_speakers\", String(request.numSpeakers))\n if (request.audioEvents !== undefined)\n form.set(\"tag_audio_events\", request.audioEvents ? \"true\" : \"false\")\n // Vocab biasing → Scribe `keyterms` (≤1000 terms, ≤50 chars). Each\n // term is a repeated form field (`keyterms=a&keyterms=b`), matching\n // the ElevenLabs SDK. Scribe has no free-form prompt field.\n for (const term of request.biasingTerms ?? []) form.append(\"keyterms\", term)\n yield* Capabilities.warnDroppedWhen(request.prompt, {\n provider: \"elevenlabs\",\n capability: \"prompt\",\n field: \"prompt\",\n reason: \"ElevenLabs Scribe has no free-form prompt field; bias via `biasingTerms`.\",\n })\n return form\n })\n\n// ---------------------------------------------------------------------------\n// HTTP plumbing\n// ---------------------------------------------------------------------------\n\nconst transcribeImpl = (cfg: Config) => (request: ElevenLabsTranscribeRequest) =>\n Effect.gen(function* () {\n const client = yield* HttpClient.HttpClient\n const form = yield* buildForm(request)\n const httpRequest = HttpClientRequest.post(`${resolveHost(cfg)}/speech-to-text`).pipe(\n HttpClientRequest.setHeader(\"xi-api-key\", Redacted.value(cfg.apiKey)),\n HttpClientRequest.bodyFormData(form),\n )\n const response = yield* client.execute(httpRequest).pipe(Effect.mapError(transportFailure))\n if (response.status >= 400) {\n const text = yield* response.text.pipe(Effect.orElseSucceed(() => \"\"))\n return yield* Effect.fail(httpStatusError(response.status, text))\n }\n const json = yield* response.json.pipe(Effect.mapError(transportFailure))\n const wire = yield* decodeWire(json).pipe(\n Effect.mapError(\n (cause) => new AiError.GenerationFailed({ provider: \"elevenlabs\", raw: cause }),\n ),\n )\n const words = wire.words\n ?.map(toWordTimestamp)\n .filter((w): w is WordTimestamp => w !== undefined)\n return {\n text: wire.text,\n ...(wire.language_code !== undefined && { languageCode: wire.language_code }),\n ...(words !== undefined && words.length > 0 && { words }),\n raw: json,\n } satisfies TranscriptResult\n })\n\n// ---------------------------------------------------------------------------\n// Constructors\n// ---------------------------------------------------------------------------\n\nexport const make = (cfg: Config) =>\n Effect.gen(function* () {\n const client = yield* HttpClient.HttpClient\n const ctor = yield* Socket.WebSocketConstructor\n return {\n transcribe: (r) =>\n transcribeImpl(cfg)(r).pipe(Effect.provideService(HttpClient.HttpClient, client)),\n streamTranscriptionFrom: (audioIn, request) =>\n streamTranscription(cfg)(audioIn, request).pipe(\n Stream.provideService(HttpClient.HttpClient, client),\n Stream.provideService(Socket.WebSocketConstructor, ctor),\n ),\n } satisfies ElevenLabsTranscriberService\n })\n\n/**\n * Layer registers `ElevenLabsTranscriber`, the generic `Transcriber`,\n * **and the `SttStreaming` capability marker** — `streamTranscriptionFrom`\n * is wired to the realtime WebSocket. Provide\n * `Socket.layerWebSocketConstructorGlobal` (or a custom constructor) +\n * an `HttpClient` Layer at the call site.\n */\nexport const layer = (cfg: Config) =>\n Layer.mergeAll(\n Layer.effect(ElevenLabsTranscriber, make(cfg)),\n Layer.effect(\n Transcriber,\n Effect.map(make(cfg), (s): TranscriberService => ({\n transcribe: (req: CommonTranscribeRequest) =>\n s.transcribe(req as ElevenLabsTranscribeRequest),\n streamTranscriptionFrom: s.streamTranscriptionFrom,\n })),\n ),\n Layer.succeed(SttStreaming, undefined),\n )\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export {}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as describe, r as it, t as globalExpect } from "./test.DNmyFkvJ-N3QqMRwZ.mjs";
|
|
2
|
+
import { t as import_dist } from "./dist-C0AvqZTC.mjs";
|
|
2
3
|
import { ElevenLabsTranscriber, layer } from "./ElevenLabsTranscriber.mjs";
|
|
3
4
|
import { Effect, Layer, Redacted, Stream } from "effect";
|
|
4
5
|
import { FetchHttpClient } from "effect/unstable/http";
|
|
5
6
|
import * as Socket from "effect/unstable/socket/Socket";
|
|
6
7
|
import * as Transcriber$1 from "@effect-uai/core/Transcriber";
|
|
7
|
-
|
|
8
|
+
//#region src/ElevenLabsTranscriber.test.ts
|
|
9
|
+
const cfg = { apiKey: Redacted.make("test-key") };
|
|
10
|
+
const live = layer(cfg).pipe(Layer.provide(FetchHttpClient.layer), Layer.provide(Socket.layerWebSocketConstructorGlobal));
|
|
8
11
|
const dummyAudio = {
|
|
9
12
|
_tag: "bytes",
|
|
10
13
|
bytes: new Uint8Array([
|
|
@@ -43,13 +46,15 @@ describe("ElevenLabsTranscriber Layer (compile-time)", () => {
|
|
|
43
46
|
sampleRate: 16e3
|
|
44
47
|
}
|
|
45
48
|
}));
|
|
46
|
-
|
|
49
|
+
const provided = Stream.runDrain(events).pipe(Effect.provide(live));
|
|
50
|
+
(0, import_dist.expectTypeOf)(provided).toEqualTypeOf();
|
|
47
51
|
});
|
|
48
52
|
it("sync `transcribe` requires no marker", () => {
|
|
49
|
-
|
|
53
|
+
const t = Transcriber$1.transcribe({
|
|
50
54
|
audio: dummyAudio,
|
|
51
55
|
model: "scribe_v2"
|
|
52
|
-
}).pipe(Effect.provide(live))
|
|
56
|
+
}).pipe(Effect.provide(live));
|
|
57
|
+
(0, import_dist.expectTypeOf)(t).toEqualTypeOf();
|
|
53
58
|
});
|
|
54
59
|
});
|
|
55
60
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ElevenLabsTranscriber.test.mjs","names":["ElevenLabsTranscriber.layer","Transcriber"],"sources":["../src/ElevenLabsTranscriber.test.ts"],"sourcesContent":["import { Effect, Layer, Redacted, Stream } from \"effect\"\nimport { FetchHttpClient } from \"effect/unstable/http\"\nimport * as Socket from \"effect/unstable/socket/Socket\"\nimport { describe, expect, expectTypeOf, it } from \"vitest\"\nimport type * as AiError from \"@effect-uai/core/AiError\"\nimport type { TranscriptResult } from \"@effect-uai/core/Transcript\"\nimport * as Transcriber from \"@effect-uai/core/Transcriber\"\nimport * as ElevenLabsTranscriber from \"./ElevenLabsTranscriber.js\"\n\nconst cfg: ElevenLabsTranscriber.Config = { apiKey: Redacted.make(\"test-key\") }\n// FetchHttpClient + globalThis.WebSocket are required for `make`, but these\n// tests only exercise the codec + compile-time / runtime branches — no real\n// HTTP or WS connection is opened.\nconst live = ElevenLabsTranscriber.layer(cfg).pipe(\n Layer.provide(FetchHttpClient.layer),\n Layer.provide(Socket.layerWebSocketConstructorGlobal),\n)\n\nconst dummyAudio = {\n _tag: \"bytes\" as const,\n bytes: new Uint8Array([0, 1, 2, 3]),\n mimeType: \"audio/wav\" as const,\n}\n\ndescribe(\"ElevenLabsTranscriber input format guard (runtime)\", () => {\n it(\"fails Unsupported for unsupported raw encodings\", async () => {\n const program = ElevenLabsTranscriber.ElevenLabsTranscriber.use((s) =>\n Stream.runDrain(\n s.streamTranscriptionFrom(Stream.fromIterable([new Uint8Array([0])]), {\n model: \"scribe_v2_realtime\",\n inputFormat: { container: \"mp3\", encoding: \"mp3\", sampleRate: 44100 },\n }),\n ),\n )\n const exit = await Effect.runPromiseExit(program.pipe(Effect.provide(live)))\n expect(exit._tag).toBe(\"Failure\")\n if (exit._tag === \"Failure\") {\n expect(JSON.stringify(exit.cause)).toContain(\"Unsupported\")\n expect(JSON.stringify(exit.cause)).toContain(\"inputFormat\")\n }\n })\n})\n\ndescribe(\"ElevenLabsTranscriber Layer (compile-time)\", () => {\n it(\"registers `SttStreaming` — `streamTranscriptionFrom` clears R to never\", () => {\n const audio: Stream.Stream<Uint8Array> = Stream.fromIterable([new Uint8Array([0])])\n const events = audio.pipe(\n Transcriber.streamTranscriptionFrom({\n model: \"scribe_v2_realtime\",\n inputFormat: { container: \"raw\", encoding: \"pcm_s16le\", sampleRate: 16000 },\n }),\n )\n const provided = Stream.runDrain(events).pipe(Effect.provide(live))\n expectTypeOf(provided).toEqualTypeOf<Effect.Effect<void, AiError.AiError, never>>()\n })\n\n it(\"sync `transcribe` requires no marker\", () => {\n const t = Transcriber.transcribe({ audio: dummyAudio, model: \"scribe_v2\" }).pipe(\n Effect.provide(live),\n )\n expectTypeOf(t).toEqualTypeOf<Effect.Effect<TranscriptResult, AiError.AiError, never>>()\n })\n})\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"ElevenLabsTranscriber.test.mjs","names":["ElevenLabsTranscriber.layer","Transcriber"],"sources":["../src/ElevenLabsTranscriber.test.ts"],"sourcesContent":["import { Effect, Layer, Redacted, Stream } from \"effect\"\nimport { FetchHttpClient } from \"effect/unstable/http\"\nimport * as Socket from \"effect/unstable/socket/Socket\"\nimport { describe, expect, expectTypeOf, it } from \"vitest\"\nimport type * as AiError from \"@effect-uai/core/AiError\"\nimport type { TranscriptResult } from \"@effect-uai/core/Transcript\"\nimport * as Transcriber from \"@effect-uai/core/Transcriber\"\nimport * as ElevenLabsTranscriber from \"./ElevenLabsTranscriber.js\"\n\nconst cfg: ElevenLabsTranscriber.Config = { apiKey: Redacted.make(\"test-key\") }\n// FetchHttpClient + globalThis.WebSocket are required for `make`, but these\n// tests only exercise the codec + compile-time / runtime branches — no real\n// HTTP or WS connection is opened.\nconst live = ElevenLabsTranscriber.layer(cfg).pipe(\n Layer.provide(FetchHttpClient.layer),\n Layer.provide(Socket.layerWebSocketConstructorGlobal),\n)\n\nconst dummyAudio = {\n _tag: \"bytes\" as const,\n bytes: new Uint8Array([0, 1, 2, 3]),\n mimeType: \"audio/wav\" as const,\n}\n\ndescribe(\"ElevenLabsTranscriber input format guard (runtime)\", () => {\n it(\"fails Unsupported for unsupported raw encodings\", async () => {\n const program = ElevenLabsTranscriber.ElevenLabsTranscriber.use((s) =>\n Stream.runDrain(\n s.streamTranscriptionFrom(Stream.fromIterable([new Uint8Array([0])]), {\n model: \"scribe_v2_realtime\",\n inputFormat: { container: \"mp3\", encoding: \"mp3\", sampleRate: 44100 },\n }),\n ),\n )\n const exit = await Effect.runPromiseExit(program.pipe(Effect.provide(live)))\n expect(exit._tag).toBe(\"Failure\")\n if (exit._tag === \"Failure\") {\n expect(JSON.stringify(exit.cause)).toContain(\"Unsupported\")\n expect(JSON.stringify(exit.cause)).toContain(\"inputFormat\")\n }\n })\n})\n\ndescribe(\"ElevenLabsTranscriber Layer (compile-time)\", () => {\n it(\"registers `SttStreaming` — `streamTranscriptionFrom` clears R to never\", () => {\n const audio: Stream.Stream<Uint8Array> = Stream.fromIterable([new Uint8Array([0])])\n const events = audio.pipe(\n Transcriber.streamTranscriptionFrom({\n model: \"scribe_v2_realtime\",\n inputFormat: { container: \"raw\", encoding: \"pcm_s16le\", sampleRate: 16000 },\n }),\n )\n const provided = Stream.runDrain(events).pipe(Effect.provide(live))\n expectTypeOf(provided).toEqualTypeOf<Effect.Effect<void, AiError.AiError, never>>()\n })\n\n it(\"sync `transcribe` requires no marker\", () => {\n const t = Transcriber.transcribe({ audio: dummyAudio, model: \"scribe_v2\" }).pipe(\n Effect.provide(live),\n )\n expectTypeOf(t).toEqualTypeOf<Effect.Effect<TranscriptResult, AiError.AiError, never>>()\n })\n})\n"],"mappings":";;;;;;;;AASA,MAAM,MAAoC,EAAE,QAAQ,SAAS,KAAK,UAAU,EAAE;AAI9E,MAAM,OAAOA,MAA4B,GAAG,CAAC,CAAC,KAC5C,MAAM,QAAQ,gBAAgB,KAAK,GACnC,MAAM,QAAQ,OAAO,+BAA+B,CACtD;AAEA,MAAM,aAAa;CACjB,MAAM;CACN,OAAO,IAAI,WAAW;EAAC;EAAG;EAAG;EAAG;CAAC,CAAC;CAClC,UAAU;AACZ;AAEA,SAAS,4DAA4D;CACnE,GAAG,mDAAmD,YAAY;EAChE,MAAM,UAAA,sBAAsD,KAAK,MAC/D,OAAO,SACL,EAAE,wBAAwB,OAAO,aAAa,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG;GACpE,OAAO;GACP,aAAa;IAAE,WAAW;IAAO,UAAU;IAAO,YAAY;GAAM;EACtE,CAAC,CACH,CACF;EACA,MAAM,OAAO,MAAM,OAAO,eAAe,QAAQ,KAAK,OAAO,QAAQ,IAAI,CAAC,CAAC;EAC3E,aAAO,KAAK,IAAI,CAAC,CAAC,KAAK,SAAS;EAChC,IAAI,KAAK,SAAS,WAAW;GAC3B,aAAO,KAAK,UAAU,KAAK,KAAK,CAAC,CAAC,CAAC,UAAU,aAAa;GAC1D,aAAO,KAAK,UAAU,KAAK,KAAK,CAAC,CAAC,CAAC,UAAU,aAAa;EAC5D;CACF,CAAC;AACH,CAAC;AAED,SAAS,oDAAoD;CAC3D,GAAG,gFAAgF;EAEjF,MAAM,SADmC,OAAO,aAAa,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,CAC9D,CAAC,CAAC,KACnBC,cAAY,wBAAwB;GAClC,OAAO;GACP,aAAa;IAAE,WAAW;IAAO,UAAU;IAAa,YAAY;GAAM;EAC5E,CAAC,CACH;EACA,MAAM,WAAW,OAAO,SAAS,MAAM,CAAC,CAAC,KAAK,OAAO,QAAQ,IAAI,CAAC;EAClE,CAAA,GAAA,YAAA,aAAA,CAAa,QAAQ,CAAC,CAAC,cAA2D;CACpF,CAAC;CAED,GAAG,8CAA8C;EAC/C,MAAM,IAAIA,cAAY,WAAW;GAAE,OAAO;GAAY,OAAO;EAAY,CAAC,CAAC,CAAC,KAC1E,OAAO,QAAQ,IAAI,CACrB;EACA,CAAA,GAAA,YAAA,aAAA,CAAa,CAAC,CAAC,CAAC,cAAuE;CACzF,CAAC;AACH,CAAC"}
|
package/dist/codec.d.mts
CHANGED
|
@@ -2,8 +2,6 @@ import { Effect } from "effect";
|
|
|
2
2
|
import * as AiError from "@effect-uai/core/AiError";
|
|
3
3
|
import { CustomPronunciation } from "@effect-uai/core/SpeechSynthesizer";
|
|
4
4
|
import { AudioFormat, AudioSource } from "@effect-uai/core/Audio";
|
|
5
|
-
|
|
6
|
-
//#region src/codec.d.ts
|
|
7
5
|
declare namespace codec_d_exports {
|
|
8
6
|
export { PronunciationDictionaryLocator, VoiceSettings, audioToBlob, defaultFileName, defaultFormat, formatToOutputSlug, httpStatusError, rejectInlinePronunciations, transportFailure, wirePronunciationLocators, wireVoiceSettings };
|
|
9
7
|
}
|
|
@@ -15,11 +13,11 @@ type VoiceSettings = {
|
|
|
15
13
|
readonly speed?: number;
|
|
16
14
|
};
|
|
17
15
|
declare const wireVoiceSettings: (v: VoiceSettings | undefined) => {
|
|
18
|
-
speed?: number;
|
|
19
|
-
use_speaker_boost?: boolean;
|
|
20
|
-
style?: number;
|
|
21
|
-
similarity_boost?: number;
|
|
22
16
|
stability?: number;
|
|
17
|
+
similarity_boost?: number;
|
|
18
|
+
style?: number;
|
|
19
|
+
use_speaker_boost?: boolean;
|
|
20
|
+
speed?: number;
|
|
23
21
|
} | undefined;
|
|
24
22
|
/**
|
|
25
23
|
* Reference to a pre-provisioned ElevenLabs pronunciation dictionary.
|
package/dist/codec.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codec.d.mts","names":[],"sources":["../src/codec.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"codec.d.mts","names":[],"sources":["../src/codec.ts"],"mappings":";;;;;;;KASY;WACD;WACA;WACA;WACA;WACA;;cAGE,oBAAiB,GAAO;;;;;;;;;;;;KAoBzB;WACD;WACA;;cAGE,4BAAyB,UAC1B,cAAc;;;;;;;;;;;;cAiBb,6BAA0B,gBACrB,cAAc,qCAC7B,OAAO,aAAa,QAAQ;;;;;;;;;;;;cA2BlB,qBAAqB,QAAQ,gBAAgB,OAAO,eAAe,QAAQ;;cAgC3E,eAAe;cA6Bf,cAAc,OAAO,gBAAgB,OAAO,OAAO,MAAM,QAAQ;cA2BjE,kBAAe;cAYf,kBAAkB,gBAAgB,iBAAiB,QAAQ;cAyC3D,mBAAgB,mBAAqB,QAAQ"}
|