@dimer47/gladia-sdk 1.0.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/README.fr.md +342 -0
- package/README.md +342 -0
- package/dist/index.cjs +575 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +690 -0
- package/dist/index.d.ts +690 -0
- package/dist/index.js +533 -0
- package/dist/index.js.map +1 -0
- package/package.json +58 -0
package/README.fr.md
ADDED
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
# 🎙️ Gladia SDK — TypeScript Client
|
|
2
|
+
|
|
3
|
+
       
|
|
4
|
+
|
|
5
|
+
**SDK TypeScript fait main pour l'[API Gladia](https://docs.gladia.io)** — transcription audio/vidéo pré-enregistrée et en temps réel, avec support complet du WebSocket live streaming.
|
|
6
|
+
|
|
7
|
+
> 🌐 **[English version](README.md)**
|
|
8
|
+
|
|
9
|
+
> 💡 Fonctionne partout : **Node.js**, **Bun**, **Deno**, et **navigateurs** — zéro dépendance runtime.
|
|
10
|
+
|
|
11
|
+
## 🎉 Features
|
|
12
|
+
|
|
13
|
+
- 🎤 **Transcription pré-enregistrée** — envoi par fichier ou URL, polling automatique avec backoff exponentiel
|
|
14
|
+
- 🔴 **Live streaming** — WebSocket typé avec événements temps réel (partiels, finaux, speech events)
|
|
15
|
+
- 📤 **Upload** — multipart (fichier) ou JSON (URL distante)
|
|
16
|
+
- 🌍 **Traduction, résumé, diarisation, analyse de sentiments** — et 10+ addons activables
|
|
17
|
+
- 🔒 **PII redaction** — masquage des données personnelles (GDPR, HIPAA...)
|
|
18
|
+
- 🏷️ **100% typé** — interfaces TypeScript pour les 54 schemas de l'API
|
|
19
|
+
- ⚡ **Dual ESM + CJS** — compatible avec tous les bundlers et runtimes
|
|
20
|
+
- 🪶 **0 dépendance** — uniquement `fetch` et `WebSocket` natifs
|
|
21
|
+
- 🧪 **91 tests unitaires** — couverture complète sans clé API requise
|
|
22
|
+
|
|
23
|
+
## 📍 Install
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install @dimer47/gladia-sdk
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
yarn add @dimer47/gladia-sdk
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pnpm add @dimer47/gladia-sdk
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## 🚀 Quick Start
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import { GladiaClient } from '@dimer47/gladia-sdk';
|
|
41
|
+
|
|
42
|
+
const gladia = new GladiaClient({ apiKey: 'gla_xxx' });
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## 🕹️ Usage
|
|
46
|
+
|
|
47
|
+
### 📤 Upload
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
// Depuis un fichier (Blob, File, Buffer)
|
|
51
|
+
const uploaded = await gladia.upload.fromFile(myBlob, 'recording.wav');
|
|
52
|
+
console.log(uploaded.audio_url);
|
|
53
|
+
|
|
54
|
+
// Depuis une URL distante
|
|
55
|
+
const uploaded = await gladia.upload.fromUrl('https://example.com/audio.mp3');
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### 🎧 Transcription pré-enregistrée
|
|
59
|
+
|
|
60
|
+
#### ✅ Mode simple (POST + polling automatique)
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
const result = await gladia.preRecorded.transcribe({
|
|
64
|
+
audio_url: 'https://example.com/audio.mp3',
|
|
65
|
+
diarization: true,
|
|
66
|
+
translation: true,
|
|
67
|
+
translation_config: { target_languages: ['en'] },
|
|
68
|
+
onPoll: (res) => console.log(`⏳ ${res.status}...`),
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
console.log(result.result?.transcription?.full_transcript);
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
#### 🔧 Contrôle granulaire
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
// Créer un job
|
|
78
|
+
const job = await gladia.preRecorded.create({
|
|
79
|
+
audio_url: 'https://example.com/audio.mp3',
|
|
80
|
+
summarization: true,
|
|
81
|
+
sentiment_analysis: true,
|
|
82
|
+
});
|
|
83
|
+
console.log(`🆔 Job: ${job.id}`);
|
|
84
|
+
|
|
85
|
+
// Vérifier le statut
|
|
86
|
+
const status = await gladia.preRecorded.get(job.id);
|
|
87
|
+
console.log(`📊 Status: ${status.status}`);
|
|
88
|
+
|
|
89
|
+
// Lister les transcriptions
|
|
90
|
+
const list = await gladia.preRecorded.list({ limit: 10 });
|
|
91
|
+
|
|
92
|
+
// Télécharger le fichier audio original
|
|
93
|
+
const audioBlob = await gladia.preRecorded.getFile(job.id);
|
|
94
|
+
|
|
95
|
+
// Supprimer
|
|
96
|
+
await gladia.preRecorded.delete(job.id);
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### 🔴 Live Streaming
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
const session = await gladia.live.stream({
|
|
103
|
+
encoding: 'wav/pcm',
|
|
104
|
+
sample_rate: 16000,
|
|
105
|
+
language_config: { languages: ['fr'] },
|
|
106
|
+
realtime_processing: {
|
|
107
|
+
translation: true,
|
|
108
|
+
translation_config: { target_languages: ['en'] },
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// 📝 Écouter les transcriptions finales
|
|
113
|
+
session.on('transcript:final', (msg) => {
|
|
114
|
+
console.log(`🗣️ ${msg.transcription.text}`);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// 📝 Écouter les transcriptions partielles
|
|
118
|
+
session.on('transcript:partial', (msg) => {
|
|
119
|
+
process.stdout.write(`... ${msg.transcription.text}\r`);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// 🎤 Envoyer des chunks audio
|
|
123
|
+
session.sendAudio(audioChunk); // ArrayBuffer | Uint8Array | Blob
|
|
124
|
+
|
|
125
|
+
// ⏹️ Arrêter et attendre la fin du traitement
|
|
126
|
+
await session.stop();
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
#### 🔧 Contrôle granulaire du live
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
// Initialiser sans ouvrir le WebSocket
|
|
133
|
+
const liveSession = await gladia.live.init(
|
|
134
|
+
{ encoding: 'wav/pcm', sample_rate: 16000 },
|
|
135
|
+
{ region: 'eu-west' },
|
|
136
|
+
);
|
|
137
|
+
console.log(`🔗 WebSocket URL: ${liveSession.url}`);
|
|
138
|
+
|
|
139
|
+
// Lister, récupérer, supprimer
|
|
140
|
+
const sessions = await gladia.live.list({ limit: 5 });
|
|
141
|
+
const session = await gladia.live.get('session-id');
|
|
142
|
+
const audioBlob = await gladia.live.getFile('session-id');
|
|
143
|
+
await gladia.live.delete('session-id');
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## 📦 Addons disponibles
|
|
147
|
+
|
|
148
|
+
| Addon | Champ | Config |
|
|
149
|
+
|-------|-------|--------|
|
|
150
|
+
| 🗣️ Diarisation | `diarization` | `diarization_config` |
|
|
151
|
+
| 🌍 Traduction | `translation` | `translation_config` |
|
|
152
|
+
| 📝 Résumé | `summarization` | `summarization_config` |
|
|
153
|
+
| 💬 Analyse de sentiments | `sentiment_analysis` | — |
|
|
154
|
+
| 🏷️ Entités nommées (NER) | `named_entity_recognition` | — |
|
|
155
|
+
| 📑 Chapitrage | `chapterization` | — |
|
|
156
|
+
| 🔒 PII Redaction | `pii_redaction` | `pii_redaction_config` |
|
|
157
|
+
| 📺 Sous-titres | `subtitles` | `subtitles_config` |
|
|
158
|
+
| 🤖 Audio to LLM | `audio_to_llm` | `audio_to_llm_config` |
|
|
159
|
+
| ✏️ Custom Spelling | `custom_spelling` | `custom_spelling_config` |
|
|
160
|
+
| 📊 Extraction structurée | `structured_data_extraction` | `structured_data_extraction_config` |
|
|
161
|
+
| 🔤 Custom Vocabulary | `custom_vocabulary` | `custom_vocabulary_config` |
|
|
162
|
+
| 🧑 Name Consistency | `name_consistency` | — |
|
|
163
|
+
| 🖥️ Display Mode | `display_mode` | — |
|
|
164
|
+
| 🚫 Modération | `moderation` | — |
|
|
165
|
+
|
|
166
|
+
## 🧮 API Reference
|
|
167
|
+
|
|
168
|
+
### `GladiaClient`
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
new GladiaClient(config: GladiaClientConfig)
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
| Paramètre | Type | Description |
|
|
175
|
+
|-----------|------|-------------|
|
|
176
|
+
| `apiKey` | `string` | 🔑 Clé API Gladia (obligatoire) |
|
|
177
|
+
| `baseUrl` | `string?` | URL de base (défaut: `https://api.gladia.io`) |
|
|
178
|
+
| `WebSocket` | `unknown?` | Constructeur WebSocket custom (pour Node < 21, passer `ws`) |
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
### `gladia.upload`
|
|
183
|
+
|
|
184
|
+
| Méthode | Description |
|
|
185
|
+
|---------|-------------|
|
|
186
|
+
| `fromFile(blob, filename?, signal?)` | 📤 Upload un fichier (multipart) |
|
|
187
|
+
| `fromUrl(url, signal?)` | 🔗 Upload depuis une URL distante |
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
### `gladia.preRecorded`
|
|
192
|
+
|
|
193
|
+
| Méthode | Description |
|
|
194
|
+
|---------|-------------|
|
|
195
|
+
| `transcribe(options)` | ✅ POST + polling auto jusqu'à complétion |
|
|
196
|
+
| `create(request, signal?)` | 📝 Créer un job de transcription |
|
|
197
|
+
| `get(id, signal?)` | 🔍 Récupérer un job par ID |
|
|
198
|
+
| `list(params?, signal?)` | 📋 Lister les jobs (paginé) |
|
|
199
|
+
| `delete(id, signal?)` | 🗑️ Supprimer un job |
|
|
200
|
+
| `getFile(id, signal?)` | 💾 Télécharger le fichier audio original |
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
### `gladia.live`
|
|
205
|
+
|
|
206
|
+
| Méthode | Description |
|
|
207
|
+
|---------|-------------|
|
|
208
|
+
| `stream(options?)` | 🔴 Init + ouverture WebSocket → `LiveSession` |
|
|
209
|
+
| `init(request?, options?)` | 🔧 Init session (retourne l'URL WebSocket) |
|
|
210
|
+
| `get(id, signal?)` | 🔍 Récupérer une session par ID |
|
|
211
|
+
| `list(params?, signal?)` | 📋 Lister les sessions (paginé) |
|
|
212
|
+
| `delete(id, signal?)` | 🗑️ Supprimer une session |
|
|
213
|
+
| `getFile(id, signal?)` | 💾 Télécharger l'enregistrement audio |
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
### `LiveSession`
|
|
218
|
+
|
|
219
|
+
| Méthode / Propriété | Description |
|
|
220
|
+
|---------------------|-------------|
|
|
221
|
+
| `on(event, listener)` | 👂 Écouter un événement typé |
|
|
222
|
+
| `off(event, listener)` | 🔇 Retirer un listener |
|
|
223
|
+
| `sendAudio(data)` | 🎤 Envoyer un chunk audio |
|
|
224
|
+
| `stop()` | ⏹️ Signaler la fin et attendre le traitement |
|
|
225
|
+
| `closed` | `boolean` — état du WebSocket |
|
|
226
|
+
|
|
227
|
+
#### 📡 Événements disponibles
|
|
228
|
+
|
|
229
|
+
| Événement | Type | Description |
|
|
230
|
+
|-----------|------|-------------|
|
|
231
|
+
| `transcript:final` | `LiveTranscriptMessage` | Transcription finale d'un énoncé |
|
|
232
|
+
| `transcript:partial` | `LiveTranscriptMessage` | Transcription partielle en cours |
|
|
233
|
+
| `speech-begin` | `LiveSpeechBeginMessage` | Début de parole détecté |
|
|
234
|
+
| `speech-end` | `LiveSpeechEndMessage` | Fin de parole détectée |
|
|
235
|
+
| `ready` | `LiveReadyMessage` | Session prête à recevoir l'audio |
|
|
236
|
+
| `done` | `LiveDoneMessage` | Traitement terminé |
|
|
237
|
+
| `error` | `LiveErrorMessage` | Erreur WebSocket |
|
|
238
|
+
| `message` | `LiveBaseMessage` | Tout message brut (catch-all) |
|
|
239
|
+
|
|
240
|
+
## ⚠️ Gestion des erreurs
|
|
241
|
+
|
|
242
|
+
Le SDK fournit une hiérarchie d'erreurs typées :
|
|
243
|
+
|
|
244
|
+
```
|
|
245
|
+
GladiaError
|
|
246
|
+
├── GladiaApiError (toute erreur HTTP)
|
|
247
|
+
│ ├── BadRequestError (400)
|
|
248
|
+
│ ├── UnauthorizedError (401)
|
|
249
|
+
│ ├── ForbiddenError (403)
|
|
250
|
+
│ ├── NotFoundError (404)
|
|
251
|
+
│ └── UnprocessableEntityError (422)
|
|
252
|
+
├── GladiaTimeoutError (polling timeout / abort)
|
|
253
|
+
└── GladiaWebSocketError (erreur WebSocket)
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
import { UnauthorizedError, GladiaTimeoutError } from '@dimer47/gladia-sdk';
|
|
258
|
+
|
|
259
|
+
try {
|
|
260
|
+
const result = await gladia.preRecorded.transcribe({
|
|
261
|
+
audio_url: '...',
|
|
262
|
+
pollTimeout: 60_000,
|
|
263
|
+
});
|
|
264
|
+
} catch (err) {
|
|
265
|
+
if (err instanceof UnauthorizedError) {
|
|
266
|
+
console.error('🔑 Clé API invalide');
|
|
267
|
+
} else if (err instanceof GladiaTimeoutError) {
|
|
268
|
+
console.error('⏱️ Timeout dépassé');
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
## 🌐 Compatibilité Node < 21 (WebSocket)
|
|
274
|
+
|
|
275
|
+
Node.js < 21 n'a pas de `WebSocket` global. Utilisez le package [`ws`](https://www.npmjs.com/package/ws) :
|
|
276
|
+
|
|
277
|
+
```bash
|
|
278
|
+
npm install ws
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
import WebSocket from 'ws';
|
|
283
|
+
import { GladiaClient } from '@dimer47/gladia-sdk';
|
|
284
|
+
|
|
285
|
+
const gladia = new GladiaClient({
|
|
286
|
+
apiKey: 'gla_xxx',
|
|
287
|
+
WebSocket,
|
|
288
|
+
});
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
## 🧪 Tests
|
|
292
|
+
|
|
293
|
+
```bash
|
|
294
|
+
npm test # Exécuter les 91 tests
|
|
295
|
+
npm run test:watch # Mode watch
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Les tests utilisent des mocks (`fetch`, `WebSocket`) — **aucune clé API nécessaire**.
|
|
299
|
+
|
|
300
|
+
## 🏗️ Build
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
npm run build # ESM + CJS + .d.ts via tsup
|
|
304
|
+
npm run typecheck # Vérification TypeScript
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
## 📁 Structure du projet
|
|
308
|
+
|
|
309
|
+
```
|
|
310
|
+
gladia-sdk/
|
|
311
|
+
├── src/
|
|
312
|
+
│ ├── index.ts # Re-exports publics
|
|
313
|
+
│ ├── client.ts # GladiaClient (façade)
|
|
314
|
+
│ ├── http.ts # HttpClient (fetch wrapper)
|
|
315
|
+
│ ├── errors.ts # Hiérarchie d'erreurs typées
|
|
316
|
+
│ ├── types/ # 54 interfaces TypeScript
|
|
317
|
+
│ │ ├── config.ts # LanguageConfig, DiarizationConfig, PiiRedactionConfig...
|
|
318
|
+
│ │ ├── common.ts # JobStatus, PaginationParams, GladiaClientConfig
|
|
319
|
+
│ │ ├── upload.ts # UploadResponse, AudioMetadata
|
|
320
|
+
│ │ ├── pre-recorded.ts # PreRecordedRequest (31 champs), responses
|
|
321
|
+
│ │ ├── live.ts # LiveRequest, LiveResponse, LiveRequestParams
|
|
322
|
+
│ │ ├── transcription.ts # Utterance, Word, TranscriptionDTO
|
|
323
|
+
│ │ └── addons.ts # AddonTranslationDTO, SentimentAnalysisEntry...
|
|
324
|
+
│ ├── resources/
|
|
325
|
+
│ │ ├── upload.ts # .fromFile(), .fromUrl()
|
|
326
|
+
│ │ ├── pre-recorded.ts # .create(), .get(), .list(), .delete(), .getFile(), .transcribe()
|
|
327
|
+
│ │ └── live.ts # .init(), .get(), .list(), .delete(), .getFile(), .stream()
|
|
328
|
+
│ ├── live/
|
|
329
|
+
│ │ ├── session.ts # LiveSession (WebSocket typé)
|
|
330
|
+
│ │ └── events.ts # LiveEventMap (11 types d'événements)
|
|
331
|
+
│ └── utils/
|
|
332
|
+
│ └── polling.ts # poll() avec backoff exponentiel
|
|
333
|
+
├── tests/ # 91 tests unitaires (vitest)
|
|
334
|
+
├── dist/ # Build output (ESM + CJS + .d.ts)
|
|
335
|
+
├── package.json
|
|
336
|
+
├── tsconfig.json
|
|
337
|
+
└── tsup.config.ts
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
## 🧾 License
|
|
341
|
+
|
|
342
|
+
[MIT](LICENSE)
|
package/README.md
ADDED
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
# 🎙️ Gladia SDK — TypeScript Client
|
|
2
|
+
|
|
3
|
+
       
|
|
4
|
+
|
|
5
|
+
**Handcrafted TypeScript SDK for the [Gladia API](https://docs.gladia.io)** — supporting both **pre-recorded** transcription (REST + automatic polling) and **real-time live streaming** via WebSocket, with full typed event system.
|
|
6
|
+
|
|
7
|
+
> 🌐 **[Version française](README.fr.md)**
|
|
8
|
+
|
|
9
|
+
> 💡 Works everywhere: **Node.js**, **Bun**, **Deno**, and **browsers** — zero runtime dependencies.
|
|
10
|
+
|
|
11
|
+
## 🎉 Features
|
|
12
|
+
|
|
13
|
+
- 🎤 **Pre-recorded transcription** — upload by file or URL, automatic polling with exponential backoff
|
|
14
|
+
- 🔴 **Live streaming** — typed WebSocket with real-time events (partial, final, speech events)
|
|
15
|
+
- 📤 **Upload** — multipart (file) or JSON (remote URL)
|
|
16
|
+
- 🌍 **Translation, summarization, diarization, sentiment analysis** — and 10+ toggleable addons
|
|
17
|
+
- 🔒 **PII redaction** — personal data masking (GDPR, HIPAA...)
|
|
18
|
+
- 🏷️ **100% typed** — TypeScript interfaces for all 54 API schemas
|
|
19
|
+
- ⚡ **Dual ESM + CJS** — compatible with all bundlers and runtimes
|
|
20
|
+
- 🪶 **0 dependencies** — only native `fetch` and `WebSocket`
|
|
21
|
+
- 🧪 **91 unit tests** — full coverage without any API key required
|
|
22
|
+
|
|
23
|
+
## 📍 Install
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install @dimer47/gladia-sdk
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
yarn add @dimer47/gladia-sdk
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pnpm add @dimer47/gladia-sdk
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## 🚀 Quick Start
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import { GladiaClient } from '@dimer47/gladia-sdk';
|
|
41
|
+
|
|
42
|
+
const gladia = new GladiaClient({ apiKey: 'gla_xxx' });
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## 🕹️ Usage
|
|
46
|
+
|
|
47
|
+
### 📤 Upload
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
// From a file (Blob, File, Buffer)
|
|
51
|
+
const uploaded = await gladia.upload.fromFile(myBlob, 'recording.wav');
|
|
52
|
+
console.log(uploaded.audio_url);
|
|
53
|
+
|
|
54
|
+
// From a remote URL
|
|
55
|
+
const uploaded = await gladia.upload.fromUrl('https://example.com/audio.mp3');
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### 🎧 Pre-recorded Transcription
|
|
59
|
+
|
|
60
|
+
#### ✅ Simple mode (POST + automatic polling)
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
const result = await gladia.preRecorded.transcribe({
|
|
64
|
+
audio_url: 'https://example.com/audio.mp3',
|
|
65
|
+
diarization: true,
|
|
66
|
+
translation: true,
|
|
67
|
+
translation_config: { target_languages: ['en'] },
|
|
68
|
+
onPoll: (res) => console.log(`⏳ ${res.status}...`),
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
console.log(result.result?.transcription?.full_transcript);
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
#### 🔧 Granular control
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
// Create a job
|
|
78
|
+
const job = await gladia.preRecorded.create({
|
|
79
|
+
audio_url: 'https://example.com/audio.mp3',
|
|
80
|
+
summarization: true,
|
|
81
|
+
sentiment_analysis: true,
|
|
82
|
+
});
|
|
83
|
+
console.log(`🆔 Job: ${job.id}`);
|
|
84
|
+
|
|
85
|
+
// Check status
|
|
86
|
+
const status = await gladia.preRecorded.get(job.id);
|
|
87
|
+
console.log(`📊 Status: ${status.status}`);
|
|
88
|
+
|
|
89
|
+
// List transcriptions
|
|
90
|
+
const list = await gladia.preRecorded.list({ limit: 10 });
|
|
91
|
+
|
|
92
|
+
// Download the original audio file
|
|
93
|
+
const audioBlob = await gladia.preRecorded.getFile(job.id);
|
|
94
|
+
|
|
95
|
+
// Delete
|
|
96
|
+
await gladia.preRecorded.delete(job.id);
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### 🔴 Live Streaming
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
const session = await gladia.live.stream({
|
|
103
|
+
encoding: 'wav/pcm',
|
|
104
|
+
sample_rate: 16000,
|
|
105
|
+
language_config: { languages: ['fr'] },
|
|
106
|
+
realtime_processing: {
|
|
107
|
+
translation: true,
|
|
108
|
+
translation_config: { target_languages: ['en'] },
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// 📝 Listen to final transcriptions
|
|
113
|
+
session.on('transcript:final', (msg) => {
|
|
114
|
+
console.log(`🗣️ ${msg.transcription.text}`);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// 📝 Listen to partial transcriptions
|
|
118
|
+
session.on('transcript:partial', (msg) => {
|
|
119
|
+
process.stdout.write(`... ${msg.transcription.text}\r`);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// 🎤 Send audio chunks
|
|
123
|
+
session.sendAudio(audioChunk); // ArrayBuffer | Uint8Array | Blob
|
|
124
|
+
|
|
125
|
+
// ⏹️ Stop and wait for processing to finish
|
|
126
|
+
await session.stop();
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
#### 🔧 Granular live control
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
// Initialize without opening the WebSocket
|
|
133
|
+
const liveSession = await gladia.live.init(
|
|
134
|
+
{ encoding: 'wav/pcm', sample_rate: 16000 },
|
|
135
|
+
{ region: 'eu-west' },
|
|
136
|
+
);
|
|
137
|
+
console.log(`🔗 WebSocket URL: ${liveSession.url}`);
|
|
138
|
+
|
|
139
|
+
// List, retrieve, delete
|
|
140
|
+
const sessions = await gladia.live.list({ limit: 5 });
|
|
141
|
+
const session = await gladia.live.get('session-id');
|
|
142
|
+
const audioBlob = await gladia.live.getFile('session-id');
|
|
143
|
+
await gladia.live.delete('session-id');
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## 📦 Available Addons
|
|
147
|
+
|
|
148
|
+
| Addon | Field | Config |
|
|
149
|
+
|-------|-------|--------|
|
|
150
|
+
| 🗣️ Diarization | `diarization` | `diarization_config` |
|
|
151
|
+
| 🌍 Translation | `translation` | `translation_config` |
|
|
152
|
+
| 📝 Summarization | `summarization` | `summarization_config` |
|
|
153
|
+
| 💬 Sentiment Analysis | `sentiment_analysis` | — |
|
|
154
|
+
| 🏷️ Named Entity Recognition (NER) | `named_entity_recognition` | — |
|
|
155
|
+
| 📑 Chapterization | `chapterization` | — |
|
|
156
|
+
| 🔒 PII Redaction | `pii_redaction` | `pii_redaction_config` |
|
|
157
|
+
| 📺 Subtitles | `subtitles` | `subtitles_config` |
|
|
158
|
+
| 🤖 Audio to LLM | `audio_to_llm` | `audio_to_llm_config` |
|
|
159
|
+
| ✏️ Custom Spelling | `custom_spelling` | `custom_spelling_config` |
|
|
160
|
+
| 📊 Structured Data Extraction | `structured_data_extraction` | `structured_data_extraction_config` |
|
|
161
|
+
| 🔤 Custom Vocabulary | `custom_vocabulary` | `custom_vocabulary_config` |
|
|
162
|
+
| 🧑 Name Consistency | `name_consistency` | — |
|
|
163
|
+
| 🖥️ Display Mode | `display_mode` | — |
|
|
164
|
+
| 🚫 Moderation | `moderation` | — |
|
|
165
|
+
|
|
166
|
+
## 🧮 API Reference
|
|
167
|
+
|
|
168
|
+
### `GladiaClient`
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
new GladiaClient(config: GladiaClientConfig)
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
| Parameter | Type | Description |
|
|
175
|
+
|-----------|------|-------------|
|
|
176
|
+
| `apiKey` | `string` | 🔑 Gladia API key (required) |
|
|
177
|
+
| `baseUrl` | `string?` | Base URL (default: `https://api.gladia.io`) |
|
|
178
|
+
| `WebSocket` | `unknown?` | Custom WebSocket constructor (for Node < 21, pass `ws`) |
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
### `gladia.upload`
|
|
183
|
+
|
|
184
|
+
| Method | Description |
|
|
185
|
+
|--------|-------------|
|
|
186
|
+
| `fromFile(blob, filename?, signal?)` | 📤 Upload a file (multipart) |
|
|
187
|
+
| `fromUrl(url, signal?)` | 🔗 Upload from a remote URL |
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
### `gladia.preRecorded`
|
|
192
|
+
|
|
193
|
+
| Method | Description |
|
|
194
|
+
|--------|-------------|
|
|
195
|
+
| `transcribe(options)` | ✅ POST + automatic polling until completion |
|
|
196
|
+
| `create(request, signal?)` | 📝 Create a transcription job |
|
|
197
|
+
| `get(id, signal?)` | 🔍 Retrieve a job by ID |
|
|
198
|
+
| `list(params?, signal?)` | 📋 List jobs (paginated) |
|
|
199
|
+
| `delete(id, signal?)` | 🗑️ Delete a job |
|
|
200
|
+
| `getFile(id, signal?)` | 💾 Download the original audio file |
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
### `gladia.live`
|
|
205
|
+
|
|
206
|
+
| Method | Description |
|
|
207
|
+
|--------|-------------|
|
|
208
|
+
| `stream(options?)` | 🔴 Init + open WebSocket → `LiveSession` |
|
|
209
|
+
| `init(request?, options?)` | 🔧 Init session (returns the WebSocket URL) |
|
|
210
|
+
| `get(id, signal?)` | 🔍 Retrieve a session by ID |
|
|
211
|
+
| `list(params?, signal?)` | 📋 List sessions (paginated) |
|
|
212
|
+
| `delete(id, signal?)` | 🗑️ Delete a session |
|
|
213
|
+
| `getFile(id, signal?)` | 💾 Download the audio recording |
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
### `LiveSession`
|
|
218
|
+
|
|
219
|
+
| Method / Property | Description |
|
|
220
|
+
|-------------------|-------------|
|
|
221
|
+
| `on(event, listener)` | 👂 Listen to a typed event |
|
|
222
|
+
| `off(event, listener)` | 🔇 Remove a listener |
|
|
223
|
+
| `sendAudio(data)` | 🎤 Send an audio chunk |
|
|
224
|
+
| `stop()` | ⏹️ Signal end and wait for processing |
|
|
225
|
+
| `closed` | `boolean` — WebSocket state |
|
|
226
|
+
|
|
227
|
+
#### 📡 Available Events
|
|
228
|
+
|
|
229
|
+
| Event | Type | Description |
|
|
230
|
+
|-------|------|-------------|
|
|
231
|
+
| `transcript:final` | `LiveTranscriptMessage` | Final transcription of an utterance |
|
|
232
|
+
| `transcript:partial` | `LiveTranscriptMessage` | Partial transcription in progress |
|
|
233
|
+
| `speech-begin` | `LiveSpeechBeginMessage` | Speech start detected |
|
|
234
|
+
| `speech-end` | `LiveSpeechEndMessage` | Speech end detected |
|
|
235
|
+
| `ready` | `LiveReadyMessage` | Session ready to receive audio |
|
|
236
|
+
| `done` | `LiveDoneMessage` | Processing complete |
|
|
237
|
+
| `error` | `LiveErrorMessage` | WebSocket error |
|
|
238
|
+
| `message` | `LiveBaseMessage` | Any raw message (catch-all) |
|
|
239
|
+
|
|
240
|
+
## ⚠️ Error Handling
|
|
241
|
+
|
|
242
|
+
The SDK provides a typed error hierarchy:
|
|
243
|
+
|
|
244
|
+
```
|
|
245
|
+
GladiaError
|
|
246
|
+
├── GladiaApiError (any HTTP error)
|
|
247
|
+
│ ├── BadRequestError (400)
|
|
248
|
+
│ ├── UnauthorizedError (401)
|
|
249
|
+
│ ├── ForbiddenError (403)
|
|
250
|
+
│ ├── NotFoundError (404)
|
|
251
|
+
│ └── UnprocessableEntityError (422)
|
|
252
|
+
├── GladiaTimeoutError (polling timeout / abort)
|
|
253
|
+
└── GladiaWebSocketError (WebSocket error)
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
import { UnauthorizedError, GladiaTimeoutError } from '@dimer47/gladia-sdk';
|
|
258
|
+
|
|
259
|
+
try {
|
|
260
|
+
const result = await gladia.preRecorded.transcribe({
|
|
261
|
+
audio_url: '...',
|
|
262
|
+
pollTimeout: 60_000,
|
|
263
|
+
});
|
|
264
|
+
} catch (err) {
|
|
265
|
+
if (err instanceof UnauthorizedError) {
|
|
266
|
+
console.error('🔑 Invalid API key');
|
|
267
|
+
} else if (err instanceof GladiaTimeoutError) {
|
|
268
|
+
console.error('⏱️ Timeout exceeded');
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
## 🌐 Node < 21 Compatibility (WebSocket)
|
|
274
|
+
|
|
275
|
+
Node.js < 21 does not have a global `WebSocket`. Use the [`ws`](https://www.npmjs.com/package/ws) package:
|
|
276
|
+
|
|
277
|
+
```bash
|
|
278
|
+
npm install ws
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
import WebSocket from 'ws';
|
|
283
|
+
import { GladiaClient } from '@dimer47/gladia-sdk';
|
|
284
|
+
|
|
285
|
+
const gladia = new GladiaClient({
|
|
286
|
+
apiKey: 'gla_xxx',
|
|
287
|
+
WebSocket,
|
|
288
|
+
});
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
## 🧪 Tests
|
|
292
|
+
|
|
293
|
+
```bash
|
|
294
|
+
npm test # Run all 91 tests
|
|
295
|
+
npm run test:watch # Watch mode
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Tests use mocks (`fetch`, `WebSocket`) — **no API key required**.
|
|
299
|
+
|
|
300
|
+
## 🏗️ Build
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
npm run build # ESM + CJS + .d.ts via tsup
|
|
304
|
+
npm run typecheck # TypeScript type checking
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
## 📁 Project Structure
|
|
308
|
+
|
|
309
|
+
```
|
|
310
|
+
gladia-sdk/
|
|
311
|
+
├── src/
|
|
312
|
+
│ ├── index.ts # Public re-exports
|
|
313
|
+
│ ├── client.ts # GladiaClient (facade)
|
|
314
|
+
│ ├── http.ts # HttpClient (fetch wrapper)
|
|
315
|
+
│ ├── errors.ts # Typed error hierarchy
|
|
316
|
+
│ ├── types/ # 54 TypeScript interfaces
|
|
317
|
+
│ │ ├── config.ts # LanguageConfig, DiarizationConfig, PiiRedactionConfig...
|
|
318
|
+
│ │ ├── common.ts # JobStatus, PaginationParams, GladiaClientConfig
|
|
319
|
+
│ │ ├── upload.ts # UploadResponse, AudioMetadata
|
|
320
|
+
│ │ ├── pre-recorded.ts # PreRecordedRequest (31 fields), responses
|
|
321
|
+
│ │ ├── live.ts # LiveRequest, LiveResponse, LiveRequestParams
|
|
322
|
+
│ │ ├── transcription.ts # Utterance, Word, TranscriptionDTO
|
|
323
|
+
│ │ └── addons.ts # AddonTranslationDTO, SentimentAnalysisEntry...
|
|
324
|
+
│ ├── resources/
|
|
325
|
+
│ │ ├── upload.ts # .fromFile(), .fromUrl()
|
|
326
|
+
│ │ ├── pre-recorded.ts # .create(), .get(), .list(), .delete(), .getFile(), .transcribe()
|
|
327
|
+
│ │ └── live.ts # .init(), .get(), .list(), .delete(), .getFile(), .stream()
|
|
328
|
+
│ ├── live/
|
|
329
|
+
│ │ ├── session.ts # LiveSession (typed WebSocket)
|
|
330
|
+
│ │ └── events.ts # LiveEventMap (11 event types)
|
|
331
|
+
│ └── utils/
|
|
332
|
+
│ └── polling.ts # poll() with exponential backoff
|
|
333
|
+
├── tests/ # 91 unit tests (vitest)
|
|
334
|
+
├── dist/ # Build output (ESM + CJS + .d.ts)
|
|
335
|
+
├── package.json
|
|
336
|
+
├── tsconfig.json
|
|
337
|
+
└── tsup.config.ts
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
## 🧾 License
|
|
341
|
+
|
|
342
|
+
[MIT](LICENSE)
|