# Transkription mit dem Node.js-SDK

> Binde @transcript1/sdk in deinen Server ein. Transkribiere Links und Dateien, lade Text oder Untertitel herunter und reagiere auf Fortschritt und Fehler.

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

Mit `@transcript1/sdk` transkribierst du Links und Dateien in deinem TypeScript- oder JavaScript-Backend. Das SDK übernimmt den Upload und wartet bei Bedarf auf das fertige Transkript.

Für Links aus Social Media brauchst du mindestens SDK 1.1.0. Version 1.0.1 nimmt nur YouTube-Links an und lehnt die anderen Links bereits lokal ab. Mit `npm i @transcript1/sdk@latest` aktualisierst du das Paket.

Diese Mindestversion gilt für die ursprünglichen sechs Plattformen. Für Twitch, Dailymotion, Pinterest, LinkedIn und Snapchat brauchst du eine SDK-Version, die die jeweilige Plattform unterstützt. Ältere Clients können diese Links abweisen, bevor sie die API erreichen.

## Installation

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

Die Beispiele verwenden ES-Module. Speichere den Code in `.mjs`-Dateien. Für `.js`-Dateien setzt du in `package.json` den Eintrag `"type": "module"`. Ab Node 20.19+ kannst du das Paket auch mit `require()` laden, etwa mit `require('@transcript1/sdk')`.

## API-Schlüssel

