@transcribe-api/sdk 0.1.3 → 0.1.6

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 (4) hide show
  1. package/README.md +392 -54
  2. package/index.js +1143 -1354
  3. package/package.json +2 -2
  4. package/worker.js +543 -296
package/README.md CHANGED
@@ -1,75 +1,413 @@
1
- # Transcribe API JavaScript SDK
2
-
3
- Official JavaScript SDK for Transcribe API.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- npm install @transcribe-api/sdk
9
- ```
10
-
11
- ## Usage
12
-
1
+ # Transcribe API JavaScript SDK
2
+
3
+ Official JavaScript SDK for Transcribe API.
4
+
5
+ Use this SDK to send one file, many files, local uploads, remote audio URLs, webhook jobs, and large multipart uploads to the Transcribe API from Node.js and modern JavaScript runtimes.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @transcribe-api/sdk
11
+ ```
12
+
13
+ ## Import
14
+
15
+ ```js
16
+ import { TranscribeAPI, TranscribeAPIError } from "@transcribe-api/sdk";
17
+ ```
18
+
19
+ The default export is also `TranscribeAPI`:
20
+
21
+ ```js
22
+ import TranscribeAPI from "@transcribe-api/sdk";
23
+ ```
24
+
25
+ ## Quick start
26
+
13
27
  ```js
14
28
  import { TranscribeAPI } from "@transcribe-api/sdk";
15
-
29
+
30
+ const client = new TranscribeAPI({
31
+ apiKey: process.env.TRANSCRIBE_API_KEY,
32
+ polling: {
33
+ interval: 10,
34
+ timeout: 15 * 60,
35
+ },
36
+ });
37
+
38
+ const result = await client.transcribe({
39
+ language: "en",
40
+ files: [
41
+ { reference_id: "meeting_001", file: "./meeting.mp3" },
42
+ ],
43
+ });
44
+
45
+ console.log(result);
46
+ ```
47
+
48
+ `client.transcribe({ files: [...] })` is the main API for both single-file and multi-file transcription.
49
+
50
+ ## How `transcribe` routes work
51
+
52
+ The SDK automatically chooses the right API flow:
53
+
54
+ - One small local file is sent through the direct synchronous upload path.
55
+ - One remote URL is sent through the direct `/v1/transcribe` endpoint and the API decides whether it can finish immediately or should continue as an async job.
56
+ - Multiple files, files larger than 30 MB, and files estimated over 10 minutes are sent through the async job flow.
57
+ - Large local async uploads use signed R2 upload URLs returned by the API.
58
+ - Multipart upload is used automatically when the backend returns multipart upload instructions.
59
+ - If `polling` is configured, async calls wait until the job reaches a terminal status.
60
+ - If `polling` is not configured, async calls return the upload-completion/job response. Use `client.jobs.get(job_id)` or `client.waitForJobCompletion(job_id, ...)` to check later.
61
+
62
+ Terminal job statuses are `completed`, `failed`, and `insufficient_funds`. Completed job responses include `result_url` when the API has a result file ready.
63
+
64
+ ## Client options
65
+
66
+ ```js
16
67
  const client = new TranscribeAPI({
17
68
  apiKey: "YOUR_API_KEY",
69
+ baseUrl: "https://api.transcribeapi.com/v1",
70
+ uploadConcurrency: 4,
18
71
  showLogs: true,
72
+ logger: console,
19
73
  polling: {
20
74
  interval: 10,
21
75
  timeout: 15 * 60,
22
76
  },
23
77
  });
24
-
25
- const transcript = await client.transcribe({
26
- file: "audio.mp3",
27
- });
28
-
29
- const asyncJob = await client.transcribe({
30
- file: "long-audio.mp3",
31
- multipartConcurrency: 8,
32
- });
33
-
34
- const batchJob = await client.batch.transcribe({
78
+ ```
79
+
80
+ | Option | Description |
81
+ | --- | --- |
82
+ | `apiKey` | Required. Your Transcribe API key. |
83
+ | `baseUrl` | Optional. Defaults to `https://api.transcribeapi.com/v1`. |
84
+ | `uploadConcurrency` | Optional. Number of in-flight upload PUTs. Defaults to `1` and is capped at `32`. |
85
+ | `showLogs` | Optional. Prints upload progress, upload completion, polling status, and final result info. |
86
+ | `logger` | Optional. Logger object with a `log` method. Defaults to `console`. |
87
+ | `polling` | Optional. `{ interval, timeout }` in seconds. `interval` must be at least `10`. Omit or set to `null`/`false` to disable automatic polling. |
88
+
89
+ ## File inputs
90
+
91
+ Each item in `files` must be an object with either `file` or `url`:
92
+
93
+ ```js
94
+ { reference_id: "episode_1", file: "./episode.mp3" }
95
+ { reference_id: "episode_2", url: "https://example.com/signed-audio-url.mp3" }
96
+ ```
97
+
98
+ Supported local/upload inputs:
99
+
100
+ - Node.js local file path strings, such as `"./audio.mp3"`.
101
+ - `File` objects.
102
+ - `Blob` objects.
103
+ - `{ data, name, type }`, where `data` is a `Uint8Array` or `ArrayBuffer`.
104
+
105
+ Supported remote inputs:
106
+
107
+ - Public or signed URLs using `{ url: "https://..." }`.
108
+
109
+ Do not include both `file` and `url` in the same item.
110
+
111
+ ## Single local file
112
+
113
+ ```js
114
+ const result = await client.transcribe({
115
+ files: [
116
+ { reference_id: "call_001", file: "./call.mp3" },
117
+ ],
118
+ language: "en",
119
+ });
120
+ ```
121
+
122
+ For one small local file, this usually uses the direct upload path. Larger files automatically become async jobs.
123
+
124
+ ## Remote URL transcription
125
+
126
+ ```js
127
+ const job = await client.transcribe({
128
+ files: [
129
+ { reference_id: "remote_001", url: "https://example.com/audio.mp3" },
130
+ ],
131
+ language: "en",
132
+ });
133
+ ```
134
+
135
+ For one remote URL, the SDK submits the request to the direct `/v1/transcribe` endpoint and lets the API decide the final route. Small remote files may complete immediately, while larger or longer remote files automatically fall back to the async job flow.
136
+
137
+ ## Batch and mixed input transcription
138
+
139
+ ```js
140
+ const job = await client.transcribe({
141
+ language: "en",
142
+ uploadConcurrency: 8,
143
+ files: [
144
+ { reference_id: "episode_1", file: "./episode-1.mp3" },
145
+ { reference_id: "episode_2", file: "./episode-2.wav" },
146
+ { reference_id: "episode_3", url: "https://example.com/episode-3.m4a" },
147
+ ],
148
+ });
149
+ ```
150
+
151
+ Local files and remote URLs can be mixed in the same batch. When sending multiple files through `transcribe`, provide a unique `reference_id` for every item.
152
+
153
+ ## Per-file language
154
+
155
+ Set `language` at the top level to apply a default to the whole job. Set `language` on a file item to override the default for that file.
156
+
157
+ ```js
158
+ const job = await client.transcribe({
159
+ language: "en",
160
+ files: [
161
+ { reference_id: "intro", file: "./intro.mp3" },
162
+ { reference_id: "french_segment", file: "./segment.m4a", language: "fr" },
163
+ ],
164
+ });
165
+ ```
166
+
167
+ `language` must be a two-letter language code such as `en`, `fr`, or `es`. Omit it, pass an empty value, or pass `"auto"` to avoid sending an explicit language.
168
+
169
+ ## Excluding outputs or features
170
+
171
+ Use `exclude` to pass API exclusions. Arrays are joined with commas before sending. Valid values are only `vtt`, `segments`, `metadata`, `billing`, and `detected_language`.
172
+
173
+ ```js
174
+ const result = await client.transcribe({
175
+ files: [
176
+ { reference_id: "meeting", file: "./meeting.mp3" },
177
+ ],
178
+ exclude: ["vtt", "segments"],
179
+ });
180
+ ```
181
+
182
+ You can also pass a comma-separated string:
183
+
184
+ ```js
185
+ exclude: "metadata,billing"
186
+ ```
187
+
188
+ If `exclude` leaves only one transcript field and removes metadata, billing, and detected language, the API returns that remaining value directly instead of a JSON object. For example, text-only responses return a plain string, VTT-only responses return a plain string, and segments-only responses return an array.
189
+
190
+ ## Webhooks
191
+
192
+ ```js
193
+ const job = await client.transcribe({
194
+ webhookUrl: "https://example.com/transcribe-webhook",
195
+ files: [
196
+ { reference_id: "upload_001", file: "./long-audio.mp3" },
197
+ ],
198
+ });
199
+ ```
200
+
201
+ For a single file or URL, `webhookUrl` is sent through the direct `/v1/transcribe` endpoint and the API decides whether it can finish immediately or should continue as a job. Multi-file requests still use the async batch flow.
202
+
203
+ ## Progress and logs
204
+
205
+ Use `onProgress` to receive structured progress events:
206
+
207
+ ```js
208
+ const job = await client.transcribe({
209
+ files: [
210
+ { reference_id: "episode_1", file: "./episode-1.mp3" },
211
+ { reference_id: "episode_2", file: "./episode-2.mp3" },
212
+ ],
213
+ uploadConcurrency: 4,
214
+ onProgress(event) {
215
+ console.log(event);
216
+ },
217
+ });
218
+ ```
219
+
220
+ Common event names:
221
+
222
+ - `upload_urls_received`
223
+ - `upload_started`
224
+ - `upload_progress`
225
+ - `upload_completed`
226
+
227
+ Progress events may include `jobId`, `jobStatus`, `referenceId`, `loaded`, `total`, `fileLoaded`, `fileTotal`, `batchLoaded`, `batchTotal`, `uploadType`, `partNumber`, `totalParts`, and `multipartConcurrency`.
228
+
229
+ Set `showLogs: true` on the client or on a single call to print built-in progress and polling logs:
230
+
231
+ ```js
232
+ const client = new TranscribeAPI({
233
+ apiKey: process.env.TRANSCRIBE_API_KEY,
234
+ showLogs: true,
235
+ });
236
+ ```
237
+
238
+ ## Manual async jobs
239
+
240
+ `transcribe` uploads automatically. Use `createBatchJob` when you want to separate job creation from upload.
241
+
242
+ ```js
243
+ const job = await client.createBatchJob({
244
+ language: "en",
35
245
  files: [
36
- { reference_id: "episode_1", file: "a.mp3" },
37
- { reference_id: "episode_2", file: "b.wav" },
246
+ { reference_id: "part_1", file: "./part-1.mp3" },
247
+ { reference_id: "part_2", url: "https://example.com/part-2.mp3" },
38
248
  ],
39
249
  });
40
250
 
41
- const remoteJob = await client.transcribe({
42
- file: { url: "https://signed-get-url-from-s3-or-r2" },
43
- });
44
-
45
- const remoteBatchJob = await client.batch.transcribe({
46
- files: [
47
- { reference_id: "episode_1", url: "https://signed-get-url-1" },
48
- { reference_id: "episode_2", url: "https://signed-get-url-2" },
49
- ],
50
- });
51
-
52
- const mixedBatchJob = await client.batch.transcribe({
53
- files: [
54
- { reference_id: "episode_1", file: "local.mp3" },
55
- { reference_id: "episode_2", url: "https://signed-get-url-2" },
56
- ],
251
+ console.log(job.jobId);
252
+
253
+ const completion = await job.upload();
254
+ console.log(completion);
255
+ ```
256
+
257
+ For a single large local file, you can also use `createBigFileJob`:
258
+
259
+ ```js
260
+ const job = await client.createBigFileJob({
261
+ file: { reference_id: "large_001", file: "./large.wav" },
262
+ });
263
+
264
+ const completion = await job.upload();
265
+ ```
266
+
267
+ ## Job helpers
268
+
269
+ ```js
270
+ const job = await client.jobs.get("job_id_here");
271
+ const sameJob = await client.jobs.result("job_id_here");
272
+
273
+ const finalJob = await client.waitForJobCompletion("job_id_here", {
274
+ polling: { interval: 10, timeout: 15 * 60 },
57
275
  });
58
276
  ```
