@elevenlabs/elevenlabs-js 2.10.0 → 2.11.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.
Files changed (67) hide show
  1. package/Client.js +2 -2
  2. package/api/resources/music/client/Client.d.ts +6 -0
  3. package/api/resources/music/client/Client.js +67 -0
  4. package/api/{types → resources/music/client/requests}/BodyComposeMusicWithADetailedResponseV1MusicDetailedPost.d.ts +5 -1
  5. package/api/resources/music/client/requests/index.d.ts +1 -0
  6. package/api/resources/music/types/MusicComposeDetailedRequestOutputFormat.d.ts +28 -0
  7. package/api/resources/music/types/MusicComposeDetailedRequestOutputFormat.js +27 -0
  8. package/api/resources/music/types/index.d.ts +1 -0
  9. package/api/resources/music/types/index.js +1 -0
  10. package/api/types/User.d.ts +3 -1
  11. package/api/types/index.d.ts +0 -1
  12. package/api/types/index.js +0 -1
  13. package/dist/Client.js +2 -2
  14. package/dist/api/resources/music/client/Client.d.ts +6 -0
  15. package/dist/api/resources/music/client/Client.js +67 -0
  16. package/dist/api/{types → resources/music/client/requests}/BodyComposeMusicWithADetailedResponseV1MusicDetailedPost.d.ts +5 -1
  17. package/dist/api/resources/music/client/requests/index.d.ts +1 -0
  18. package/dist/api/resources/music/types/MusicComposeDetailedRequestOutputFormat.d.ts +28 -0
  19. package/dist/api/resources/music/types/MusicComposeDetailedRequestOutputFormat.js +27 -0
  20. package/dist/api/resources/music/types/index.d.ts +1 -0
  21. package/dist/api/resources/music/types/index.js +1 -0
  22. package/dist/api/types/User.d.ts +3 -1
  23. package/dist/api/types/index.d.ts +0 -1
  24. package/dist/api/types/index.js +0 -1
  25. package/dist/serialization/{types → resources/music/client/requests}/BodyComposeMusicWithADetailedResponseV1MusicDetailedPost.d.ts +5 -5
  26. package/dist/serialization/{types → resources/music/client/requests}/BodyComposeMusicWithADetailedResponseV1MusicDetailedPost.js +2 -2
  27. package/dist/serialization/resources/music/client/requests/index.d.ts +1 -0
  28. package/dist/serialization/resources/music/client/requests/index.js +3 -1
  29. package/dist/serialization/resources/music/types/MusicComposeDetailedRequestOutputFormat.d.ts +10 -0
  30. package/dist/serialization/resources/music/types/MusicComposeDetailedRequestOutputFormat.js +61 -0
  31. package/dist/serialization/resources/music/types/index.d.ts +1 -0
  32. package/dist/serialization/resources/music/types/index.js +1 -0
  33. package/dist/serialization/types/User.d.ts +1 -0
  34. package/dist/serialization/types/User.js +1 -0
  35. package/dist/serialization/types/index.d.ts +0 -1
  36. package/dist/serialization/types/index.js +0 -1
  37. package/dist/version.d.ts +1 -1
  38. package/dist/version.js +1 -1
  39. package/dist/wrapper/ElevenLabsClient.d.ts +3 -0
  40. package/dist/wrapper/ElevenLabsClient.js +8 -0
  41. package/dist/wrapper/index.d.ts +1 -0
  42. package/dist/wrapper/index.js +3 -1
  43. package/dist/wrapper/music.d.ts +43 -0
  44. package/dist/wrapper/music.js +162 -0
  45. package/package.json +1 -1
  46. package/serialization/{types → resources/music/client/requests}/BodyComposeMusicWithADetailedResponseV1MusicDetailedPost.d.ts +5 -5
  47. package/serialization/{types → resources/music/client/requests}/BodyComposeMusicWithADetailedResponseV1MusicDetailedPost.js +2 -2
  48. package/serialization/resources/music/client/requests/index.d.ts +1 -0
  49. package/serialization/resources/music/client/requests/index.js +3 -1
  50. package/serialization/resources/music/types/MusicComposeDetailedRequestOutputFormat.d.ts +10 -0
  51. package/serialization/resources/music/types/MusicComposeDetailedRequestOutputFormat.js +61 -0
  52. package/serialization/resources/music/types/index.d.ts +1 -0
  53. package/serialization/resources/music/types/index.js +1 -0
  54. package/serialization/types/User.d.ts +1 -0
  55. package/serialization/types/User.js +1 -0
  56. package/serialization/types/index.d.ts +0 -1
  57. package/serialization/types/index.js +0 -1
  58. package/version.d.ts +1 -1
  59. package/version.js +1 -1
  60. package/wrapper/ElevenLabsClient.d.ts +3 -0
  61. package/wrapper/ElevenLabsClient.js +8 -0
  62. package/wrapper/index.d.ts +1 -0
  63. package/wrapper/index.js +3 -1
  64. package/wrapper/music.d.ts +43 -0
  65. package/wrapper/music.js +162 -0
  66. /package/api/{types → resources/music/client/requests}/BodyComposeMusicWithADetailedResponseV1MusicDetailedPost.js +0 -0
  67. /package/dist/api/{types → resources/music/client/requests}/BodyComposeMusicWithADetailedResponseV1MusicDetailedPost.js +0 -0
