# Menggunakan SDK Node.js

> Integrasikan transkripsi link dan file dengan @transcript1/sdk di server. Unduh teks atau subtitle, pantau proses, dan tangani error.

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

Pakai `@transcript1/sdk` di server TypeScript atau JavaScript untuk mengirim link, mengunggah file, dan mengambil transkrip. SDK juga menangani proses menunggu sampai transkripsi selesai.

Link media sosial memerlukan SDK 1.1.0 atau lebih baru. Versi 1.0.1 hanya menerima YouTube; link baru ditolak sebelum dikirim ke API. Untuk memperbarui SDK, jalankan `npm i @transcript1/sdk@latest`.

Versi minimum ini berlaku untuk enam platform awal. Untuk Twitch, Dailymotion, Pinterest, LinkedIn, dan Snapchat, pilih rilis SDK yang sudah mendukung platformnya. Rilis lama bisa menolak link sebelum request sampai ke API.

## Pasang paket

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

Semua contoh memakai ES modules. Simpan kode dalam file `.mjs`. Jika memakai `.js`, tambahkan `"type": "module"` di `package.json`. Di Node 20.19+, Anda juga bisa memakai `require()`, misalnya `require('@transcript1/sdk')`.

## Siapkan kunci API

Buat kunci melalui halaman [“API keys”](https://transcript1.com/dashboard/account/tokens). Simpan sebagai variabel environment server bernama `TRANSCRIPT1_API_KEY`, atau isi `apiKey` saat membuat instance:

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

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

Jika tidak ada kunci API, constructor melempar `Transcript1Error` berkode `missing_api_key`.

## Kirim rekaman dan tunggu transkripnya

Panggil `transcribe(input, options)` untuk membuat job sekaligus menunggu transkrip. Setelah berhasil, Anda mendapat `CompletedTranscription` dengan `status: 'completed'` dan field `transcript`. Jika job gagal atau dibatalkan, promise ditolak (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 });
```

Jika input berupa Buffer atau Uint8Array, sertakan nama file. SDK memakainya untuk mengenali jenis media:

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

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

SDK menganggap string berawalan `http://` atau `https://` sebagai link. String lain dianggap sebagai path file. Link yang didukung berasal dari YouTube, X, TikTok, Instagram, Facebook, Bluesky, Twitch, Dailymotion, Pinterest, LinkedIn, dan Snapchat. Platform tambahan wajib memakai HTTPS. Periksa [sumber dan pengaturan](https://transcript1.com/id/docs/sources-and-options) untuk jenis rekaman publik, dukungan subtitle, dan batasannya.

Untuk unggahan, ukuran file maksimal 2.000.000.000 byte. Ekstensi yang diterima adalah mp3, wav, m4a, flac, ogg, opus, mp4, mov, webm, dan mkv.