59
277
 
60
- For Cloudflare Workers and other web-style runtimes, use the Worker entrypoint:
278
+ Available job helpers:
279
+
280
+ | Method | Description |
281
+ | --- | --- |
282
+ | `client.jobs.get(jobId)` | Fetches `GET /v1/transcribe/{job_id}`. |
283
+ | `client.jobs.result(jobId)` | Alias for `jobs.get`. |
284
+ | `client.jobs.uploadCompleted(jobId)` | Calls `POST /v1/transcribe/{job_id}/upload-completed`. |
285
+ | `client.jobs.complete(jobId)` | Alias for `jobs.uploadCompleted`. |
286
+ | `client.jobs.createBatch(options)` | Creates a batch job and returns a `BatchJob`. |
287
+ | `client.jobs.createBigFile(options)` | Creates a one-file async upload job and returns a `BatchJob`. |
288
+ | `client.waitForJobCompletion(jobId, options)` | Polls until a terminal job status or timeout. |
289
+
290
+ ## Limits and validation
291
+
292
+ - Batch jobs support up to `10,000` files.
293
+ - Batch local upload payloads support up to `10 GB` total local file size.
294
+ - Direct sync routing is used only for one local file up to `30 MB` and about `10 minutes`.
295
+ - Multipart upload starts when the backend returns multipart upload instructions. The SDK sends `size_bytes` for local files at least `128 MB` so the backend can choose multipart.
296
+ - `uploadConcurrency` defaults to `1` and is capped at `32`.
297
+ - `polling.interval` must be at least `10` seconds.
298
+ - Batch local uploads support `mp3`, `mpeg`, `mpga`, `m4a`, `wav`, and `webm`.
299
+ - `.mp4` is not supported.
300
+
301
+ ## Error handling
302
+
303
+ ```js
304
+ try {
305
+ const result = await client.transcribe({
306
+ files: [
307
+ { reference_id: "bad_file", file: "./missing.mp3" },
308
+ ],
309
+ });
310
+ console.log(result);
311
+ } catch (error) {
312
+ if (error instanceof TranscribeAPIError) {
313
+ console.error(error.message);
314
+ console.error(error.code);
315
+ console.error(error.status);
316
+ console.error(error.response);
317
+ console.error(error.toJSON());
318
+ } else {
319
+ throw error;
320
+ }
321
+ }
322
+ ```
323
+
324
+ `TranscribeAPIError` includes `message`, `code`, `status`, `response`, and any extra fields returned by the API or generated by the SDK.
325
+
326
+ ## Cloudflare Workers and web runtimes
327
+
328
+ Use the Worker entrypoint when running in Cloudflare Workers or other web-standard runtimes:
329
+
330
+ ```js
331
+ import { TranscribeAPI, TranscribeAPIError } from "@transcribe-api/sdk/worker";
332
+ ```
333
+
334
+ The Worker entrypoint keeps the same public client API, but these runtimes do not support Node local file path strings such as `"./audio.mp3"`.
335
+
336
+ Supported Worker-safe inputs:
337
+
338
+ - `File` objects, such as files from `request.formData()`.
339
+ - `Blob` objects.
340
+ - `{ data, name, type }`, where `data` is a `Uint8Array` or `ArrayBuffer`.
341
+ - Remote URLs using `{ url: "https://..." }`.
342
+
343
+ Not supported in Worker runtimes:
344
+
345
+ - Local file path strings.
346
+ - Node.js streams.
347
+ - Node-only filesystem APIs.
348
+
349
+ ## Cloudflare Worker quick start
61
350
 