@@ -0,0 +1,162 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.Music = void 0;
13
+ const Client_1 = require("../api/resources/music/client/Client");
14
+ class Music extends Client_1.Music {
15
+ constructor(options = {}) {
16
+ super(options);
17
+ }
18
+ /**
19
+ * Compose a song from a prompt or a composition plan with detailed response parsing.
20
+ * This method calls the original composeDetailed and then parses the stream response.
21
+ * @throws {@link ElevenLabs.UnprocessableEntityError}
22
+ */
23
+ // @ts-expect-error - Intentionally overriding parent method with different return type
24
+ composeDetailed() {
25
+ const _super = Object.create(null, {
26
+ composeDetailed: { get: () => super.composeDetailed }
27
+ });
28
+ return __awaiter(this, arguments, void 0, function* (request = {}, requestOptions) {
29
+ // Call the parent method to get the stream
30
+ const response = yield _super.composeDetailed.call(this, request, requestOptions);
31
+ // Parse the stream using your existing parsing method
32
+ const parsedResponse = yield this.parseMultipart(response);
33
+ return parsedResponse;
34
+ });
35
+ }
36
+ /**
37
+ * Reads a ReadableStream containing multipart data and parses it into JSON and audio parts
38
+ * @param stream - ReadableStream from ElevenLabs music API response
39
+ * @returns Object containing parsed JSON metadata, audio Buffer, and filename
40
+ */
41
+ parseMultipart(stream) {
42
+ return __awaiter(this, void 0, void 0, function* () {
43
+ // Read the stream and collect all chunks
44
+ const reader = stream.getReader();
45
+ const chunks = [];
46
+ let done = false;
47
+ while (!done) {
48
+ const result = yield reader.read();
49
+ done = result.done;
50
+ if (result.value) {
51
+ chunks.push(result.value);
52
+ }
53
+ }
54
+ // Combine all chunks into a single buffer
55
+ const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
56
+ const responseBytes = new Uint8Array(totalLength);
57
+ let offset = 0;
58
+ for (const chunk of chunks) {
59
+ responseBytes.set(chunk, offset);
60
+ offset += chunk.length;
61
+ }
62
+ // Parse the multipart content
63
+ const responseText = new TextDecoder().decode(responseBytes);
64
+ const lines = responseText.split('\n');
65
+ const boundary = lines[0].trim();
66
+ // Find the JSON part (should be early in the response)
67
+ let jsonData = null;
68
+ let filename = 'generated_music.mp3';
69
+ // Parse JSON from the text representation
70
+ for (let i = 0; i < Math.min(10, lines.length); i++) {
71
+ if (lines[i].includes('Content-Type: application/json') && i + 2 < lines.length) {
72
+ const jsonLine = lines[i + 2];
73
+ if (jsonLine.trim() && jsonLine.startsWith('{')) {
74
+ try {
75
+ const rawJson = JSON.parse(jsonLine);
76
+ // Convert snake_case keys to camelCase
77
+ jsonData = this.toCamelCase(rawJson);
78
+ console.log('✓ Successfully parsed JSON metadata');
79
+ }
80
+ catch (e) {
81
+ console.warn('Failed to parse JSON:', e);
82
+ }
83
+ break;
84
+ }
85
+ }
86
+ }
87
+ // Extract filename from headers
88
+ for (let i = 0; i < Math.min(20, lines.length); i++) {
89
+ if (lines[i].includes('filename=')) {
90
+ const match = lines[i].match(/filename="([^"]+)"/);
91
+ if (match) {
92
+ filename = match[1];
93
+ break;
94
+ }
95
+ }
96
+ }
97
+ // Find where the audio data starts (after the second boundary and headers)
98
+ const boundaryBytes = new TextEncoder().encode(boundary);
99
+ let firstBoundary = -1;
100
+ let secondBoundary = -1;
101
+ for (let i = 0; i <= responseBytes.length - boundaryBytes.length; i++) {
102
+ let match = true;
103
+ for (let j = 0; j < boundaryBytes.length; j++) {
104
+ if (responseBytes[i + j] !== boundaryBytes[j]) {
105
+ match = false;
106
+ break;
107
+ }
108
+ }
109
+ if (match) {
110
+ if (firstBoundary === -1) {
111
+ firstBoundary = i;
112
+ }
113
+ else if (secondBoundary === -1) {
114
+ secondBoundary = i;
115
+ break;
116
+ }
117
+ }
118
+ }
119
+ if (secondBoundary === -1) {
120
+ throw new Error('Could not find audio part boundary');
121
+ }
122
+ // Find the start of audio data (after headers and empty line)
123
+ let audioStart = secondBoundary + boundaryBytes.length;
124
+ // Skip past the headers to find the empty line
125
+ while (audioStart < responseBytes.length - 1) {
126
+ if (responseBytes[audioStart] === 0x0A && responseBytes[audioStart + 1] === 0x0A) {
127
+ // Found \n\n - audio starts after this
128
+ audioStart += 2;
129
+ break;
130
+ }
131
+ audioStart++;
132
+ }
133
+ // Audio goes until the end (or until we find another boundary, but usually it's the end)
134
+ const audioBuffer = Buffer.from(responseBytes.slice(audioStart));
135
+ if (!jsonData) {
136
+ throw new Error('Could not parse JSON data');
137
+ }
138
+ return {
139
+ json: jsonData,
140
+ audio: audioBuffer,
141
+ filename: filename
142
+ };
143
+ });
144
+ }
145
+ /**
146
+ * Converts snake_case keys to camelCase recursively
147
+ */
148
+ toCamelCase(obj) {
149
+ if (Array.isArray(obj)) {
150
+ return obj.map((item) => this.toCamelCase(item));
151
+ }
152
+ else if (obj !== null && typeof obj === 'object') {
153
+ return Object.keys(obj).reduce((result, key) => {
154
+ const camelKey = key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
155
+ result[camelKey] = this.toCamelCase(obj[key]);
156
+ return result;
157
+ }, {});
158
+ }
159
+ return obj;
160
+ }
161
+ }
162
+ exports.Music = Music;