Postingan harus bisa diakses publik. Jika satu postingan berisi beberapa video, hanya video pertama yang ditranskripsi. API mengenali platform dari link. Format link pendek dan batas penggunaannya tercantum dalam [daftar sumber](https://transcript1.com/id/docs/sources-and-options).

Input juga bisa berupa Blob, `ReadableStream<Uint8Array>`, atau async iterable yang menghasilkan chunk Uint8Array. Sertakan `filename` untuk Blob, kecuali objeknya berupa File yang sudah memiliki nama. Untuk stream dan async iterable, sertakan `filename` sekaligus `size` dalam byte.

## Unduh teks atau subtitle

Gunakan `download(id, options)` untuk menunggu proses selesai lalu mengambil transkrip sebagai string. Jika memilih JSON, Anda menerima teks JSON dari API yang belum diparse menjadi objek.

```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' });
```

Opsi `timestamps: true` hanya berlaku untuk `text`. Jika dipakai dengan format lain, promise ditolak (reject) dengan `invalid_input`. Jika job gagal atau dibatalkan, promise dari `download` juga ditolak (reject).

## Jalankan transkripsi tanpa menunggu

Panggil `transcriptions.create` jika ingin mengambil transkrip belakangan. SDK mengembalikan objek job tanpa menunggu transkrip selesai. Untuk input file, SDK tetap menyelesaikan unggahannya sebelum mengembalikan objek tersebut.

```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 });
```

Panggilan `get` tanpa `wait` mengambil status saat ini. Tambahkan `wait: true` untuk menunggu sampai status menjadi `completed`, `failed`, atau `canceled`. Selalu periksa `finished.status` sebelum mengakses transkrip. Berbeda dari `transcribe`, promise dari `get` tetap selesai secara normal saat job gagal atau dibatalkan; promise tidak ditolak (reject) karena status tersebut.

## Kelola transkripsi dan periksa akun

```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);
```

Saat Anda melakukan iterasi, `list` mengambil halaman berikutnya sesuai kebutuhan. Saring dengan `status` atau `platform`: `youtube`, `x`, `tiktok`, `instagram`, `facebook`, `bluesky`, `twitch`, `dailymotion`, `pinterest`, `linkedin`, `snapchat`, atau `upload`. Atur jumlah item per halaman melalui `limit`, dari 1 sampai 100; nilai bawaan API adalah 20. Nama field pada objek tetap mengikuti `snake_case` API. Simpan `media_id` sebagai string utuh tanpa menafsirkan isinya.

Untuk job yang masih berjalan, `delete` membatalkan prosesnya. Untuk job yang sudah berakhir, fungsi ini menghapus job beserta transkrip. Panggil `account` untuk melihat paket, saldo menit, dan batas akun.

## Atur SDK dan setiap panggilan

Constructor menerima `apiKey`, `baseUrl`, `fetch`, dan `maxRetries`. Jika tidak diisi, `baseUrl` mengikuti `TRANSCRIPT1_API_URL` jika variabel itu tersedia; jika tidak, alamatnya `https://api.transcript1.com`. Anda bisa memasukkan implementasi `fetch` sendiri. Nilai bawaan `maxRetries` adalah 2, dengan rentang bilangan bulat 0 sampai 10.

Opsi berikut berlaku untuk `transcribe` dan `transcriptions.create`:

| Opsi | Kegunaan |
|---|---|
| `speakers` | Aktifkan pengenalan pembicara. |
| `language` | Biarkan `auto` sebagai bawaan, atau tentukan kode bahasa ISO 639-1. |
| `source` | Untuk link, pilih `auto` atau `stt`. YouTube, X, TikTok, Bluesky, Dailymotion, dan LinkedIn juga menerima `captions` jika ada track yang bisa dipakai. |
| `fresh` | Buat transkripsi link baru tanpa memakai kembali transkripsi dari 24 jam terakhir. |
| `filename` | Beri nama untuk Buffer, Blob tanpa nama, dan stream. Bisa juga dipakai untuk mengganti nama file. |
| `size` | Isi ukuran dalam byte; wajib untuk stream dan async iterable. |
| `idempotencyKey` | Jika tidak diisi, SDK membuat UUID baru untuk setiap panggilan. |
| `onProgress` | Pasang callback untuk menerima event progres. |
| `signal` | Berikan AbortSignal untuk membatalkan panggilan. |

Untuk `transcriptions.get`, opsi yang tersedia adalah `wait`, `includeWords`, `onProgress`, dan `signal`. Aktifkan `includeWords: true` untuk mengambil timestamp per kata. Callback `onProgress` memberi tahu perubahan selama proses menunggu.

Pada `download`, Anda bisa mengatur `format`, `timestamps`, dan `signal`. Opsi `signal` juga diterima oleh `list`. Untuk membatalkan `transcriptions.delete(id, options)` atau `account(options)`, teruskan `{ signal }` sebagai argumen opsi.

## Pantau proses unggahan dan transkripsi

Tambahkan callback `onProgress` pada `transcribe`, `transcriptions.create`, atau `transcriptions.get` yang sedang menunggu job:

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

| Event | Informasi yang diterima |
|---|---|
| `upload` | Jumlah byte yang sudah dikirim pada `sent` dan ukuran keseluruhan pada `total`. |
| `status` | Status job saat ini pada field `status`. |
| `waiting_slot` | Field `retryAfter` berisi waktu tunggu dalam detik sebelum mencoba mendapatkan slot job lagi. |
| `reconnecting` | Tidak ada field tambahan. Event muncul sekali untuk setiap gangguan koneksi selama menunggu. |

## Batalkan panggilan SDK

Teruskan `AbortSignal` dari AbortController jika ingin mengendalikan pembatalan. Untuk membatasi waktu panggilan, gunakan `AbortSignal.timeout`:

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

Jika dibatalkan sebelum request pertama, promise ditolak (reject) dengan `aborted` tanpa ID job. Jika dibatalkan saat unggahan berlangsung, SDK mencoba menghapus job yang masih `awaiting_upload`. Setelah itu, promise ditolak (reject) dengan `aborted` beserta ID job.

Membatalkan proses menunggu tidak menghentikan job di server. Ambil `transcriptionId` dari error untuk melanjutkan lewat `transcriptions.get(id, { wait: true })`. Jika ingin menghentikan jobnya juga, panggil `transcriptions.delete(id)`.

Selama menunggu job, SDK terus mencoba lagi jika terjadi error jaringan atau respons HTTP 429, 500, 502, 503, dan 504. Tidak ada batas jumlah percobaan untuk proses menunggu ini. Jeda koneksi ulang bertambah dari 2 menjadi 4, 8, 16, lalu 30 detik. Request lain mengikuti `maxRetries`. Saat semua slot transkripsi aktif terpakai, proses pembuatan job juga menunggu dan mencoba lagi. Pakai `signal` untuk membatasi waktu keseluruhan.

## Tangani error SDK, API, dan transkripsi

Tangkap `Transcript1Error` agar aplikasi bisa membaca kode error dari API, job, maupun SDK:

```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);
  }
}
```

| Field | Keterangan |
|---|---|
| `message` | Penjelasan tentang error yang terjadi. |
| `code` | Kode error API, kegagalan job, `canceled`, atau error lokal SDK. |
| `status` | Kode HTTP. Field ini tidak ada pada error job atau error lokal. |
| `details` | Informasi tambahan dari API, seperti `minutes_needed` atau `action_url`. Jika tidak ada, nilainya objek kosong. |
| `retryable` | Menunjukkan apakah mencoba lagi mungkin membantu. Nilai bawaannya false. |
| `transcriptionId` | ID job jika sudah tersedia. |
| `transcription` | Objek transkripsi terakhir yang tersedia. |

Error lokal SDK memakai kode `missing_api_key`, `invalid_input`, `aborted`, `network_error`, atau `upload_token_refused`. Jika respons error bukan JSON, kodenya mengikuti format `http_<status>`.

Jika job gagal tanpa objek error, SDK memakai `transcription_failed`. Jika job berstatus selesai tetapi transkrip tetap tidak ada setelah diambil, promise dari `transcribe` ditolak (reject) dengan `internal_error`. Periksa [panduan error](https://transcript1.com/id/docs/errors) untuk kode API dan [referensi API](https://transcript1.com/id/docs/api-reference) untuk rincian field respons.

## Lingkungan yang didukung

Gunakan Node 20.19+. Bun dan Deno seharusnya bisa menjalankan SDK melalui kompatibilitas `node:`, tetapi pengujian otomatis hanya dilakukan di Node. SDK hanya untuk server. Jangan sertakan kunci API dalam kode yang dikirim ke browser.
