REST-API|Video-Untertitel-API

Untertitle jedes Video
mit drei API-Aufrufen

Schick eine Video-URL, bekomm ein mp4 mit wortgenau eingebrannten Untertiteln zurück. Whisper timet jedes Wort, ein KI-Durchlauf wählt die Betonungen, und gerendert wird auf unserer Worker-Flotte.

POSThttps://autostud.ai/api/v1/actions/subtitles.generate
Schnellstart

Der ganze Ablauf, in einer Datei

Einfügen, Key setzen, ausführen. Nichts davon ist Pseudocode.

const API = 'https://autostud.ai/api/v1'
const KEY = process.env.AUTOSTUD_API_KEY

const call = async (path, body) => {
  const response = await fetch(API + path, {
    method: body ? 'POST' : 'GET',
    headers: {
      Authorization: `Bearer ${KEY}`,
      'Content-Type': 'application/json',
    },
    body: body ? JSON.stringify(body) : undefined,
  })

  const payload = await response.json()
  if (!response.ok) throw new Error(payload.error?.message || response.statusText)
  return payload
}

// 1. A video project to hang the timeline on.
const created = await call('/actions/videos.create', {
  video_name: 'Interview clip',
  video_type_id: 'timeline',
  video_format: 'portrait',
  video_lang: 'en',
})
const video_id = created.data.video_id

// 2. Transcribe, emphasise, style — one call.
const subtitled = await call('/actions/subtitles.generate', {
  video_id,
  media_url: 'https://cdn.example.com/interview.mp4',
  style_preset: 'beast',
  words_per_group: 3,
})
console.log(subtitled.data.word_count, 'words', subtitled.data.duration_seconds, 's')

// 3. Render it.
await call('/actions/renders.create', {
  video_id,
  video_type_id: 'timeline',
  video_format: 'portrait',
})

// 4. Wait for the worker. A webhook is better; this is the short version.
let render
do {
  await new Promise((resolve) => setTimeout(resolve, 15000))
  const list = await call(`/renders?video_id=${video_id}&limit=1`)
  render = list.data[0]
} while (render && ['not_started', 'processing'].includes(render.render_status))

if (render.render_status !== 'done') throw new Error('Render failed')
console.log(render.render_url)

Basis-URL: https://autostud.ai/api/v1 — Authentifizierung über `Authorization: Bearer sk_live_…`. Ein `sk_test_`-Key läuft denselben Pfad und stoppt, bevor etwas ausgegeben wird.

Schritt für Schritt

Was du wirklich tun musst

