@shogo-ai/voice 1.4.1 → 1.9.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/{chunk-ZGYHDC5G.js → chunk-B4JC3DK2.js} +107 -1
- package/dist/{chunk-QHDIEE7O.js → chunk-O362EJQR.js} +73 -2
- package/dist/{chunk-D2EVSUZX.js → chunk-T3T4EBWY.js} +3 -2
- package/dist/index.cjs +107 -0
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -1
- package/dist/route/agent.cjs +176 -0
- package/dist/route/agent.js +3 -3
- package/dist/route/audio-tags.cjs +176 -0
- package/dist/route/audio-tags.js +3 -3
- package/dist/route/index.cjs +177 -0
- package/dist/route/index.d.cts +5 -1
- package/dist/route/index.d.ts +5 -1
- package/dist/route/index.js +3 -3
- package/dist/route/music.cjs +1151 -0
- package/dist/route/music.d.cts +22 -0
- package/dist/route/music.d.ts +22 -0
- package/dist/route/music.js +13 -0
- package/dist/route/signed-url.cjs +176 -0
- package/dist/route/signed-url.js +3 -3
- package/dist/route/tts-preview.cjs +176 -0
- package/dist/route/tts-preview.js +3 -3
- package/dist/server.cjs +176 -0
- package/dist/server.d.cts +7 -1
- package/dist/server.d.ts +7 -1
- package/dist/server.js +2 -2
- package/dist/{types-BKJtOUbE.d.ts → types-W9y6eMj3.d.cts} +80 -1
- package/dist/{types-BKJtOUbE.d.cts → types-W9y6eMj3.d.ts} +80 -1
- package/package.json +7 -2
package/dist/server.cjs
CHANGED
|
@@ -204,6 +204,7 @@ function resolveConvaiTtsModel(requested) {
|
|
|
204
204
|
if (requested && CONVAI_SUPPORTED_TTS_MODELS.has(requested)) return requested;
|
|
205
205
|
return CONVAI_TTS_MODEL_FALLBACK;
|
|
206
206
|
}
|
|
207
|
+
var DEFAULT_MUSIC_MODEL = "music_v1";
|
|
207
208
|
var ElevenLabsApiError = class extends Error {
|
|
208
209
|
constructor(message, status, body) {
|
|
209
210
|
super(message);
|
|
@@ -404,6 +405,110 @@ var ElevenLabsClient = class {
|
|
|
404
405
|
const contentType = res.headers.get("content-type") ?? accept;
|
|
405
406
|
return { audio, modelId: used, contentType };
|
|
406
407
|
}
|
|
408
|
+
/**
|
|
409
|
+
* Low-level escape hatch for any ElevenLabs endpoint not covered by a
|
|
410
|
+
* dedicated method (music, sound-generation, speech-to-text, dubbing,
|
|
411
|
+
* voice-design, …). Handles auth, query encoding, JSON body encoding,
|
|
412
|
+
* and JSON-vs-binary response parsing; non-2xx responses throw
|
|
413
|
+
* {@link ElevenLabsApiError} like the typed methods do.
|
|
414
|
+
*
|
|
415
|
+
* @example
|
|
416
|
+
* ```ts
|
|
417
|
+
* const { json } = await el.request({ method: 'GET', path: '/v1/models' })
|
|
418
|
+
* const { audio } = await el.request({
|
|
419
|
+
* method: 'POST',
|
|
420
|
+
* path: '/v1/sound-generation',
|
|
421
|
+
* body: { text: 'door creak' },
|
|
422
|
+
* accept: 'audio/mpeg',
|
|
423
|
+
* })
|
|
424
|
+
* ```
|
|
425
|
+
*/
|
|
426
|
+
async request(opts) {
|
|
427
|
+
const accept = opts.accept ?? "application/json";
|
|
428
|
+
let url = `${this.baseUrl}${opts.path.startsWith("/") ? "" : "/"}${opts.path}`;
|
|
429
|
+
if (opts.query) {
|
|
430
|
+
const params = new URLSearchParams();
|
|
431
|
+
for (const [k, v] of Object.entries(opts.query)) {
|
|
432
|
+
if (v !== null && v !== void 0) params.set(k, String(v));
|
|
433
|
+
}
|
|
434
|
+
const qs = params.toString();
|
|
435
|
+
if (qs) url += `${url.includes("?") ? "&" : "?"}${qs}`;
|
|
436
|
+
}
|
|
437
|
+
const headers = this.headers({ accept, ...opts.headers ?? {} });
|
|
438
|
+
const init = { method: opts.method, headers };
|
|
439
|
+
if (opts.body !== void 0 && opts.body !== null) {
|
|
440
|
+
const isPlainPayload = typeof opts.body === "object" && !(opts.body instanceof ArrayBuffer) && !(opts.body instanceof Uint8Array) && !(typeof Blob !== "undefined" && opts.body instanceof Blob) && !(typeof FormData !== "undefined" && opts.body instanceof FormData);
|
|
441
|
+
if (isPlainPayload) {
|
|
442
|
+
headers["content-type"] = "application/json";
|
|
443
|
+
init.body = JSON.stringify(opts.body);
|
|
444
|
+
} else {
|
|
445
|
+
init.body = opts.body;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
const res = await this.fetchImpl(url, init);
|
|
449
|
+
if (!res.ok) {
|
|
450
|
+
const text = await res.text();
|
|
451
|
+
throw new ElevenLabsApiError(
|
|
452
|
+
`request ${opts.method} ${opts.path} failed: ${res.status}`,
|
|
453
|
+
res.status,
|
|
454
|
+
text
|
|
455
|
+
);
|
|
456
|
+
}
|
|
457
|
+
const contentType = res.headers.get("content-type") ?? accept;
|
|
458
|
+
if (contentType.includes("application/json")) {
|
|
459
|
+
return { status: res.status, contentType, json: await res.json() };
|
|
460
|
+
}
|
|
461
|
+
return { status: res.status, contentType, audio: await res.arrayBuffer() };
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* Generate music via `POST /v1/music`. Provide exactly one of `prompt`
|
|
465
|
+
* or `compositionPlan` (ElevenLabs returns 422 otherwise). Returns the
|
|
466
|
+
* raw audio bytes plus the response content type.
|
|
467
|
+
*
|
|
468
|
+
* @example
|
|
469
|
+
* ```ts
|
|
470
|
+
* const { audio } = await el.composeMusic({
|
|
471
|
+
* prompt: 'Upbeat synthwave with driving bass',
|
|
472
|
+
* musicLengthMs: 30_000,
|
|
473
|
+
* })
|
|
474
|
+
* ```
|
|
475
|
+
*/
|
|
476
|
+
async composeMusic(params) {
|
|
477
|
+
const hasPrompt = typeof params.prompt === "string" && params.prompt.length > 0;
|
|
478
|
+
const hasPlan = params.compositionPlan != null;
|
|
479
|
+
if (hasPrompt === hasPlan) {
|
|
480
|
+
throw new Error(
|
|
481
|
+
"composeMusic: provide exactly one of `prompt` or `compositionPlan`"
|
|
482
|
+
);
|
|
483
|
+
}
|
|
484
|
+
const body = {
|
|
485
|
+
model_id: params.modelId ?? DEFAULT_MUSIC_MODEL
|
|
486
|
+
};
|
|
487
|
+
if (hasPrompt) {
|
|
488
|
+
body.prompt = params.prompt;
|
|
489
|
+
if (params.musicLengthMs !== void 0) body.music_length_ms = params.musicLengthMs;
|
|
490
|
+
if (params.forceInstrumental !== void 0) {
|
|
491
|
+
body.force_instrumental = params.forceInstrumental;
|
|
492
|
+
}
|
|
493
|
+
} else {
|
|
494
|
+
body.composition_plan = params.compositionPlan;
|
|
495
|
+
}
|
|
496
|
+
const { audio, contentType } = await this.request({
|
|
497
|
+
method: "POST",
|
|
498
|
+
path: "/v1/music",
|
|
499
|
+
body,
|
|
500
|
+
accept: "audio/mpeg",
|
|
501
|
+
...params.outputFormat ? { query: { output_format: params.outputFormat } } : {}
|
|
502
|
+
});
|
|
503
|
+
if (!audio) {
|
|
504
|
+
throw new ElevenLabsApiError(
|
|
505
|
+
"composeMusic: expected audio bytes but got a JSON response",
|
|
506
|
+
500,
|
|
507
|
+
""
|
|
508
|
+
);
|
|
509
|
+
}
|
|
510
|
+
return { audio, contentType };
|
|
511
|
+
}
|
|
407
512
|
/** Probe whether a given voice id still exists on the caller's account. */
|
|
408
513
|
async voiceExists(voiceId) {
|
|
409
514
|
const res = await this.fetchImpl(
|
|
@@ -585,6 +690,28 @@ async function readJson(req) {
|
|
|
585
690
|
}
|
|
586
691
|
var NOOP_LOGGER = () => {
|
|
587
692
|
};
|
|
693
|
+
function parseMusicBody(raw) {
|
|
694
|
+
if (raw === null || typeof raw !== "object") return { error: "Invalid JSON body" };
|
|
695
|
+
const b = raw;
|
|
696
|
+
const hasPrompt = typeof b.prompt === "string" && b.prompt.trim().length > 0;
|
|
697
|
+
const hasPlan = b.compositionPlan != null && typeof b.compositionPlan === "object";
|
|
698
|
+
if (hasPrompt === hasPlan) {
|
|
699
|
+
return { error: "Provide exactly one of `prompt` or `compositionPlan`" };
|
|
700
|
+
}
|
|
701
|
+
const params = {};
|
|
702
|
+
if (hasPrompt) {
|
|
703
|
+
params.prompt = b.prompt.trim();
|
|
704
|
+
if (typeof b.musicLengthMs === "number") params.musicLengthMs = b.musicLengthMs;
|
|
705
|
+
if (typeof b.forceInstrumental === "boolean") params.forceInstrumental = b.forceInstrumental;
|
|
706
|
+
} else {
|
|
707
|
+
params.compositionPlan = b.compositionPlan;
|
|
708
|
+
}
|
|
709
|
+
if (typeof b.modelId === "string" && b.modelId.length > 0) params.modelId = b.modelId;
|
|
710
|
+
if (typeof b.outputFormat === "string" && b.outputFormat.length > 0) {
|
|
711
|
+
params.outputFormat = b.outputFormat;
|
|
712
|
+
}
|
|
713
|
+
return { params };
|
|
714
|
+
}
|
|
588
715
|
function resolveProxyOptions(config) {
|
|
589
716
|
if (config.proxy) {
|
|
590
717
|
if (!config.proxy.runtimeToken || !config.proxy.projectId || !config.proxy.apiUrl) {
|
|
@@ -670,6 +797,34 @@ function createProxyHandlers(proxy, log) {
|
|
|
670
797
|
}
|
|
671
798
|
});
|
|
672
799
|
}
|
|
800
|
+
async function doMusic(req) {
|
|
801
|
+
if (req.method !== "POST") return json({ error: "Method Not Allowed" }, 405);
|
|
802
|
+
const raw = await readJson(req);
|
|
803
|
+
const parsed = parseMusicBody(raw);
|
|
804
|
+
if ("error" in parsed) return json({ error: parsed.error }, 400);
|
|
805
|
+
try {
|
|
806
|
+
const upstream = await fetchImpl(proxyUrl("/api/voice/music", {}), {
|
|
807
|
+
method: "POST",
|
|
808
|
+
headers: {
|
|
809
|
+
"x-runtime-token": proxy.runtimeToken,
|
|
810
|
+
"content-type": "application/json",
|
|
811
|
+
accept: "audio/mpeg"
|
|
812
|
+
},
|
|
813
|
+
body: JSON.stringify(parsed.params),
|
|
814
|
+
credentials: "omit"
|
|
815
|
+
});
|
|
816
|
+
const buf = await upstream.arrayBuffer();
|
|
817
|
+
const headers = {};
|
|
818
|
+
const ct = upstream.headers.get("content-type");
|
|
819
|
+
if (ct) headers["content-type"] = ct;
|
|
820
|
+
return new Response(buf, { status: upstream.status, headers });
|
|
821
|
+
} catch (err) {
|
|
822
|
+
log("error", "proxy music failed", {
|
|
823
|
+
error: err instanceof Error ? err.message : String(err)
|
|
824
|
+
});
|
|
825
|
+
return json({ error: "music proxy failed" }, 502);
|
|
826
|
+
}
|
|
827
|
+
}
|
|
673
828
|
function notImplemented(label) {
|
|
674
829
|
return async () => json(
|
|
675
830
|
{
|
|
@@ -682,6 +837,7 @@ function createProxyHandlers(proxy, log) {
|
|
|
682
837
|
return {
|
|
683
838
|
signedUrl: doSignedUrl,
|
|
684
839
|
tts: notImplemented("tts"),
|
|
840
|
+
music: doMusic,
|
|
685
841
|
agent: {
|
|
686
842
|
create: notImplemented("agent.create"),
|
|
687
843
|
patch: notImplemented("agent.patch"),
|
|
@@ -822,6 +978,25 @@ function createVoiceHandlers(config) {
|
|
|
822
978
|
return handleElError(e, "TTS failed");
|
|
823
979
|
}
|
|
824
980
|
}
|
|
981
|
+
async function doMusic(req) {
|
|
982
|
+
if (req.method !== "POST") return json({ error: "Method Not Allowed" }, 405);
|
|
983
|
+
const u = await resolveUser(req);
|
|
984
|
+
if (u instanceof Response) return u;
|
|
985
|
+
const raw = await readJson(req);
|
|
986
|
+
const parsed = parseMusicBody(raw);
|
|
987
|
+
if ("error" in parsed) return json({ error: parsed.error }, 400);
|
|
988
|
+
try {
|
|
989
|
+
const { audio, contentType } = await el.composeMusic(parsed.params);
|
|
990
|
+
return new Response(audio, {
|
|
991
|
+
headers: {
|
|
992
|
+
"content-type": contentType,
|
|
993
|
+
"cache-control": "private, max-age=3600"
|
|
994
|
+
}
|
|
995
|
+
});
|
|
996
|
+
} catch (e) {
|
|
997
|
+
return handleElError(e, "Music generation failed");
|
|
998
|
+
}
|
|
999
|
+
}
|
|
825
1000
|
async function doAgentCreate(req) {
|
|
826
1001
|
if (req.method !== "POST") return json({ error: "Method Not Allowed" }, 405);
|
|
827
1002
|
const u = await resolveUser(req);
|
|
@@ -952,6 +1127,7 @@ function createVoiceHandlers(config) {
|
|
|
952
1127
|
return {
|
|
953
1128
|
signedUrl: doSignedUrl,
|
|
954
1129
|
tts: doTts,
|
|
1130
|
+
music: doMusic,
|
|
955
1131
|
agent: {
|
|
956
1132
|
create: doAgentCreate,
|
|
957
1133
|
patch: doAgentPatch,
|
package/dist/server.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as node_http from 'node:http';
|
|
2
|
-
import {
|
|
2
|
+
import { y as VoiceUser, r as ElevenLabsClient, f as CompanionStore, V as VoiceMemoryStore } from './types-W9y6eMj3.cjs';
|
|
3
3
|
|
|
4
4
|
type GetVoiceUser = (req: Request) => Promise<VoiceUser | null> | VoiceUser | null;
|
|
5
5
|
/**
|
|
@@ -64,6 +64,12 @@ interface VoiceHandlers {
|
|
|
64
64
|
signedUrl: (req: Request) => Promise<Response>;
|
|
65
65
|
/** `POST /voice/tts-preview` — returns raw audio bytes. Expects {@link TtsPreviewBody}. */
|
|
66
66
|
tts: (req: Request) => Promise<Response>;
|
|
67
|
+
/**
|
|
68
|
+
* `POST /voice/music` — generate music via the ElevenLabs Music API.
|
|
69
|
+
* Returns raw audio bytes. Body mirrors {@link ComposeMusicParams}
|
|
70
|
+
* (`prompt` XOR `compositionPlan`, `musicLengthMs`, `modelId`, …).
|
|
71
|
+
*/
|
|
72
|
+
music: (req: Request) => Promise<Response>;
|
|
67
73
|
/** Agent CRUD endpoints. */
|
|
68
74
|
agent: {
|
|
69
75
|
/** `POST /voice/agent` — create a companion + 11Labs agent for the authed user. */
|
package/dist/server.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as node_http from 'node:http';
|
|
2
|
-
import {
|
|
2
|
+
import { y as VoiceUser, r as ElevenLabsClient, f as CompanionStore, V as VoiceMemoryStore } from './types-W9y6eMj3.js';
|
|
3
3
|
|
|
4
4
|
type GetVoiceUser = (req: Request) => Promise<VoiceUser | null> | VoiceUser | null;
|
|
5
5
|
/**
|
|
@@ -64,6 +64,12 @@ interface VoiceHandlers {
|
|
|
64
64
|
signedUrl: (req: Request) => Promise<Response>;
|
|
65
65
|
/** `POST /voice/tts-preview` — returns raw audio bytes. Expects {@link TtsPreviewBody}. */
|
|
66
66
|
tts: (req: Request) => Promise<Response>;
|
|
67
|
+
/**
|
|
68
|
+
* `POST /voice/music` — generate music via the ElevenLabs Music API.
|
|
69
|
+
* Returns raw audio bytes. Body mirrors {@link ComposeMusicParams}
|
|
70
|
+
* (`prompt` XOR `compositionPlan`, `musicLengthMs`, `modelId`, …).
|
|
71
|
+
*/
|
|
72
|
+
music: (req: Request) => Promise<Response>;
|
|
67
73
|
/** Agent CRUD endpoints. */
|
|
68
74
|
agent: {
|
|
69
75
|
/** `POST /voice/agent` — create a companion + 11Labs agent for the authed user. */
|
package/dist/server.js
CHANGED
|
@@ -161,6 +161,49 @@ interface TextToSpeechParams {
|
|
|
161
161
|
/** Accept header; defaults to `audio/mpeg`. */
|
|
162
162
|
accept?: string;
|
|
163
163
|
}
|
|
164
|
+
/** Options for the low-level {@link ElevenLabsClient.request} escape hatch. */
|
|
165
|
+
interface ElevenLabsRequestOptions {
|
|
166
|
+
/** HTTP method, e.g. `'POST'`. */
|
|
167
|
+
method: string;
|
|
168
|
+
/** Path relative to the base URL, e.g. `'/v1/music'`. */
|
|
169
|
+
path: string;
|
|
170
|
+
/** Request body. Plain objects/arrays are JSON-encoded; strings/binary are sent as-is. */
|
|
171
|
+
body?: unknown;
|
|
172
|
+
/** Query params appended to the path. `null`/`undefined` values are skipped. */
|
|
173
|
+
query?: Record<string, string | number | boolean | null | undefined>;
|
|
174
|
+
/** `Accept` header. Defaults to `application/json`. Use `audio/mpeg` for binary endpoints. */
|
|
175
|
+
accept?: string;
|
|
176
|
+
/** Extra headers merged on top of the `xi-api-key` auth header. */
|
|
177
|
+
headers?: Record<string, string>;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Result of a low-level {@link ElevenLabsClient.request}. Exactly one of
|
|
181
|
+
* `json` / `audio` is populated depending on the response `content-type`:
|
|
182
|
+
* JSON responses are parsed into `json`, everything else is returned as
|
|
183
|
+
* raw `audio` bytes.
|
|
184
|
+
*/
|
|
185
|
+
interface ElevenLabsResponse {
|
|
186
|
+
status: number;
|
|
187
|
+
contentType: string;
|
|
188
|
+
json?: unknown;
|
|
189
|
+
audio?: ArrayBuffer;
|
|
190
|
+
}
|
|
191
|
+
/** Parameters for {@link ElevenLabsClient.composeMusic}. */
|
|
192
|
+
interface ComposeMusicParams {
|
|
193
|
+
/** Free-text description of the desired music. Mutually exclusive with `compositionPlan`. */
|
|
194
|
+
prompt?: string;
|
|
195
|
+
/** Pre-built composition plan. Mutually exclusive with `prompt`. */
|
|
196
|
+
compositionPlan?: Record<string, unknown>;
|
|
197
|
+
/** Duration in milliseconds (3,000–600,000). Only valid alongside `prompt`. */
|
|
198
|
+
musicLengthMs?: number;
|
|
199
|
+
/** Music model id. Defaults to `music_v1`. */
|
|
200
|
+
modelId?: string;
|
|
201
|
+
/** Guarantee an instrumental output (prompt mode only). */
|
|
202
|
+
forceInstrumental?: boolean;
|
|
203
|
+
/** Output format, e.g. `mp3_44100_128`. Sent as the `output_format` query param. */
|
|
204
|
+
outputFormat?: string;
|
|
205
|
+
}
|
|
206
|
+
declare const DEFAULT_MUSIC_MODEL = "music_v1";
|
|
164
207
|
/**
|
|
165
208
|
* An error thrown when ElevenLabs returns a non-2xx response. Preserves the
|
|
166
209
|
* status and response body so callers can decide how to surface it.
|
|
@@ -197,6 +240,42 @@ declare class ElevenLabsClient {
|
|
|
197
240
|
modelId: string;
|
|
198
241
|
contentType: string;
|
|
199
242
|
}>;
|
|
243
|
+
/**
|
|
244
|
+
* Low-level escape hatch for any ElevenLabs endpoint not covered by a
|
|
245
|
+
* dedicated method (music, sound-generation, speech-to-text, dubbing,
|
|
246
|
+
* voice-design, …). Handles auth, query encoding, JSON body encoding,
|
|
247
|
+
* and JSON-vs-binary response parsing; non-2xx responses throw
|
|
248
|
+
* {@link ElevenLabsApiError} like the typed methods do.
|
|
249
|
+
*
|
|
250
|
+
* @example
|
|
251
|
+
* ```ts
|
|
252
|
+
* const { json } = await el.request({ method: 'GET', path: '/v1/models' })
|
|
253
|
+
* const { audio } = await el.request({
|
|
254
|
+
* method: 'POST',
|
|
255
|
+
* path: '/v1/sound-generation',
|
|
256
|
+
* body: { text: 'door creak' },
|
|
257
|
+
* accept: 'audio/mpeg',
|
|
258
|
+
* })
|
|
259
|
+
* ```
|
|
260
|
+
*/
|
|
261
|
+
request(opts: ElevenLabsRequestOptions): Promise<ElevenLabsResponse>;
|
|
262
|
+
/**
|
|
263
|
+
* Generate music via `POST /v1/music`. Provide exactly one of `prompt`
|
|
264
|
+
* or `compositionPlan` (ElevenLabs returns 422 otherwise). Returns the
|
|
265
|
+
* raw audio bytes plus the response content type.
|
|
266
|
+
*
|
|
267
|
+
* @example
|
|
268
|
+
* ```ts
|
|
269
|
+
* const { audio } = await el.composeMusic({
|
|
270
|
+
* prompt: 'Upbeat synthwave with driving bass',
|
|
271
|
+
* musicLengthMs: 30_000,
|
|
272
|
+
* })
|
|
273
|
+
* ```
|
|
274
|
+
*/
|
|
275
|
+
composeMusic(params: ComposeMusicParams): Promise<{
|
|
276
|
+
audio: ArrayBuffer;
|
|
277
|
+
contentType: string;
|
|
278
|
+
}>;
|
|
200
279
|
/** Probe whether a given voice id still exists on the caller's account. */
|
|
201
280
|
voiceExists(voiceId: string): Promise<boolean>;
|
|
202
281
|
/**
|
|
@@ -349,4 +428,4 @@ interface TtsPreviewBody {
|
|
|
349
428
|
characterName?: string;
|
|
350
429
|
}
|
|
351
430
|
|
|
352
|
-
export { AUDIO_TAGS as A,
|
|
431
|
+
export { AUDIO_TAGS as A, composeExpressivityBlock as B, CONVAI_SUPPORTED_TTS_MODELS as C, DEFAULT_ALLOWED_TAGS as D, type Expressivity as E, normalizeAudioTags as F, normalizeExpressivity as G, normalizeVoiceSettings as H, readAudioTags as I, readExpressivity as J, readVoiceSettings as K, resolveConvaiTtsModel as L, MEMORY_CLIENT_TOOLS as M, stripAudioTags as N, stripExpressivityBlock as O, type PatchAgentParams as P, type TextToSpeechParams as T, type VoiceMemoryStore as V, AUDIO_TAG_GROUPS as a, type AudioTag as b, type AudioTagGroup as c, CONVAI_TTS_MODEL_FALLBACK as d, type Companion as e, type CompanionStore as f, type ComposeMusicParams as g, type ConvaiClientTool as h, type CreateAgentParams as i, type CreateCompanionBody as j, DEFAULT_ELEVENLABS_BASE_URL as k, DEFAULT_MUSIC_MODEL as l, DEFAULT_VOICE_SETTINGS as m, EXPRESSIVITY_BLOCK_CLOSE as n, EXPRESSIVITY_BLOCK_OPEN as o, EXPRESSIVITY_OPTIONS as p, ElevenLabsApiError as q, ElevenLabsClient as r, type ElevenLabsClientConfig as s, type ElevenLabsRequestOptions as t, type ElevenLabsResponse as u, type PatchCompanionBody as v, type TtsPreviewBody as w, type VoiceSettings as x, type VoiceUser as y, buildPreviewLine as z };
|
|
@@ -161,6 +161,49 @@ interface TextToSpeechParams {
|
|
|
161
161
|
/** Accept header; defaults to `audio/mpeg`. */
|
|
162
162
|
accept?: string;
|
|
163
163
|
}
|
|
164
|
+
/** Options for the low-level {@link ElevenLabsClient.request} escape hatch. */
|
|
165
|
+
interface ElevenLabsRequestOptions {
|
|
166
|
+
/** HTTP method, e.g. `'POST'`. */
|
|
167
|
+
method: string;
|
|
168
|
+
/** Path relative to the base URL, e.g. `'/v1/music'`. */
|
|
169
|
+
path: string;
|
|
170
|
+
/** Request body. Plain objects/arrays are JSON-encoded; strings/binary are sent as-is. */
|
|
171
|
+
body?: unknown;
|
|
172
|
+
/** Query params appended to the path. `null`/`undefined` values are skipped. */
|
|
173
|
+
query?: Record<string, string | number | boolean | null | undefined>;
|
|
174
|
+
/** `Accept` header. Defaults to `application/json`. Use `audio/mpeg` for binary endpoints. */
|
|
175
|
+
accept?: string;
|
|
176
|
+
/** Extra headers merged on top of the `xi-api-key` auth header. */
|
|
177
|
+
headers?: Record<string, string>;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Result of a low-level {@link ElevenLabsClient.request}. Exactly one of
|
|
181
|
+
* `json` / `audio` is populated depending on the response `content-type`:
|
|
182
|
+
* JSON responses are parsed into `json`, everything else is returned as
|
|
183
|
+
* raw `audio` bytes.
|
|
184
|
+
*/
|
|
185
|
+
interface ElevenLabsResponse {
|
|
186
|
+
status: number;
|
|
187
|
+
contentType: string;
|
|
188
|
+
json?: unknown;
|
|
189
|
+
audio?: ArrayBuffer;
|
|
190
|
+
}
|
|
191
|
+
/** Parameters for {@link ElevenLabsClient.composeMusic}. */
|
|
192
|
+
interface ComposeMusicParams {
|
|
193
|
+
/** Free-text description of the desired music. Mutually exclusive with `compositionPlan`. */
|
|
194
|
+
prompt?: string;
|
|
195
|
+
/** Pre-built composition plan. Mutually exclusive with `prompt`. */
|
|
196
|
+
compositionPlan?: Record<string, unknown>;
|
|
197
|
+
/** Duration in milliseconds (3,000–600,000). Only valid alongside `prompt`. */
|
|
198
|
+
musicLengthMs?: number;
|
|
199
|
+
/** Music model id. Defaults to `music_v1`. */
|
|
200
|
+
modelId?: string;
|
|
201
|
+
/** Guarantee an instrumental output (prompt mode only). */
|
|
202
|
+
forceInstrumental?: boolean;
|
|
203
|
+
/** Output format, e.g. `mp3_44100_128`. Sent as the `output_format` query param. */
|
|
204
|
+
outputFormat?: string;
|
|
205
|
+
}
|
|
206
|
+
declare const DEFAULT_MUSIC_MODEL = "music_v1";
|
|
164
207
|
/**
|
|
165
208
|
* An error thrown when ElevenLabs returns a non-2xx response. Preserves the
|
|
166
209
|
* status and response body so callers can decide how to surface it.
|
|
@@ -197,6 +240,42 @@ declare class ElevenLabsClient {
|
|
|
197
240
|
modelId: string;
|
|
198
241
|
contentType: string;
|
|
199
242
|
}>;
|
|
243
|
+
/**
|
|
244
|
+
* Low-level escape hatch for any ElevenLabs endpoint not covered by a
|
|
245
|
+
* dedicated method (music, sound-generation, speech-to-text, dubbing,
|
|
246
|
+
* voice-design, …). Handles auth, query encoding, JSON body encoding,
|
|
247
|
+
* and JSON-vs-binary response parsing; non-2xx responses throw
|
|
248
|
+
* {@link ElevenLabsApiError} like the typed methods do.
|
|
249
|
+
*
|
|
250
|
+
* @example
|
|
251
|
+
* ```ts
|
|
252
|
+
* const { json } = await el.request({ method: 'GET', path: '/v1/models' })
|
|
253
|
+
* const { audio } = await el.request({
|
|
254
|
+
* method: 'POST',
|
|
255
|
+
* path: '/v1/sound-generation',
|
|
256
|
+
* body: { text: 'door creak' },
|
|
257
|
+
* accept: 'audio/mpeg',
|
|
258
|
+
* })
|
|
259
|
+
* ```
|
|
260
|
+
*/
|
|
261
|
+
request(opts: ElevenLabsRequestOptions): Promise<ElevenLabsResponse>;
|
|
262
|
+
/**
|
|
263
|
+
* Generate music via `POST /v1/music`. Provide exactly one of `prompt`
|
|
264
|
+
* or `compositionPlan` (ElevenLabs returns 422 otherwise). Returns the
|
|
265
|
+
* raw audio bytes plus the response content type.
|
|
266
|
+
*
|
|
267
|
+
* @example
|
|
268
|
+
* ```ts
|
|
269
|
+
* const { audio } = await el.composeMusic({
|
|
270
|
+
* prompt: 'Upbeat synthwave with driving bass',
|
|
271
|
+
* musicLengthMs: 30_000,
|
|
272
|
+
* })
|
|
273
|
+
* ```
|
|
274
|
+
*/
|
|
275
|
+
composeMusic(params: ComposeMusicParams): Promise<{
|
|
276
|
+
audio: ArrayBuffer;
|
|
277
|
+
contentType: string;
|
|
278
|
+
}>;
|
|
200
279
|
/** Probe whether a given voice id still exists on the caller's account. */
|
|
201
280
|
voiceExists(voiceId: string): Promise<boolean>;
|
|
202
281
|
/**
|
|
@@ -349,4 +428,4 @@ interface TtsPreviewBody {
|
|
|
349
428
|
characterName?: string;
|
|
350
429
|
}
|
|
351
430
|
|
|
352
|
-
export { AUDIO_TAGS as A,
|
|
431
|
+
export { AUDIO_TAGS as A, composeExpressivityBlock as B, CONVAI_SUPPORTED_TTS_MODELS as C, DEFAULT_ALLOWED_TAGS as D, type Expressivity as E, normalizeAudioTags as F, normalizeExpressivity as G, normalizeVoiceSettings as H, readAudioTags as I, readExpressivity as J, readVoiceSettings as K, resolveConvaiTtsModel as L, MEMORY_CLIENT_TOOLS as M, stripAudioTags as N, stripExpressivityBlock as O, type PatchAgentParams as P, type TextToSpeechParams as T, type VoiceMemoryStore as V, AUDIO_TAG_GROUPS as a, type AudioTag as b, type AudioTagGroup as c, CONVAI_TTS_MODEL_FALLBACK as d, type Companion as e, type CompanionStore as f, type ComposeMusicParams as g, type ConvaiClientTool as h, type CreateAgentParams as i, type CreateCompanionBody as j, DEFAULT_ELEVENLABS_BASE_URL as k, DEFAULT_MUSIC_MODEL as l, DEFAULT_VOICE_SETTINGS as m, EXPRESSIVITY_BLOCK_CLOSE as n, EXPRESSIVITY_BLOCK_OPEN as o, EXPRESSIVITY_OPTIONS as p, ElevenLabsApiError as q, ElevenLabsClient as r, type ElevenLabsClientConfig as s, type ElevenLabsRequestOptions as t, type ElevenLabsResponse as u, type PatchCompanionBody as v, type TtsPreviewBody as w, type VoiceSettings as x, type VoiceUser as y, buildPreviewLine as z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shogo-ai/voice",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.0",
|
|
4
4
|
"description": "Shogo Voice — ElevenLabs/Twilio voice agent infrastructure with React + React Native UI primitives.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -44,6 +44,11 @@
|
|
|
44
44
|
"import": "./dist/route/tts-preview.js",
|
|
45
45
|
"require": "./dist/route/tts-preview.cjs"
|
|
46
46
|
},
|
|
47
|
+
"./route/music": {
|
|
48
|
+
"types": "./dist/route/music.d.ts",
|
|
49
|
+
"import": "./dist/route/music.js",
|
|
50
|
+
"require": "./dist/route/music.cjs"
|
|
51
|
+
},
|
|
47
52
|
"./route/agent": {
|
|
48
53
|
"types": "./dist/route/agent.d.ts",
|
|
49
54
|
"import": "./dist/route/agent.js",
|
|
@@ -65,7 +70,7 @@
|
|
|
65
70
|
"build": "tsup",
|
|
66
71
|
"dev": "tsup --watch",
|
|
67
72
|
"typecheck": "tsc --noEmit",
|
|
68
|
-
"test": "bun --no-env-file test src/"
|
|
73
|
+
"test": "bun --no-env-file --conditions=development test src/"
|
|
69
74
|
},
|
|
70
75
|
"peerDependencies": {
|
|
71
76
|
"@ai-sdk/react": ">=3.0.0",
|