Erstelle im Dashboard unter [„API keys“](https://transcript1.com/dashboard/account/tokens) einen Schlüssel. Hinterlege ihn auf deinem Server als Umgebungsvariable `TRANSCRIPT1_API_KEY` oder übergib ihn dem Konstruktor als `apiKey`:

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

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

Fehlt der Schlüssel, wirft der Konstruktor einen `Transcript1Error` mit dem Code `missing_api_key`.

## Ein Transkript erstellen

Rufe `transcribe(input, options)` auf, um einen Job zu starten und auf das Transkript zu warten. Du bekommst eine `CompletedTranscription` mit `status: 'completed'` und dem Transkript im Feld `transcript`. Wenn der Job fehlschlägt oder abgebrochen wird, schlägt auch der Aufruf fehl.

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

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

Übergib bei einem Buffer oder Uint8Array auch den Dateinamen. Daran erkennt das SDK den Medientyp:

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

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

Ein String mit `http://` oder `https://` am Anfang gilt als Link. Andere Strings behandelt das SDK als Dateipfad. Unterstützt werden Uploads sowie Links von YouTube, X, TikTok, Instagram, Facebook, Bluesky, Twitch, Dailymotion, Pinterest, LinkedIn und Snapchat. Welche öffentlichen Aufnahmen und Untertitel du nutzen kannst, steht unter [Quellen und Einstellungen](https://transcript1.com/de/docs/sources-and-options). Die zusätzlich unterstützten Plattformen setzen HTTPS voraus. Dateien dürfen bis zu 2.000.000.000 Bytes groß sein. Erlaubte Endungen sind mp3, wav, m4a, flac, ogg, opus, mp4, mov, webm und mkv.

Die API erkennt am Link, von welcher Plattform das Video stammt. Posts aus Social Media müssen öffentlich sein. Enthält ein Post mehrere Videos, transkribiert transcript1 nur das erste. Erlaubte Kurzlinks und weitere Grenzen findest du unter [Quellen und Einstellungen](https://transcript1.com/de/docs/sources-and-options).

Du kannst auch einen Blob, einen `ReadableStream<Uint8Array>` oder ein asynchrones Iterable mit Uint8Array-Chunks übergeben. Gib für einen Blob `filename` an. Nur bei einem File-Objekt mit eigenem Namen entfällt das. Für Streams und asynchrone Iterables brauchst du `filename` und die Dateigröße `size` in Bytes.

## Text und Untertitel herunterladen

Mit `download(id, options)` lädst du das Transkript herunter. Der Aufruf wartet, bis es fertig ist, und gibt einen String zurück. Auch bei JSON bekommst du den unverarbeiteten JSON-Text der API, kein geparstes Objekt.

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

Die Option `timestamps: true` lässt sich nur mit `text` verwenden. Bei anderen Formaten schlägt der Aufruf mit `invalid_input` fehl. Auch wenn ein Job fehlschlägt oder abgebrochen wird, meldet `download` einen Fehler.

## Jobs im Hintergrund starten

Nutze `transcriptions.create`, wenn du nicht auf das Transkript warten willst. Bei Dateien wartet der Aufruf nur, bis der Upload abgeschlossen ist.

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

Ohne `wait` liefert `get` den aktuellen Stand. Mit `wait: true` wartet der Aufruf auf einen der Statuswerte `completed`, `failed` oder `canceled`. Prüfe deshalb `finished.status`, bevor du auf das Transkript zugreifst. Anders als `transcribe` gibt `get` auch einen fehlgeschlagenen oder abgebrochenen Job regulär zurück.

## Jobs verwalten und Kontodaten abfragen

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

Beim Iterieren lädt `list` die nächsten Seiten nach. Du kannst nach `status` oder `platform` filtern. Für die Plattform stehen `youtube`, `x`, `tiktok`, `instagram`, `facebook`, `bluesky`, `twitch`, `dailymotion`, `pinterest`, `linkedin`, `snapchat` und `upload` zur Auswahl. Mit `limit` setzt du die Seitengröße auf 1 bis 100 Einträge; die API verwendet standardmäßig 20. Feldnamen bleiben wie in der API in `snake_case`. Behandle `media_id` als String, dessen internen Aufbau du nicht auswertest.

Mit `delete` brichst du einen laufenden Job ab. Ist er bereits beendet, löschst du ihn samt Transkript. Über `account` fragst du Tarif, Minutenguthaben und Limits ab.

## Optionen

Beim Erstellen des Clients kannst du `apiKey`, `baseUrl`, `fetch` und `maxRetries` übergeben. Ohne eigene `baseUrl` nutzt das SDK die Variable `TRANSCRIPT1_API_URL`, falls sie gesetzt ist. Sonst verbindet es sich mit `https://api.transcript1.com`. Über `fetch` bindest du eine eigene Implementierung ein. `maxRetries` steht standardmäßig auf 2; erlaubt sind ganze Zahlen von 0 bis 10.

Für `transcribe` und `transcriptions.create` stehen dieselben Optionen bereit:

| Option | Bedeutung |
|---|---|
| `speakers` | Aktiviert die Sprecherzuordnung. |
| `language` | `auto` (Standard) oder ein ISO-639-1-Sprachcode. |
| `source` | Bei Links `auto` oder `stt`. Für verwendbare Untertitel auf YouTube, X, TikTok, Bluesky, Dailymotion und LinkedIn gibt es auch `captions`. |
| `fresh` | Erstellt für einen Link einen neuen Job, statt eine Transkription aus den letzten 24 Stunden zu verwenden. |
| `filename` | Dateiname für Buffer, Blobs ohne Namen und Streams. Bei diesen Eingaben ist er Pflicht. Du kannst damit auch einen vorhandenen Dateinamen ersetzen. |
| `size` | Dateigröße in Bytes. Pflicht für Streams und asynchrone Iterables. |
| `idempotencyKey` | Das SDK erzeugt ohne diese Angabe für jeden Aufruf eine neue UUID. |
| `onProgress` | Callback für Fortschrittsmeldungen. |
| `signal` | AbortSignal zum Abbrechen des Aufrufs. |

Bei `transcriptions.get` kannst du `wait`, `includeWords`, `onProgress` und `signal` übergeben. Mit `includeWords: true` erhältst du Wort-Zeitstempel. Während du auf den Job wartest, meldet `onProgress` Änderungen.

Für `download` gibt es `format`, `timestamps` und `signal`. Auch `list` unterstützt `signal`. Bei `transcriptions.delete(id, options)` und `account(options)` übergibst du das Signal im Optionsobjekt als `{ signal }`.

## Fortschritt verfolgen

Mit `onProgress` verfolgst du Upload und Verarbeitung. Übergib den Callback an `transcribe`, `transcriptions.create` oder an `transcriptions.get`, wenn der Aufruf auf den Job wartet:

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

| Event | Felder |
|---|---|
| `upload` | Übertragene Bytes in `sent`, Gesamtgröße in `total`. |
| `status` | Aktueller Jobstatus in `status`. |
| `waiting_slot` | `retryAfter` gibt an, wie viele Sekunden das SDK bis zum nächsten Versuch auf einen freien Job-Slot wartet. |
| `reconnecting` | Keine zusätzlichen Felder. Tritt während des Wartens einmal pro Verbindungsausfall auf. |

## Aufruf abbrechen

Zum Abbrechen übergibst du ein `AbortSignal` aus einem AbortController. Mit `AbortSignal.timeout` setzt du stattdessen ein Zeitlimit:

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

Brichst du vor dem ersten Request ab, bekommst du den Fehler `aborted` ohne Job-ID. Läuft der Upload bereits, versucht das SDK den Job zu löschen, sofern er noch den Status `awaiting_upload` hat. Danach meldet es `aborted` mit der Job-ID.

Wenn du nur das Warten abbrichst, läuft der Job weiter. Nimm die `transcriptionId` aus dem Fehler und warte mit `transcriptions.get(id, { wait: true })` erneut darauf. Den Job selbst brichst du mit `transcriptions.delete(id)` ab.

Während das SDK auf einen Job wartet, versucht es bei Netzwerkfehlern und den HTTP-Statuscodes 429, 500, 502, 503 und 504 unbegrenzt weiter. Zwischen den Verbindungsversuchen wartet es zunächst 2, dann 4, 8, 16 und schließlich 30 Sekunden. Für andere Requests gilt `maxRetries`. Sind beim Erstellen eines Jobs alle Plätze belegt, wartet das SDK ebenfalls und versucht es erneut. Mit `signal` begrenzt du die gesamte Wartezeit.

## Fehler

Fange einen `Transcript1Error` ab, um Fehler der API, der Transkription oder des SDKs auszuwerten:

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

| Feld | Bedeutung |
|---|---|
| `message` | Beschreibt den Fehler. |
| `code` | Fehlercode der API oder des Jobs, `canceled` oder ein lokaler SDK-Fehlercode. |
| `status` | HTTP-Statuscode. Fehlt bei Jobfehlern und lokalen Fehlern. |
| `details` | Weitere Angaben der API, etwa `minutes_needed` oder `action_url`. Ohne solche Angaben ein leeres Objekt. |
| `retryable` | Gibt an, ob ein neuer Versuch helfen kann. Standardmäßig false. |
| `transcriptionId` | ID des Jobs, sofern vorhanden. |
| `transcription` | Letztes bekanntes Transkriptionsobjekt, sofern vorhanden. |

Die lokalen Fehlercodes heißen `missing_api_key`, `invalid_input`, `aborted`, `network_error` und `upload_token_refused`. Ist die Fehlerantwort kein JSON, verwendet das SDK `http_<status>`.

Fehlt bei einem fehlgeschlagenen Job das Fehlerobjekt, meldet das SDK `transcription_failed`. Ist ein Job abgeschlossen, liefert aber auch nach dem Abruf kein Transkript, schlägt `transcribe` mit `internal_error` fehl. Alle API-Fehlercodes findest du unter [Fehler](https://transcript1.com/de/docs/errors), die Antwortfelder in der [API-Referenz](https://transcript1.com/de/docs/api-reference).

## Unterstützte Laufzeiten

Das SDK setzt Node 20.19+ voraus. Bun und Deno sollten dank ihrer `node:`-Kompatibilität ebenfalls funktionieren; automatisiert testen wir nur mit Node. Verwende das SDK ausschließlich auf dem Server. Ein API-Schlüssel gehört nie in den Browser.