Sechs Schritte, vier davon je ein Request.

  1. 1

    API-Key anlegen

    Dashboard, Einstellungen, API-Keys. Nimm das Preset "Automation", wenn du die Scopes nicht selbst wählen willst: es deckt Videos, Renders und Dateien ab. Das Secret wird einmal angezeigt. `sk_live_` gibt aus, `sk_test_` validiert den ganzen Request und stoppt vor dem Schreiben.

    export AUTOSTUD_API_KEY="sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    
    # What can this key actually do?
    curl https://autostud.ai/api/v1 \
      -H "Authorization: Bearer $AUTOSTUD_API_KEY"
  2. 2

    Video hinter eine URL legen

    Es gibt keinen Upload-Endpoint: die API liest eine URL. Dein Bucket, dein CDN, ein signierter Link — alles, was unsere Server abrufen können. Der Eintrag in der Workspace-Bibliothek ist optional und ändert am Ablauf nichts.

    # The API takes a URL, never a file upload. Anything publicly
    # reachable works: your bucket, your CDN, a signed URL.
    export MEDIA_URL="https://cdn.example.com/interview.mp4"
    
    # Optional: keep a record of it in the workspace library.
    curl -X POST https://autostud.ai/api/v1/assets \
      -H "Authorization: Bearer $AUTOSTUD_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "provider_file_url": "'"$MEDIA_URL"'",
        "provider_file_name": "interview.mp4",
        "file_mime_type": "video/mp4",
        "provider_file_id": "interview-2026-08-18",
        "sync_method": "api"
      }'
  3. 3

    Video-Projekt erstellen

    `videos.create` liefert die `video_id`, an der alles Weitere hängt. Schick einen `Idempotency-Key`, dann gibt ein wiederholter Request die erste Antwort zurück statt ein zweites Projekt anzulegen.

    curl -X POST https://autostud.ai/api/v1/actions/videos.create \
      -H "Authorization: Bearer $AUTOSTUD_API_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: interview-2026-08-18" \
      -d '{
        "video_name": "Interview clip",
        "video_type_id": "timeline",
        "video_format": "portrait",
        "video_lang": "en"
      }'
  4. 4

    Untertitel erzeugen

    `subtitles.generate` erledigt alles serverseitig: Whisper transkribiert wortgenau, ein KI-Durchlauf markiert die zu betonenden Wörter, und einer von 116 Stilen wird angewendet. Zurück kommen Wortanzahl, exakte Dauer und erkannte Sprache.

    export VIDEO_ID="9f0c4e2a-1d6b-4a77-9d51-6b0f2e8c3a4d"
    
    curl -X POST https://autostud.ai/api/v1/actions/subtitles.generate \
      -H "Authorization: Bearer $AUTOSTUD_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "video_id": "'"$VIDEO_ID"'",
        "media_url": "'"$MEDIA_URL"'",
        "style_preset": "beast",
        "words_per_group": 3,
        "enable_emphasis": true,
        "enable_diarization": false
      }'
  5. 5

    Render starten

    `renders.create` legt den Job auf die Worker-Flotte und antwortet sofort mit der `render_id`. Ein Render kostet 20 Credits, unabhängig von der Länge.

    curl -X POST https://autostud.ai/api/v1/actions/renders.create \
      -H "Authorization: Bearer $AUTOSTUD_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "video_id": "'"$VIDEO_ID"'",
        "video_type_id": "timeline",
        "video_format": "portrait"
      }'
  6. 6

    mp4 abholen

    Abonniere `render.completed`, dann wird dir die fertige URL signiert zugestellt. Wer lieber zieht, listet die Renders des Videos und liest `render_status`, bis dort `done` steht.

    # Register once, then stop polling.
    curl -X POST https://autostud.ai/api/v1/webhooks \
      -H "Authorization: Bearer $AUTOSTUD_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "url": "https://your-app.com/hooks/autostud",
        "events": ["render.completed", "render.failed"],
        "description": "Subtitled videos"
      }'
    # The signing secret comes back once, in this response. Store it.
Referenz

Alle Aufrufe dieser Seite

Scopes sind das, was der Key tragen muss, nicht was du sendest.

AufrufScopeWas er tut
GET /api/v1-Discovery: was dieser Key darf, seine Limits und sein Verbrauch.
POST /api/v1/actions/videos.createvideos:writeLegt das Video-Projekt an und gibt seine id zurück.
POST /api/v1/actions/subtitles.generatevideos:executeTranskribiert, betont, stylt und speichert die Untertitelspur.
POST /api/v1/actions/renders.createrenders:executeStellt den Render auf die Worker-Flotte. 20 Credits.
GET /api/v1/renders?video_id=…renders:readDie Render-Jobs eines Videos, neueste zuerst, mit Status und URL.
POST /api/v1/webhookswebhooks:writeRegistriert einen https-Endpoint und gibt sein Signing-Secret zurück, einmalig.

Stil-Presets

Übergib eines als `style_preset`. Jedes setzt Schrift, Kontur, Akzentfarbe und Animation gemeinsam — mehr ist nicht zu konfigurieren.

makeitlookeasy
default4 Wörter · simple
makeitloud
bold3 Wörter · simple
thisoneword
impact3 Wörter · focus_on_one_word
huge
beast1 Wörter · focus_on_one_word
onewordatatime
karaoke5 Wörter · focus_on_one_word
itfillsasyousing
karaoke_fill5 Wörter · karaoke
lightsonthewords
neon4 Wörter · progressively_visible
nothingbehindthetextatall
minimal6 Wörter · simple
wordbywordtheyland
pop5 Wörter · progressively_visible
darktextonapill
pill5 Wörter · simple
twocalmlinesatthebottomoftheframe
cinematic9 Wörter · simple