62
351
  ```js
63
352
  import { TranscribeAPI } from "@transcribe-api/sdk/worker";
353
+
354
+ export default {
355
+ async fetch(request, env) {
356
+ const client = new TranscribeAPI({
357
+ apiKey: env.TRANSCRIBE_API_KEY,
358
+ polling: {
359
+ interval: 10,
360
+ timeout: 15 * 60,
361
+ },
362
+ });
363
+
364
+ const result = await client.transcribe({
365
+ language: "en",
366
+ files: [
367
+ {
368
+ reference_id: "sample_001",
369
+ url: "https://example.com/audio.mp3",
370
+ },
371
+ ],
372
+ });
373
+
374
+ return Response.json(result);
375
+ },
376
+ };
64
377
  ```
65
-
66
- Async uploads use signed R2 URLs returned by the API. Multipart upload is used automatically when the backend returns a multipart flow.
67
- Async job creation now goes through `POST /v1/transcribe` for single-file and batch jobs. For batch calls, each item must be `{ reference_id, file }` or `{ reference_id, url }`, and local plus remote entries can be mixed in the same batch. The SDK adds `size_bytes` automatically for large local files when the backend needs multipart upload.
68
- Set `polling.interval` and optional `polling.timeout` in seconds on the client to make async jobs wait for completion automatically. The SDK enforces a minimum polling interval of `10` seconds and stops on `completed`, `failed`, or `insufficient_funds`.
69
- If polling is not configured, use `GET /v1/transcribe/{job_id}` manually. The response always includes the core job fields and adds `result_url` when `job_status` is `completed`.
70
- The SDK defaults `multipartConcurrency` to `8` for reliability. You can increase it up to `32` when your network path is stable.
71
- For Node path uploads, multipart progress is persisted to a sidecar resume file and the SDK will resume the existing big-file job on the next run instead of starting over.
72
- Multipart uploads also adaptively reduce concurrency on retryable transport errors instead of failing the whole upload immediately.
73
- Set `showLogs: true` on the client or per async call to let the SDK print upload URL receipt, upload progress, and the final `/upload-completed` response automatically. Pass a custom `logger` object if you want those messages redirected somewhere other than `console`.
74
-
75
- Use `@transcribe-api/sdk/worker` when you need a runtime-safe build for Cloudflare Workers. The Worker entrypoint supports remote URLs, `Blob`, `File`, and byte inputs, but does not support local file path strings or Node.js filesystem resume state.
378
+
379
+ ## Uploading a request file in a Worker
380
+
381
+ ```js
382
+ import { TranscribeAPI } from "@transcribe-api/sdk/worker";
383
+
384
+ export default {
385
+ async fetch(request, env) {
386
+ const form = await request.formData();
387
+ const audio = form.get("file");
388
+
389
+ if (!(audio instanceof File)) {
390
+ return Response.json({ error: "Missing file" }, { status: 400 });
391
+ }
392
+
393
+ const client = new TranscribeAPI({
394
+ apiKey: env.TRANSCRIBE_API_KEY,
395
+ polling: {
396
+ interval: 10,
397
+ timeout: 15 * 60,
398
+ },
399
+ });
400
+
401
+ const result = await client.transcribe({
402
+ language: "en",
403
+ files: [
404
+ { reference_id: "upload_001", file: audio },
405
+ ],
406
+ });
407
+
408
+ return Response.json(result);
409
+ },
410
+ };
411
+ ```
412
+
413
+ Remote URL transcription is usually the best fit for Workers when audio is already stored in R2, S3, or another storage service.