@cartesia/cartesia-js 0.0.4-alpha.0 → 1.0.0-alpha.2
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/.turbo/turbo-build.log +63 -45
- package/CHANGELOG.md +12 -0
- package/README.md +123 -16
- package/dist/chunk-36JBKJUN.js +119 -0
- package/dist/chunk-3F5E46FT.js +212 -0
- package/dist/{chunk-XPIMIAAE.js → chunk-3FL2SNIR.js} +1 -1
- package/dist/chunk-JGP5BIUV.js +34 -0
- package/dist/chunk-KWBSQZTY.js +25 -0
- package/dist/chunk-PQ6CIPFW.js +120 -0
- package/dist/chunk-RO7TY474.js +81 -0
- package/dist/chunk-T3RG6WV4.js +22 -0
- package/dist/{chunk-R4P7LWVZ.js → chunk-WIFMLPT5.js} +31 -6
- package/dist/chunk-WVTITUXX.js +58 -0
- package/dist/chunk-XHTDPLFR.js +19 -0
- package/dist/index.cjs +425 -166
- package/dist/index.d.cts +7 -3
- package/dist/index.d.ts +7 -3
- package/dist/index.js +13 -6
- package/dist/lib/client.cjs +49 -1
- package/dist/lib/client.d.cts +2 -0
- package/dist/lib/client.d.ts +2 -0
- package/dist/lib/client.js +3 -3
- package/dist/lib/constants.cjs +15 -8
- package/dist/lib/constants.d.cts +4 -4
- package/dist/lib/constants.d.ts +4 -4
- package/dist/lib/constants.js +6 -6
- package/dist/lib/index.cjs +310 -171
- package/dist/lib/index.d.cts +6 -2
- package/dist/lib/index.d.ts +6 -2
- package/dist/lib/index.js +9 -6
- package/dist/react/index.cjs +573 -290
- package/dist/react/index.d.cts +20 -14
- package/dist/react/index.d.ts +20 -14
- package/dist/react/index.js +157 -105
- package/dist/react/utils.js +2 -2
- package/dist/tts/index.cjs +496 -0
- package/dist/tts/index.d.cts +17 -0
- package/dist/tts/index.d.ts +17 -0
- package/dist/tts/index.js +12 -0
- package/dist/tts/player.cjs +198 -0
- package/dist/tts/player.d.cts +43 -0
- package/dist/tts/player.d.ts +43 -0
- package/dist/tts/player.js +8 -0
- package/dist/tts/source.cjs +181 -0
- package/dist/tts/source.d.cts +53 -0
- package/dist/tts/source.d.ts +53 -0
- package/dist/tts/source.js +7 -0
- package/dist/{audio → tts}/utils.cjs +25 -60
- package/dist/tts/utils.d.cts +67 -0
- package/dist/tts/utils.d.ts +67 -0
- package/dist/{audio → tts}/utils.js +2 -7
- package/dist/tts/websocket.cjs +479 -0
- package/dist/tts/websocket.d.cts +53 -0
- package/dist/tts/websocket.d.ts +53 -0
- package/dist/tts/websocket.js +11 -0
- package/dist/types/index.d.cts +50 -1
- package/dist/types/index.d.ts +50 -1
- package/dist/voices/index.cjs +157 -0
- package/dist/voices/index.d.cts +12 -0
- package/dist/voices/index.d.ts +12 -0
- package/dist/voices/index.js +9 -0
- package/package.json +2 -1
- package/src/index.ts +1 -0
- package/src/lib/client.ts +15 -1
- package/src/lib/constants.ts +15 -4
- package/src/lib/index.ts +6 -3
- package/src/react/index.ts +176 -110
- package/src/tts/index.ts +17 -0
- package/src/tts/player.ts +110 -0
- package/src/tts/source.ts +115 -0
- package/src/tts/utils.ts +150 -0
- package/src/tts/websocket.ts +214 -0
- package/src/types/index.ts +63 -0
- package/src/voices/index.ts +47 -0
- package/dist/audio/index.cjs +0 -404
- package/dist/audio/index.d.cts +0 -5
- package/dist/audio/index.d.ts +0 -5
- package/dist/audio/index.js +0 -10
- package/dist/audio/utils.d.cts +0 -5
- package/dist/audio/utils.d.ts +0 -5
- package/dist/chunk-4MHF74A7.js +0 -272
- package/dist/chunk-5TSWLYOW.js +0 -113
- package/dist/chunk-MJIFZWHS.js +0 -18
- package/dist/chunk-OVI3W3GG.js +0 -12
- package/dist/chunk-S6A27RQL.js +0 -18
- package/dist/index-C2_3XFxn.d.cts +0 -163
- package/dist/index-DgwnZezj.d.ts +0 -163
- package/src/audio/index.ts +0 -297
- package/src/audio/utils.ts +0 -220
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,57 +1,75 @@
|
|
|
1
1
|
$ tsup src/ --format cjs,esm --dts
|
|
2
|
-
[34mCLI[39m Building entry: src/index.ts, src/
|
|
2
|
+
[34mCLI[39m Building entry: src/index.ts, src/lib/client.ts, src/lib/constants.ts, src/lib/index.ts, src/react/index.ts, src/react/utils.ts, src/tts/index.ts, src/tts/player.ts, src/tts/source.ts, src/tts/utils.ts, src/tts/websocket.ts, src/types/index.ts, src/voices/index.ts
|
|
3
3
|
[34mCLI[39m Using tsconfig: tsconfig.json
|
|
4
4
|
[34mCLI[39m tsup v8.0.2
|
|
5
5
|
[34mCLI[39m Target: es6
|
|
6
6
|
[34mCJS[39m Build start
|
|
7
7
|
[34mESM[39m Build start
|
|
8
|
+
[32mCJS[39m [1mdist/index.cjs [22m[32m21.16 KB[39m
|
|
9
|
+
[32mCJS[39m [1mdist/lib/client.cjs [22m[32m3.51 KB[39m
|
|
10
|
+
[32mCJS[39m [1mdist/react/index.cjs [22m[32m27.38 KB[39m
|
|
11
|
+
[32mCJS[39m [1mdist/tts/index.cjs [22m[32m15.80 KB[39m
|
|
8
12
|
[32mCJS[39m [1mdist/types/index.cjs [22m[32m764.00 B[39m
|
|
9
|
-
[32mCJS[39m [1mdist/index.cjs
|
|
10
|
-
[32mCJS[39m [1mdist/
|
|
11
|
-
[32mCJS[39m [1mdist/
|
|
12
|
-
[32mCJS[39m [1mdist/lib/client.cjs [22m[32m1.40 KB[39m
|
|
13
|
-
[32mCJS[39m [1mdist/lib/constants.cjs [22m[32m1.35 KB[39m
|
|
14
|
-
[32mCJS[39m [1mdist/lib/index.cjs [22m[32m13.32 KB[39m
|
|
15
|
-
[32mCJS[39m [1mdist/react/index.cjs [22m[32m18.78 KB[39m
|
|
13
|
+
[32mCJS[39m [1mdist/voices/index.cjs [22m[32m5.21 KB[39m
|
|
14
|
+
[32mCJS[39m [1mdist/lib/constants.cjs [22m[32m1.61 KB[39m
|
|
15
|
+
[32mCJS[39m [1mdist/lib/index.cjs [22m[32m17.33 KB[39m
|
|
16
16
|
[32mCJS[39m [1mdist/react/utils.cjs [22m[32m1.80 KB[39m
|
|
17
|
-
[32mCJS[39m
|
|
18
|
-
[
|
|
19
|
-
[
|
|
17
|
+
[32mCJS[39m [1mdist/tts/player.cjs [22m[32m6.66 KB[39m
|
|
18
|
+
[32mCJS[39m [1mdist/tts/source.cjs [22m[32m6.63 KB[39m
|
|
19
|
+
[32mCJS[39m [1mdist/tts/utils.cjs [22m[32m3.87 KB[39m
|
|
20
|
+
[32mCJS[39m [1mdist/tts/websocket.cjs [22m[32m15.49 KB[39m
|
|
21
|
+
[32mCJS[39m ⚡️ Build success in 134ms
|
|
20
22
|
[32mESM[39m [1mdist/chunk-FXPGR372.js [22m[32m0 B[39m
|
|
23
|
+
[32mESM[39m [1mdist/tts/source.js [22m[32m112.00 B[39m
|
|
24
|
+
[32mESM[39m [1mdist/tts/utils.js [22m[32m395.00 B[39m
|
|
25
|
+
[32mESM[39m [1mdist/tts/websocket.js [22m[32m242.00 B[39m
|
|
26
|
+
[32mESM[39m [1mdist/types/index.js [22m[32m31.00 B[39m
|
|
27
|
+
[32mESM[39m [1mdist/voices/index.js [22m[32m174.00 B[39m
|
|
28
|
+
[32mESM[39m [1mdist/index.js [22m[32m437.00 B[39m
|
|
21
29
|
[32mESM[39m [1mdist/lib/client.js [22m[32m132.00 B[39m
|
|
22
|
-
[32mESM[39m [1mdist/
|
|
23
|
-
[32mESM[39m [1mdist/
|
|
24
|
-
[32mESM[39m [1mdist/
|
|
25
|
-
[32mESM[39m [1mdist/
|
|
26
|
-
[32mESM[39m [1mdist/chunk-
|
|
27
|
-
[32mESM[39m [1mdist/chunk-4MHF74A7.js [22m[32m7.88 KB[39m
|
|
28
|
-
[32mESM[39m [1mdist/chunk-5TSWLYOW.js [22m[32m3.22 KB[39m
|
|
29
|
-
[32mESM[39m [1mdist/chunk-MJIFZWHS.js [22m[32m385.00 B[39m
|
|
30
|
-
[32mESM[39m [1mdist/chunk-OVI3W3GG.js [22m[32m275.00 B[39m
|
|
30
|
+
[32mESM[39m [1mdist/lib/constants.js [22m[32m183.00 B[39m
|
|
31
|
+
[32mESM[39m [1mdist/lib/index.js [22m[32m322.00 B[39m
|
|
32
|
+
[32mESM[39m [1mdist/react/index.js [22m[32m6.22 KB[39m
|
|
33
|
+
[32mESM[39m [1mdist/chunk-T3RG6WV4.js [22m[32m353.00 B[39m
|
|
34
|
+
[32mESM[39m [1mdist/chunk-WVTITUXX.js [22m[32m1.35 KB[39m
|
|
31
35
|
[32mESM[39m [1mdist/react/utils.js [22m[32m109.00 B[39m
|
|
32
|
-
[32mESM[39m [1mdist/chunk-
|
|
33
|
-
[32mESM[39m [1mdist/
|
|
34
|
-
[32mESM[39m [1mdist/
|
|
35
|
-
[32mESM[39m
|
|
36
|
+
[32mESM[39m [1mdist/chunk-3FL2SNIR.js [22m[32m337.00 B[39m
|
|
37
|
+
[32mESM[39m [1mdist/tts/index.js [22m[32m261.00 B[39m
|
|
38
|
+
[32mESM[39m [1mdist/chunk-KWBSQZTY.js [22m[32m439.00 B[39m
|
|
39
|
+
[32mESM[39m [1mdist/chunk-3F5E46FT.js [22m[32m5.81 KB[39m
|
|
40
|
+
[32mESM[39m [1mdist/chunk-PQ6CIPFW.js [22m[32m4.02 KB[39m
|
|
41
|
+
[32mESM[39m [1mdist/chunk-JGP5BIUV.js [22m[32m841.00 B[39m
|
|
42
|
+
[32mESM[39m [1mdist/chunk-XHTDPLFR.js [22m[32m542.00 B[39m
|
|
43
|
+
[32mESM[39m [1mdist/tts/player.js [22m[32m143.00 B[39m
|
|
44
|
+
[32mESM[39m [1mdist/chunk-36JBKJUN.js [22m[32m3.52 KB[39m
|
|
45
|
+
[32mESM[39m [1mdist/chunk-RO7TY474.js [22m[32m1.95 KB[39m
|
|
46
|
+
[32mESM[39m [1mdist/chunk-WIFMLPT5.js [22m[32m2.27 KB[39m
|
|
47
|
+
[32mESM[39m ⚡️ Build success in 140ms
|
|
36
48
|
[34mDTS[39m Build start
|
|
37
|
-
[32mDTS[39m ⚡️ Build success in
|
|
38
|
-
[32mDTS[39m [1mdist/
|
|
39
|
-
[32mDTS[39m [1mdist/
|
|
40
|
-
[32mDTS[39m [1mdist/lib/
|
|
41
|
-
[32mDTS[39m [1mdist/react/
|
|
42
|
-
[32mDTS[39m [1mdist/
|
|
43
|
-
[32mDTS[39m [1mdist/
|
|
44
|
-
[32mDTS[39m [1mdist/
|
|
45
|
-
[32mDTS[39m [1mdist/
|
|
46
|
-
[32mDTS[39m [1mdist/
|
|
47
|
-
[32mDTS[39m [1mdist/
|
|
48
|
-
[32mDTS[39m [1mdist/
|
|
49
|
-
[32mDTS[39m [1mdist/
|
|
50
|
-
[32mDTS[39m [1mdist/
|
|
51
|
-
[32mDTS[39m [1mdist/
|
|
52
|
-
[32mDTS[39m [1mdist/
|
|
53
|
-
[32mDTS[39m [1mdist/lib/index.d.ts
|
|
54
|
-
[32mDTS[39m [1mdist/
|
|
55
|
-
[32mDTS[39m [1mdist/
|
|
56
|
-
[32mDTS[39m [1mdist/index.d.ts
|
|
57
|
-
[32mDTS[39m [1mdist/
|
|
49
|
+
[32mDTS[39m ⚡️ Build success in 8877ms
|
|
50
|
+
[32mDTS[39m [1mdist/index.d.cts [22m[32m509.00 B[39m
|
|
51
|
+
[32mDTS[39m [1mdist/lib/constants.d.cts [22m[32m247.00 B[39m
|
|
52
|
+
[32mDTS[39m [1mdist/lib/index.d.cts [22m[32m410.00 B[39m
|
|
53
|
+
[32mDTS[39m [1mdist/react/index.d.cts [22m[32m1018.00 B[39m
|
|
54
|
+
[32mDTS[39m [1mdist/react/utils.d.cts [22m[32m240.00 B[39m
|
|
55
|
+
[32mDTS[39m [1mdist/tts/index.d.cts [22m[32m471.00 B[39m
|
|
56
|
+
[32mDTS[39m [1mdist/tts/player.d.cts [22m[32m1.06 KB[39m
|
|
57
|
+
[32mDTS[39m [1mdist/tts/utils.d.cts [22m[32m2.56 KB[39m
|
|
58
|
+
[32mDTS[39m [1mdist/tts/websocket.d.cts [22m[32m2.39 KB[39m
|
|
59
|
+
[32mDTS[39m [1mdist/tts/source.d.cts [22m[32m2.17 KB[39m
|
|
60
|
+
[32mDTS[39m [1mdist/voices/index.d.cts [22m[32m399.00 B[39m
|
|
61
|
+
[32mDTS[39m [1mdist/lib/client.d.cts [22m[32m267.00 B[39m
|
|
62
|
+
[32mDTS[39m [1mdist/types/index.d.cts [22m[32m1.28 KB[39m
|
|
63
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m501.00 B[39m
|
|
64
|
+
[32mDTS[39m [1mdist/lib/constants.d.ts [22m[32m247.00 B[39m
|
|
65
|
+
[32mDTS[39m [1mdist/lib/index.d.ts [22m[32m404.00 B[39m
|
|
66
|
+
[32mDTS[39m [1mdist/react/index.d.ts [22m[32m1016.00 B[39m
|
|
67
|
+
[32mDTS[39m [1mdist/react/utils.d.ts [22m[32m240.00 B[39m
|
|
68
|
+
[32mDTS[39m [1mdist/tts/index.d.ts [22m[32m467.00 B[39m
|
|
69
|
+
[32mDTS[39m [1mdist/tts/player.d.ts [22m[32m1.06 KB[39m
|
|
70
|
+
[32mDTS[39m [1mdist/tts/utils.d.ts [22m[32m2.55 KB[39m
|
|
71
|
+
[32mDTS[39m [1mdist/tts/websocket.d.ts [22m[32m2.39 KB[39m
|
|
72
|
+
[32mDTS[39m [1mdist/tts/source.d.ts [22m[32m2.16 KB[39m
|
|
73
|
+
[32mDTS[39m [1mdist/voices/index.d.ts [22m[32m397.00 B[39m
|
|
74
|
+
[32mDTS[39m [1mdist/lib/client.d.ts [22m[32m266.00 B[39m
|
|
75
|
+
[32mDTS[39m [1mdist/types/index.d.ts [22m[32m1.28 KB[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @cartesia/cartesia-js
|
|
2
2
|
|
|
3
|
+
## 1.0.0-alpha.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 585d2c9: Makes JS client compatible with the Cartesia Stable API (2024-06-10)
|
|
8
|
+
|
|
9
|
+
## 1.0.0-alpha.1
|
|
10
|
+
|
|
11
|
+
### Major Changes
|
|
12
|
+
|
|
13
|
+
- 3ee5bfc: Initial release of Cartesia client with voices and WebSocket support
|
|
14
|
+
|
|
3
15
|
## 0.0.4-alpha.0
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -15,39 +15,146 @@ bun add @cartesia/cartesia-js
|
|
|
15
15
|
|
|
16
16
|
## Usage
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
### CRUD on Voices
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
import Cartesia from "@cartesia/cartesia-js";
|
|
22
|
+
|
|
23
|
+
const cartesia = new Cartesia({
|
|
24
|
+
apiKey: "your-api-key",
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// List all voices.
|
|
28
|
+
const voices = await cartesia.voices.list();
|
|
29
|
+
console.log(voices);
|
|
30
|
+
|
|
31
|
+
// Get a voice.
|
|
32
|
+
const voice = await cartesia.voices.get("<voice-id>");
|
|
33
|
+
console.log(voice);
|
|
34
|
+
|
|
35
|
+
// Create a voice.
|
|
36
|
+
const newVoice = await cartesia.voices.create({
|
|
37
|
+
name: "Tim",
|
|
38
|
+
description: "A deep, resonant voice.",
|
|
39
|
+
embedding: Array(192).fill(1.0),
|
|
40
|
+
});
|
|
41
|
+
console.log(newVoice);
|
|
42
|
+
|
|
43
|
+
// Clone a voice from a URL.
|
|
44
|
+
const clonedVoice = await cartesia.voices.clone({
|
|
45
|
+
mode: "url",
|
|
46
|
+
url: "https://youtu.be/AdtLxlttrHg?si=07OLmDPg__0IN14f&t=6",
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Clone a voice from a file.
|
|
50
|
+
const clonedVoice = await cartesia.voices.clone({
|
|
51
|
+
mode: "clip",
|
|
52
|
+
clip: myFile, // Pass a File object or a Blob.
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### TTS over WebSocket
|
|
57
|
+
|
|
58
|
+
```js
|
|
19
59
|
import Cartesia from "@cartesia/cartesia-js";
|
|
20
60
|
|
|
21
|
-
const cartesia = new Cartesia(
|
|
61
|
+
const cartesia = new Cartesia({
|
|
62
|
+
apiKey: "your-api-key",
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Initialize the WebSocket. Make sure the sample rate you specify is supported.
|
|
66
|
+
const websocket = cartesia.tts.websocket({ sampleRate: 44100 });
|
|
22
67
|
|
|
23
68
|
try {
|
|
24
|
-
await
|
|
69
|
+
await websocket.connect();
|
|
25
70
|
} catch (error) {
|
|
26
71
|
console.error(`Failed to connect to Cartesia: ${error}`);
|
|
27
72
|
}
|
|
28
73
|
|
|
29
|
-
|
|
74
|
+
// Create a stream.
|
|
75
|
+
const response = await websocket.send({
|
|
30
76
|
model: "upbeat-moon",
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
77
|
+
voice: {
|
|
78
|
+
mode: "embedding",
|
|
79
|
+
embedding: Array(192).fill(1.0),
|
|
34
80
|
},
|
|
81
|
+
transcript: "Hello, world!"
|
|
82
|
+
// The WebSocket sets output_format on your behalf.
|
|
83
|
+
// The container is "raw" and the encoding is "pcm_f32le".
|
|
35
84
|
});
|
|
36
85
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
console.log("Received
|
|
41
|
-
console.log("All chunks:", chunks);
|
|
86
|
+
// Access the raw messages from the WebSocket.
|
|
87
|
+
response.on("message", (message) => {
|
|
88
|
+
// Raw message.
|
|
89
|
+
console.log("Received message:", message);
|
|
42
90
|
});
|
|
43
91
|
|
|
44
|
-
|
|
92
|
+
// You can also access messages using a for-await-of loop.
|
|
93
|
+
for await (const message of response.events('message')) {
|
|
45
94
|
// Raw message.
|
|
46
95
|
console.log("Received message:", message);
|
|
47
|
-
}
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
#### Playing audio in the browser
|
|
100
|
+
|
|
101
|
+
(We currently only support playing audio in the browser. Support for other JS environments is coming soon.)
|
|
102
|
+
|
|
103
|
+
```js
|
|
104
|
+
// If you're using the client in the browser, you can play the audio like this:
|
|
105
|
+
import { WebPlayer } from "@cartesia/cartesia-js";
|
|
48
106
|
|
|
49
|
-
// If you're using the client in the browser, you can play the stream like this:
|
|
50
107
|
console.log("Playing stream...");
|
|
51
|
-
|
|
108
|
+
|
|
109
|
+
// Create a Player object.
|
|
110
|
+
const player = new WebPlayer();
|
|
111
|
+
|
|
112
|
+
// Play the audio. (`response` includes a custom Source object that the Player can play.)
|
|
113
|
+
// The call resolves when the audio finishes playing.
|
|
114
|
+
await player.play(response.source);
|
|
115
|
+
|
|
52
116
|
console.log("Done playing.");
|
|
53
117
|
```
|
|
118
|
+
|
|
119
|
+
## React
|
|
120
|
+
|
|
121
|
+
We export a React hook that simplifies the process of using the TTS API. The hook manages the WebSocket connection and provides a simple interface for buffering and playing audio.
|
|
122
|
+
|
|
123
|
+
```jsx
|
|
124
|
+
import { useTTS } from '@cartesia/cartesia-js/react';
|
|
125
|
+
|
|
126
|
+
function TextToSpeech() {
|
|
127
|
+
const tts = useTTS({
|
|
128
|
+
apiKey: "your-api-key",
|
|
129
|
+
samplingRate: 44100,
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
const [text, setText] = useState("");
|
|
133
|
+
|
|
134
|
+
const handlePlay = async () => {
|
|
135
|
+
// Begin buffering the audio.
|
|
136
|
+
const response = await tts.buffer({
|
|
137
|
+
model: "upbeat-moon",
|
|
138
|
+
voice: {
|
|
139
|
+
mode: "embedding",
|
|
140
|
+
embedding: Array(192).fill(1.0),
|
|
141
|
+
},
|
|
142
|
+
transcript: text,
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// Immediately play the audio. (You can also buffer in advance and play later.)
|
|
146
|
+
await tts.play();
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return (
|
|
150
|
+
<div>
|
|
151
|
+
<input type="text" value={text} onChange={(event) => setText(event.target.value)} />
|
|
152
|
+
<button onClick={handlePlay}>Play</button>
|
|
153
|
+
|
|
154
|
+
<div>
|
|
155
|
+
{tts.playbackStatus} | {tts.bufferStatus} | {tts.isWaiting}
|
|
156
|
+
</div>
|
|
157
|
+
</div>
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
```
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import {
|
|
2
|
+
playAudioBuffer
|
|
3
|
+
} from "./chunk-RO7TY474.js";
|
|
4
|
+
import {
|
|
5
|
+
__async,
|
|
6
|
+
__privateAdd,
|
|
7
|
+
__privateGet,
|
|
8
|
+
__privateMethod,
|
|
9
|
+
__privateSet
|
|
10
|
+
} from "./chunk-WIFMLPT5.js";
|
|
11
|
+
|
|
12
|
+
// src/tts/player.ts
|
|
13
|
+
import Emittery from "emittery";
|
|
14
|
+
var _context, _startNextPlaybackAt, _bufferDuration, _emitter, _playBuffer, playBuffer_fn;
|
|
15
|
+
var Player = class {
|
|
16
|
+
/**
|
|
17
|
+
* Create a new Player.
|
|
18
|
+
*
|
|
19
|
+
* @param options - Options for the Player.
|
|
20
|
+
* @param options.bufferDuration - The duration of the audio buffer to play.
|
|
21
|
+
*/
|
|
22
|
+
constructor({ bufferDuration }) {
|
|
23
|
+
__privateAdd(this, _playBuffer);
|
|
24
|
+
__privateAdd(this, _context, null);
|
|
25
|
+
__privateAdd(this, _startNextPlaybackAt, 0);
|
|
26
|
+
__privateAdd(this, _bufferDuration, void 0);
|
|
27
|
+
__privateAdd(this, _emitter, new Emittery());
|
|
28
|
+
__privateSet(this, _bufferDuration, bufferDuration);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Play audio from a source.
|
|
32
|
+
*
|
|
33
|
+
* @param source The source to play audio from.
|
|
34
|
+
* @returns A promise that resolves when the audio has finished playing.
|
|
35
|
+
*/
|
|
36
|
+
play(source) {
|
|
37
|
+
return __async(this, null, function* () {
|
|
38
|
+
__privateSet(this, _startNextPlaybackAt, 0);
|
|
39
|
+
__privateSet(this, _context, new AudioContext({ sampleRate: source.sampleRate }));
|
|
40
|
+
const buffer = new Float32Array(
|
|
41
|
+
source.durationToSampleCount(__privateGet(this, _bufferDuration))
|
|
42
|
+
);
|
|
43
|
+
const plays = [];
|
|
44
|
+
while (true) {
|
|
45
|
+
const read = yield source.read(buffer);
|
|
46
|
+
const playableAudio = buffer.subarray(0, read);
|
|
47
|
+
plays.push(__privateMethod(this, _playBuffer, playBuffer_fn).call(this, playableAudio, source.sampleRate));
|
|
48
|
+
if (read < buffer.length) {
|
|
49
|
+
yield __privateGet(this, _emitter).emit("finish");
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
yield Promise.all(plays);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Pause the audio.
|
|
58
|
+
*
|
|
59
|
+
* @returns A promise that resolves when the audio has been paused.
|
|
60
|
+
*/
|
|
61
|
+
pause() {
|
|
62
|
+
return __async(this, null, function* () {
|
|
63
|
+
if (!__privateGet(this, _context)) {
|
|
64
|
+
throw new Error("AudioContext not initialized.");
|
|
65
|
+
}
|
|
66
|
+
yield __privateGet(this, _context).suspend();
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Resume the audio.
|
|
71
|
+
*
|
|
72
|
+
* @returns A promise that resolves when the audio has been resumed.
|
|
73
|
+
*/
|
|
74
|
+
resume() {
|
|
75
|
+
return __async(this, null, function* () {
|
|
76
|
+
if (!__privateGet(this, _context)) {
|
|
77
|
+
throw new Error("AudioContext not initialized.");
|
|
78
|
+
}
|
|
79
|
+
yield __privateGet(this, _context).resume();
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Toggle the audio.
|
|
84
|
+
*
|
|
85
|
+
* @returns A promise that resolves when the audio has been toggled.
|
|
86
|
+
*/
|
|
87
|
+
toggle() {
|
|
88
|
+
return __async(this, null, function* () {
|
|
89
|
+
if (!__privateGet(this, _context)) {
|
|
90
|
+
throw new Error("AudioContext not initialized.");
|
|
91
|
+
}
|
|
92
|
+
if (__privateGet(this, _context).state === "running") {
|
|
93
|
+
yield this.pause();
|
|
94
|
+
} else {
|
|
95
|
+
yield this.resume();
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
_context = new WeakMap();
|
|
101
|
+
_startNextPlaybackAt = new WeakMap();
|
|
102
|
+
_bufferDuration = new WeakMap();
|
|
103
|
+
_emitter = new WeakMap();
|
|
104
|
+
_playBuffer = new WeakSet();
|
|
105
|
+
playBuffer_fn = function(buf, sampleRate) {
|
|
106
|
+
return __async(this, null, function* () {
|
|
107
|
+
if (!__privateGet(this, _context)) {
|
|
108
|
+
throw new Error("AudioContext not initialized.");
|
|
109
|
+
}
|
|
110
|
+
const startAt = __privateGet(this, _startNextPlaybackAt);
|
|
111
|
+
const duration = buf.length / sampleRate;
|
|
112
|
+
__privateSet(this, _startNextPlaybackAt, duration + Math.max(__privateGet(this, _context).currentTime, __privateGet(this, _startNextPlaybackAt)));
|
|
113
|
+
yield playAudioBuffer(buf, __privateGet(this, _context), startAt, sampleRate);
|
|
114
|
+
});
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
export {
|
|
118
|
+
Player
|
|
119
|
+
};
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Source
|
|
3
|
+
} from "./chunk-PQ6CIPFW.js";
|
|
4
|
+
import {
|
|
5
|
+
Client
|
|
6
|
+
} from "./chunk-JGP5BIUV.js";
|
|
7
|
+
import {
|
|
8
|
+
CARTESIA_VERSION,
|
|
9
|
+
constructApiUrl
|
|
10
|
+
} from "./chunk-XHTDPLFR.js";
|
|
11
|
+
import {
|
|
12
|
+
base64ToArray,
|
|
13
|
+
createMessageHandlerForContextId,
|
|
14
|
+
getEmitteryCallbacks,
|
|
15
|
+
isSentinel
|
|
16
|
+
} from "./chunk-RO7TY474.js";
|
|
17
|
+
import {
|
|
18
|
+
__async,
|
|
19
|
+
__privateAdd,
|
|
20
|
+
__privateGet,
|
|
21
|
+
__privateMethod,
|
|
22
|
+
__privateSet,
|
|
23
|
+
__spreadProps,
|
|
24
|
+
__spreadValues
|
|
25
|
+
} from "./chunk-WIFMLPT5.js";
|
|
26
|
+
|
|
27
|
+
// src/tts/websocket.ts
|
|
28
|
+
import Emittery from "emittery";
|
|
29
|
+
import { humanId } from "human-id";
|
|
30
|
+
import { WebSocket as PartySocketWebSocket } from "partysocket";
|
|
31
|
+
var _isConnected, _sampleRate, _generateId, generateId_fn;
|
|
32
|
+
var WebSocket = class extends Client {
|
|
33
|
+
/**
|
|
34
|
+
* Create a new WebSocket client.
|
|
35
|
+
*
|
|
36
|
+
* @param args - Arguments to pass to the Client constructor.
|
|
37
|
+
*/
|
|
38
|
+
constructor({ sampleRate }, ...args) {
|
|
39
|
+
super(...args);
|
|
40
|
+
/**
|
|
41
|
+
* Generate a unique ID suitable for a streaming context.
|
|
42
|
+
*
|
|
43
|
+
* Not suitable for security purposes or as a primary key, since
|
|
44
|
+
* it lacks the amount of entropy required for those use cases.
|
|
45
|
+
*
|
|
46
|
+
* @returns A unique ID.
|
|
47
|
+
*/
|
|
48
|
+
__privateAdd(this, _generateId);
|
|
49
|
+
__privateAdd(this, _isConnected, false);
|
|
50
|
+
__privateAdd(this, _sampleRate, void 0);
|
|
51
|
+
__privateSet(this, _sampleRate, sampleRate);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Send a message over the WebSocket in order to start a stream.
|
|
55
|
+
*
|
|
56
|
+
* @param inputs - Stream options.
|
|
57
|
+
* @param options - Options for the stream.
|
|
58
|
+
* @param options.timeout - The maximum time to wait for a chunk before cancelling the stream.
|
|
59
|
+
* If `0`, the stream will not time out.
|
|
60
|
+
* @returns A Source object that can be passed to a Player to play the audio.
|
|
61
|
+
*/
|
|
62
|
+
send(inputs, { timeout = 0 } = {}) {
|
|
63
|
+
var _a, _b, _c, _d;
|
|
64
|
+
if (!__privateGet(this, _isConnected)) {
|
|
65
|
+
throw new Error("Not connected to WebSocket. Call .connect() first.");
|
|
66
|
+
}
|
|
67
|
+
const contextId = __privateMethod(this, _generateId, generateId_fn).call(this);
|
|
68
|
+
(_a = this.socket) == null ? void 0 : _a.send(
|
|
69
|
+
JSON.stringify(__spreadProps(__spreadValues({
|
|
70
|
+
context_id: contextId
|
|
71
|
+
}, inputs), {
|
|
72
|
+
output_format: {
|
|
73
|
+
container: "raw",
|
|
74
|
+
encoding: "pcm_f32le",
|
|
75
|
+
sample_rate: __privateGet(this, _sampleRate)
|
|
76
|
+
}
|
|
77
|
+
}))
|
|
78
|
+
);
|
|
79
|
+
const emitter = new Emittery();
|
|
80
|
+
const source = new Source({
|
|
81
|
+
sampleRate: __privateGet(this, _sampleRate)
|
|
82
|
+
});
|
|
83
|
+
const streamCompleteController = new AbortController();
|
|
84
|
+
let timeoutId = null;
|
|
85
|
+
if (timeout > 0) {
|
|
86
|
+
timeoutId = setTimeout(streamCompleteController.abort, timeout);
|
|
87
|
+
}
|
|
88
|
+
const handleMessage = createMessageHandlerForContextId(
|
|
89
|
+
contextId,
|
|
90
|
+
(_0) => __async(this, [_0], function* ({ chunk, message }) {
|
|
91
|
+
emitter.emit("message", message);
|
|
92
|
+
if (isSentinel(chunk)) {
|
|
93
|
+
yield source.close();
|
|
94
|
+
streamCompleteController.abort();
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
yield source.enqueue(base64ToArray([chunk]));
|
|
98
|
+
if (timeoutId) {
|
|
99
|
+
clearTimeout(timeoutId);
|
|
100
|
+
timeoutId = setTimeout(streamCompleteController.abort, timeout);
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
);
|
|
104
|
+
(_b = this.socket) == null ? void 0 : _b.addEventListener("message", handleMessage, {
|
|
105
|
+
signal: streamCompleteController.signal
|
|
106
|
+
});
|
|
107
|
+
(_c = this.socket) == null ? void 0 : _c.addEventListener(
|
|
108
|
+
"close",
|
|
109
|
+
() => {
|
|
110
|
+
streamCompleteController.abort();
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
once: true
|
|
114
|
+
}
|
|
115
|
+
);
|
|
116
|
+
(_d = this.socket) == null ? void 0 : _d.addEventListener(
|
|
117
|
+
"error",
|
|
118
|
+
() => {
|
|
119
|
+
streamCompleteController.abort();
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
once: true
|
|
123
|
+
}
|
|
124
|
+
);
|
|
125
|
+
streamCompleteController.signal.addEventListener("abort", () => {
|
|
126
|
+
source.close();
|
|
127
|
+
if (timeoutId) {
|
|
128
|
+
clearTimeout(timeoutId);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
return __spreadValues({ source }, getEmitteryCallbacks(emitter));
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Authenticate and connect to a Cartesia streaming WebSocket.
|
|
135
|
+
*
|
|
136
|
+
* @returns A promise that resolves when the WebSocket is connected.
|
|
137
|
+
* @throws {Error} If the WebSocket fails to connect.
|
|
138
|
+
*/
|
|
139
|
+
connect() {
|
|
140
|
+
const url = constructApiUrl(
|
|
141
|
+
this.baseUrl,
|
|
142
|
+
`/tts/websocket?cartesia_version=${CARTESIA_VERSION}`,
|
|
143
|
+
"ws"
|
|
144
|
+
);
|
|
145
|
+
url.searchParams.set("api_key", this.apiKey);
|
|
146
|
+
const emitter = new Emittery();
|
|
147
|
+
this.socket = new PartySocketWebSocket(url.toString());
|
|
148
|
+
this.socket.onopen = () => {
|
|
149
|
+
__privateSet(this, _isConnected, true);
|
|
150
|
+
emitter.emit("open");
|
|
151
|
+
};
|
|
152
|
+
this.socket.onclose = () => {
|
|
153
|
+
__privateSet(this, _isConnected, false);
|
|
154
|
+
emitter.emit("close");
|
|
155
|
+
};
|
|
156
|
+
return new Promise(
|
|
157
|
+
(resolve, reject) => {
|
|
158
|
+
var _a, _b, _c;
|
|
159
|
+
(_a = this.socket) == null ? void 0 : _a.addEventListener(
|
|
160
|
+
"open",
|
|
161
|
+
() => {
|
|
162
|
+
resolve(getEmitteryCallbacks(emitter));
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
once: true
|
|
166
|
+
}
|
|
167
|
+
);
|
|
168
|
+
const aborter = new AbortController();
|
|
169
|
+
(_b = this.socket) == null ? void 0 : _b.addEventListener(
|
|
170
|
+
"error",
|
|
171
|
+
() => {
|
|
172
|
+
aborter.abort();
|
|
173
|
+
reject(new Error("WebSocket failed to connect."));
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
signal: aborter.signal
|
|
177
|
+
}
|
|
178
|
+
);
|
|
179
|
+
(_c = this.socket) == null ? void 0 : _c.addEventListener(
|
|
180
|
+
"close",
|
|
181
|
+
() => {
|
|
182
|
+
aborter.abort();
|
|
183
|
+
reject(new Error("WebSocket closed before it could connect."));
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
signal: aborter.signal
|
|
187
|
+
}
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Disconnect from the Cartesia streaming WebSocket.
|
|
194
|
+
*/
|
|
195
|
+
disconnect() {
|
|
196
|
+
var _a;
|
|
197
|
+
(_a = this.socket) == null ? void 0 : _a.close();
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
_isConnected = new WeakMap();
|
|
201
|
+
_sampleRate = new WeakMap();
|
|
202
|
+
_generateId = new WeakSet();
|
|
203
|
+
generateId_fn = function() {
|
|
204
|
+
return humanId({
|
|
205
|
+
separator: "-",
|
|
206
|
+
capitalize: false
|
|
207
|
+
});
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
export {
|
|
211
|
+
WebSocket
|
|
212
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BASE_URL,
|
|
3
|
+
CARTESIA_VERSION,
|
|
4
|
+
constructApiUrl
|
|
5
|
+
} from "./chunk-XHTDPLFR.js";
|
|
6
|
+
import {
|
|
7
|
+
__spreadProps,
|
|
8
|
+
__spreadValues
|
|
9
|
+
} from "./chunk-WIFMLPT5.js";
|
|
10
|
+
|
|
11
|
+
// src/lib/client.ts
|
|
12
|
+
import fetch from "cross-fetch";
|
|
13
|
+
var Client = class {
|
|
14
|
+
constructor(options = {}) {
|
|
15
|
+
if (!(options.apiKey || process.env.CARTESIA_API_KEY)) {
|
|
16
|
+
throw new Error("Missing Cartesia API key.");
|
|
17
|
+
}
|
|
18
|
+
this.apiKey = options.apiKey || process.env.CARTESIA_API_KEY;
|
|
19
|
+
this.baseUrl = options.baseUrl || BASE_URL;
|
|
20
|
+
}
|
|
21
|
+
fetch(path, options = {}) {
|
|
22
|
+
const url = constructApiUrl(this.baseUrl, path);
|
|
23
|
+
return fetch(url.toString(), __spreadProps(__spreadValues({}, options), {
|
|
24
|
+
headers: __spreadValues({
|
|
25
|
+
"X-API-Key": this.apiKey,
|
|
26
|
+
"Cartesia-Version": CARTESIA_VERSION
|
|
27
|
+
}, options.headers)
|
|
28
|
+
}));
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export {
|
|
33
|
+
Client
|
|
34
|
+
};
|