Was du vor dem Bauen wissen solltest

  • Rate Limits gelten pro Key und stehen in den Headern: `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `Retry-After` bei einem 429.
  • `Idempotency-Key` auf jedem POST macht einen Retry 24 Stunden lang sicher; die erste Antwort wird unverändert wiederholt.
  • Ein `sk_test_`-Key durchläuft Authentifizierung, Scopes, Limits und Validierung und antwortet dann `simulated: true`, ohne zu schreiben oder auszugeben.
  • Fehler sind typisiert: `invalid_request`, `insufficient_credits`, `rate_limit_exceeded`, `upstream_error` — verzweige über den Code, nie über die Nachricht.

Wenn es schiefgeht

Jeder Fehler hat dieselbe Form: ein stabiler `code` zum Verzweigen, ein `hint`, der den korrigierenden Aufruf nennt, und eine `request_id` zum Zitieren. Das vollständige Vokabular steht unter /docs/api/errors.

CodeWas es bedeutet
401 missing_credentialsKein Schlüssel im Request, oder ein unbekannter.
403 insufficient_scopeDem Schlüssel fehlt ein Scope; `details.required_scopes` nennt ihn.
422 validation_failedEin Feld ist ungültig; `details.issues` listet jedes einzelne auf.
402 insufficient_creditsZu wenig Credits für den Render. Aufladen, oder einen Test-Key nehmen.
429 rate_limit_exceededZu viele Aufrufe. `Retry-After` Sekunden warten, dann erneut.
502 upstream_errorEin Anbieter, von dem wir abhängen, ist ausgefallen. Mit Backoff wiederholen.
{
  "error": {
    "type": "permission_error",
    "code": "insufficient_scope",
    "message": "This API key is missing the required scope: videos:execute.",
    "details": {
      "required_scopes": ["videos:execute"],
      "granted_scopes": ["videos:read", "videos:write"]
    },
    "hint": "`details.required_scopes` lists what is missing. Call GET /api/v1 to see what this key does hold, then re-scope it at /app/settings/api-keys.",
    "retryable": false,
    "request_id": "req_8f2c41d0a95b",
    "doc_url": "https://autostud.ai/docs/api/errors#insufficient_scope"
  }
}

Fehlercodes

Webhooks

Hör auf zu pollen

Ein Render dauert Minuten. Lass ihn zu dir kommen.

Signiert, in zehn Zeilen prüfbar

`X-Autostud-Signature: t=<unix>,v1=<hex>` ist ein HMAC-SHA256 über `"<timestamp>.<roher Body>"`. Prüfe gegen den rohen Body, bevor du ihn parst.

Wiederholt, ohne dein Zutun

Fünf Versuche über rund zwei Stunden, die Delivery-Zeile wird vor dem ersten geschrieben. Ein Endpoint, der zwanzigmal in Folge scheitert, wird deaktiviert statt geflutet.

Dedupliziere über die Delivery-Id

Jeder Versuch trägt `X-Autostud-Delivery`. Gleiche Id heißt gleiches Event: behandle sie als Primärschlüssel der Arbeit, die du auslöst.

import crypto from 'node:crypto'

// The header is "t=<unix>,v1=<hex>" and the signed string is "<t>.<raw body>".
// Raw body: parse it AFTER verifying, never re-serialize before.
export function verify(raw_body, header, secret, tolerance = 300) {
  const parts = Object.fromEntries(
    String(header || '').split(',').map((entry) => entry.split('=').map((s) => s.trim()))
  )

  const timestamp = Number(parts.t)
  if (!Number.isFinite(timestamp)) return false
  if (Math.abs(Date.now() / 1000 - timestamp) > tolerance) return false

  const expected = crypto
    .createHmac('sha256', secret)
    .update(`${timestamp}.${raw_body}`)
    .digest('hex')

  const received = String(parts.v1 || '')
  if (received.length !== expected.length) return false

  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(received))
}

app.post('/hooks/autostud', express.raw({ type: '*/*' }), (req, res) => {
  const raw = req.body.toString('utf8')

  if (!verify(raw, req.get('X-Autostud-Signature'), process.env.AUTOSTUD_WEBHOOK_SECRET)) {
    return res.status(400).send('bad signature')
  }

  // Deliveries can repeat: deduplicate on this id before doing any work.
  const delivery_id = req.get('X-Autostud-Delivery')
  const event = JSON.parse(raw)

  if (event.event === 'render.completed') {
    console.log(event.data.render_url)
  }

  res.status(200).send('ok')
})
Was du bekommst

Warum das ein Aufruf ist und nicht fünfzehn

Die Teile, die schwer nachzubauen sind, betreiben wir.

Wortgenaues Timing

Jedes Wort trägt eigenen Start und Ende, das Highlight sitzt also auf der Silbe. Satzweises Timing ist der Grund, warum die meisten automatischen Untertitel zu spät wirken.

116 Stile, ein String

Von sauberen Broadcast-Untertiteln bis zum hüpfenden Highlight-Look. Das Preset setzt Schrift, Kontur, Farbe und Animation zusammen, skaliert auf deine Leinwand.

Die KI wählt die Akzente

Ein zweiter Durchlauf liest das Transkript und markiert die bedeutungstragenden Wörter. Füllwörter bleiben ruhig. Ein Boolean schaltet es ab.

Zwei Stimmen, zwei Farben

Diarisierung ist ein Flag. Ein Interview kommt mit je eigener Farbe pro Stimme zurück, damit man auch ohne Ton weiß, wer spricht.

Dieselben Objekte wie im Dashboard

Ein per API untertiteltes Video öffnet sich im Editor wie jedes andere. Wort von Hand korrigieren, neu rendern, weiter automatisieren — beide Wege schreiben dasselbe Dokument.

Auf Retries gebaut

Idempotency-Keys, typisierte Fehler, Test-Keys, signierte Webhooks und ein 30-Tage-Request-Log. Die langweilige Hälfte einer API — also die, die man um 3 Uhr nachts spürt.

FAQ

Die Fragen, die Entwickler uns wirklich schicken

Nein, und das ist Absicht: die API nimmt eine URL. Hoste das Video dort, wo unsere Server es lesen können — dein Bucket, ein CDN, ein signierter Link — und übergib es als `media_url`. Dateien aus dem Dashboard haben bereits eine nutzbare URL.

Heute nicht. Die Untertitel werden ins mp4 gerendert, was Kurzvideo-Plattformen brauchen. Die Wortliste mit ihren Zeiten liegt auf dem Video, eine Sidecar-Datei ist also eine Umwandlung, die du aus der API-Antwort selbst bauen kannst.

Ein Render kostet 20 Credits, fix, egal wie lang. Transkription und Betonungsdurchlauf werden wie jeder andere KI-Aufruf in deinem Workspace protokolliert, und `GET /api/v1/usage` zeigt, was ein Key in dieser Periode verbraucht hat.

Minuten, nicht Sekunden: er läuft auf einer Worker-Flotte, nicht im Request. Genau dafür gibt es `render.completed` — abonnieren statt eine Verbindung offenzuhalten.

Ja. Ruf `subtitles.generate` erneut mit `restyle_only: true` und einem anderen `style_preset` auf: die bereits gespeicherten Wörter werden wiederverwendet, nichts wird zweimal transkribiert.

Whisper erkennt die Sprache selbst, und die Untertitel kommen in der gesprochenen Sprache zurück — nichts zu deklarieren. Die erkannte Sprache steht in der Antwort, falls du darauf verzweigen willst.

Untertitelte Videos aus deinem eigenen Backend ausliefern

Key anlegen, Quickstart ausführen — das erste untertitelte mp4 ist Minuten entfernt.

Sichere Zahlungen
Sofortiger Zugang
Jederzeit kündbar