# Node.js SDK

> 用@transcript1/sdk在服务端转录视频链接和本地文件，获取文本或字幕，并监听进度、处理错误。

Canonical: https://transcript1.com/zh/docs/sdk
Language: zh-Hans
Last updated: 2026-10-16

在TypeScript或JavaScript服务端调用`@transcript1/sdk`，即可上传文件、提交转录，并等待转录文本生成。

处理社交平台链接，请使用SDK 1.1.0或更高版本。SDK 1.0.1只支持YouTube，其他平台的链接会在本地校验时被拒绝。用`npm i @transcript1/sdk@latest`更新。

这个版本要求针对最初支持的YouTube、X、TikTok、Instagram、Facebook和Bluesky。使用Twitch、Dailymotion、Pinterest、LinkedIn或Snapchat时，需要安装已加入对应平台支持的SDK版本，否则链接可能在本地校验时被拒绝。

## 安装SDK

```bash
npm i @transcript1/sdk
```

下文示例采用ES模块。可以保存为`.mjs`文件；使用`.js`文件时，在`package.json`中设置`"type": "module"`。Node 20.19+也支持`require()`，例如`require('@transcript1/sdk')`。

## 配置API密钥

先到[“API keys”](https://transcript1.com/dashboard/account/tokens)页面创建密钥。可通过服务器环境变量`TRANSCRIPT1_API_KEY`提供，也可在创建实例时传入`apiKey`：

```javascript
import { Transcript1 } from '@transcript1/sdk';

const t1 = new Transcript1(); // reads TRANSCRIPT1_API_KEY
const other = new Transcript1({ apiKey: 't1_...' });
```

未提供密钥就创建实例，会抛出`Transcript1Error`，其错误码为`missing_api_key`。

## 提交转录并等待文本

调用`transcribe(input, options)`后，SDK会创建任务，等转录文本生成后再返回。返回类型为`CompletedTranscription`，包含`status: 'completed'`和`transcript`字段。任务失败或被取消时，Promise会被reject（拒绝）。

```javascript
const done = await t1.transcribe('https://youtu.be/dQw4w9WgXcQ');
console.log(done.transcript.text);

const file = await t1.transcribe('./interview.m4a', { speakers: true });
```

输入为Buffer或Uint8Array时，需要附上文件名，让SDK判断媒体类型：

```javascript
import { readFile } from 'node:fs/promises';

const buffer = await readFile('./call.mp3');
const call = await t1.transcribe(buffer, { filename: 'call.mp3' });
```

SDK把以`http://`或`https://`开头的字符串当作链接，其他字符串当作文件路径。链接支持YouTube、X、TikTok、Instagram、Facebook、Bluesky、Twitch、Dailymotion、Pinterest、LinkedIn和Snapchat，也支持直接上传文件。后续新增的平台要求HTTPS。哪些公开录制内容可以提交、各平台支持哪些字幕，见[来源与选项](https://transcript1.com/zh/docs/sources-and-options)。文件不能超过2,000,000,000字节，扩展名支持mp3、wav、m4a、flac、ogg、opus、mp4、mov、webm和mkv。

帖子必须公开；同一个帖子有多个视频时，只转录第1个。平台由API根据链接自动判断，不需要自行识别。短链接的支持情况和其他限制见[来源与选项](https://transcript1.com/zh/docs/sources-and-options)。

除了路径和Buffer，也能传入Blob、`ReadableStream<Uint8Array>`，或逐块提供Uint8Array的异步可迭代对象。Blob需要指定`filename`，带文件名的File除外。流和异步可迭代对象必须同时提供`filename`和`size`，后者是以字节为单位的大小。

## 获取文本或字幕文件

用`download(id, options)`获取指定格式的转录文本。它会等转录完成，返回值始终是字符串；选择JSON时，拿到的是API返回的JSON原文，不是解析后的对象。

```javascript
const text = await t1.download(done.id); // text is the default
const withTimes = await t1.download(done.id, { timestamps: true });
const srt = await t1.download(done.id, { format: 'srt' });
const vtt = await t1.download(done.id, { format: 'vtt' });
const json = await t1.download(done.id, { format: 'json' });
```

只有`text`支持`timestamps: true`。其他格式设置该选项，Promise会被reject（拒绝），错误码为`invalid_input`。如果任务失败或被取消，`download`返回的Promise也会被reject（拒绝）。

## 提交后稍后再取文本

不想等待转录完成，可用`transcriptions.create`先提交任务。输入为文件时，该调用仍会等上传结束后再返回。

```javascript
const job = await t1.transcriptions.create('./long-interview.mp4');
const now = await t1.transcriptions.get(job.id);
const finished = await t1.transcriptions.get(job.id, { wait: true });
```

`get`默认立即返回任务的当前状态。加上`wait: true`，则等到状态变为`completed`、`failed`或`canceled`再返回。先检查`finished.status`，再读取转录文本。注意：与`transcribe`不同，任务失败或被取消不会让`get`返回的Promise被reject（拒绝）。

## 查询任务、删除任务和查看账号

```javascript
for await (const item of t1.transcriptions.list({ status: 'completed', limit: 50 })) {
  console.log(item.id, item.created_at);
}

await t1.transcriptions.delete(job.id);
const account = await t1.account();
console.log(account.minutes.remaining);
```

迭代`list`时，SDK会按需翻页。可按`status`筛选，也可指定`platform`：`youtube`、`x`、`tiktok`、`instagram`、`facebook`、`bluesky`、`twitch`、`dailymotion`、`pinterest`、`linkedin`、`snapchat`或`upload`。`limit`表示每页数量，可设为1到100，API默认为20。返回对象沿用API的`snake_case`字段名。`media_id`只作为字符串使用，不要解析其中的内容。

对运行中的任务调用`delete`会取消任务；对已结束的任务调用，则会删除任务和转录文本。用`account`查询套餐、分钟余额和用量限制。

## 调用选项

创建实例时可传入`apiKey`、`baseUrl`、`fetch`和`maxRetries`。未指定`baseUrl`时，SDK会使用环境变量`TRANSCRIPT1_API_URL`；该变量也未设置时，使用`https://api.transcript1.com`。需要自定义网络请求时，传入自己的`fetch`实现。`maxRetries`可设为0到10的整数，默认2。

以下选项同时适用于`transcribe`和`transcriptions.create`：

| 选项 | 用法 |
|---|---|
| `speakers` | 开启说话人分离。 |
| `language` | 用`auto`自动识别（默认），或指定ISO 639-1语言代码。 |
| `source` | 链接支持`auto`或`stt`。YouTube、X、TikTok、Bluesky、Dailymotion和LinkedIn有可用字幕轨道时，也支持`captions`。 |
| `fresh` | 重新转录链接，不复用最近24小时内已有的转录。 |
| `filename` | Buffer、未命名的Blob和流必须提供；也可用来覆盖原文件名。 |
| `size` | 流和异步可迭代对象必须提供，单位为字节。 |
| `idempotencyKey` | 不传时，每次调用都会生成新的UUID。 |
| `onProgress` | 通过回调监听进度事件。 |
| `signal` | 传入AbortSignal，用于中止本次调用。 |

`transcriptions.get`支持`wait`、`includeWords`、`onProgress`和`signal`。要获取逐词时间戳，设置`includeWords: true`；等待时的进度变化通过`onProgress`通知。

`download`支持`format`、`timestamps`和`signal`，`list`也支持`signal`。调用`transcriptions.delete(id, options)`或`account(options)`时，可在options参数中传入`{ signal }`。

## 监听上传和转录进度

在`transcribe`、`transcriptions.create`，或开启等待的`transcriptions.get`调用中，传入`onProgress`：

```javascript
await t1.transcribe('./interview.m4a', {
  onProgress(event) {
    console.log(event);
  },
});
```

| 事件类型 | 事件内容 |
|---|---|
| `upload` | `sent`为已上传大小，`total`为总大小，单位都是字节。 |
| `status` | `status`表示当前任务状态。 |
| `waiting_slot` | `retryAfter`表示多少秒后再次尝试获取可用的任务名额。 |
| `reconnecting` | 等待时每次连接中断都会触发1次，没有额外字段。 |

## 中止调用与取消任务

用AbortController创建`AbortSignal`并传入，即可中止调用。也可以用`AbortSignal.timeout`限制等待时间：

```javascript
await t1.transcribe('https://youtu.be/dQw4w9WgXcQ', {
  signal: AbortSignal.timeout(10 * 60_000),
});
```

如果还没发出首个请求就中止，Promise会被reject（拒绝），错误码为`aborted`，不带任务id。上传过程中中止时，如果任务仍为`awaiting_upload`，SDK会先尝试删除它。随后Promise会被reject（拒绝），错误码为`aborted`，并在错误中附上任务id。

中止等待不等于取消转录，服务端任务仍会继续。可以取出错误中的`transcriptionId`，用`transcriptions.get(id, { wait: true })`接着等待。确实要取消任务时，调用`transcriptions.delete(id)`。

等待转录时，如果发生网络错误，或收到HTTP 429、500、502、503、504响应，SDK会持续重试，不受重试次数限制。重连间隔依次为2、4、8、16秒，之后为30秒。其他请求按`maxRetries`重试。创建任务时若没有可用的活跃任务名额，SDK也会等待并重试。需要限制整个调用的时长时，使用`signal`。

## 捕获并处理错误

API请求、转录任务和SDK本地错误，都可以通过捕获`Transcript1Error`来处理：

```javascript
import { Transcript1Error } from '@transcript1/sdk';

try {
  await t1.transcribe('./call.mp3');
} catch (error) {
  if (error instanceof Transcript1Error) {
    console.error(error.code, error.message, error.transcriptionId);
  }
}
```

| 字段 | 说明 |
|---|---|
| `message` | 说明错误原因的文本。 |
| `code` | 可能是API错误码、任务失败码、`canceled`，或SDK本地错误码。 |
| `status` | HTTP状态码。任务错误和本地错误不包含该字段。 |
| `details` | API附带的错误信息，例如`minutes_needed`、`action_url`；默认是空对象。 |
| `retryable` | 重试是否可能成功，默认false。 |
| `transcriptionId` | 已有任务id时返回该id。 |
| `transcription` | 已获取转录对象时，返回最近获取的对象。 |

SDK本地错误码有`missing_api_key`、`invalid_input`、`aborted`、`network_error`和`upload_token_refused`。服务端返回的错误不是JSON时，错误码为`http_<status>`。

任务失败但没有提供错误对象时，SDK使用`transcription_failed`。如果取回的任务已完成，却没有转录文本，`transcribe`的Promise会被reject（拒绝），错误码为`internal_error`。API错误码见[错误说明](https://transcript1.com/zh/docs/errors)，响应字段见[API参考](https://transcript1.com/zh/docs/api-reference)。

## 运行环境要求

需要Node 20.19+。Bun和Deno通过`node:`兼容层应当也能运行，但自动化测试仅覆盖Node。SDK只供服务端使用，不要把API密钥放进浏览器代码。
