REST-API|API for Videoundertekster

Tekst hvilken som helst video
med tre API-kall

Send en video-URL og få tilbake en mp4 med undertekster brent inn ord for ord. Whisper timer hvert ord, en KI-gjennomgang velger hvilke som skal fremheves, og rendringen kjører på vår workerflåte.

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

Hele løpet, i én fil

Lim inn, sett nøkkelen din, kjør. Ingenting her er pseudokode.

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 — autentiser med `Authorization: Bearer sk_live_…`. En `sk_test_`-nøkkel går nøyaktig samme vei og stopper før noe brukes.

Steg for steg

Det du faktisk må gjøre

Seks steg, fire av dem ett kall hver.

  1. 1

    Lag en API-nøkkel

    Dashbord, Innstillinger, API-nøkler. Ta forhåndsvalget "Automation" hvis du ikke vil velge scopes for hånd: det dekker videoer, rendringer og filer. Hemmeligheten vises én gang. `sk_live_` bruker, `sk_test_` validerer hele kallet og stopper før skrivingen.

    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

    Legg videoen bak en URL

    Det finnes ingen opplastings-endepunkt: API-et leser en URL. Din bucket, din CDN, en signert lenke — alt serverne våre kan hente. Å registrere den i arbeidsområdets bibliotek er valgfritt og endrer ingenting.

    # 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

    Opprett videoprosjektet

    `videos.create` returnerer `video_id`-en alt annet henger på. Send en `Idempotency-Key`, så gir et gjentatt kall det første svaret i stedet for å lage et prosjekt til.

    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

    Tekst den

    `subtitles.generate` gjør hele jobben på serveren: Whisper transkriberer med ordnøyaktig timing, en KI-gjennomgang markerer ordene som skal fremheves, og en av 116 stiler legges på. Svaret inneholder antall ord, nøyaktig lengde og oppdaget språk.

    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

    Køa rendringen

    `renders.create` legger jobben på workerflåten og svarer umiddelbart med `render_id`. En rendring koster 20 credits, uansett lengde.

    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

    Hent mp4-en

    Abonner på `render.completed`, så sendes den ferdige URL-en signert til deg. Vil du heller hente selv: list videoens rendringer og les `render_status` til den sier `done`.

    # 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.
Referanse

Alle kall på denne siden

Scopes er det nøkkelen må bære, ikke det du sender.

KallScopeHva det gjør
GET /api/v1-Discovery: hva nøkkelen kan gjøre, grensene og forbruket.
POST /api/v1/actions/videos.createvideos:writeOppretter videoprosjektet og returnerer id-en.
POST /api/v1/actions/subtitles.generatevideos:executeTranskriberer, fremhever, styler og lagrer undertekstsporet.
POST /api/v1/actions/renders.createrenders:executeKøer rendringen på workerflåten. 20 credits.
GET /api/v1/renders?video_id=…renders:readEn videos rendringer, nyeste først, med status og URL.
POST /api/v1/webhookswebhooks:writeRegistrerer et https-endepunkt og returnerer signeringsnøkkelen, én gang.

Stilforvalg

Send ett som `style_preset`. Hvert forvalg setter skrift, kontur, aksentfarge og animasjon samtidig — det er ikke mer å konfigurere.

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

Verdt å vite før du bygger

  • Grensene gjelder per nøkkel og kommer i headere: `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `Retry-After` ved en 429.
  • `Idempotency-Key` på et hvilket som helst POST gjør et nytt forsøk trygt i 24 timer; første svar spilles av ordrett.
  • En `sk_test_`-nøkkel går gjennom autentisering, scopes, grenser og validering og svarer så `simulated: true` uten å skrive eller bruke noe.
  • Feil er typede: `invalid_request`, `insufficient_credits`, `rate_limit_exceeded`, `upstream_error` — forgren på koden, aldri på teksten.

Når det går galt

Alle feil har samme form: en stabil `code` å forgrene på, et `hint` som peker ut kallet som fikser det, og en `request_id` å vise til. Hele ordlista ligger på /docs/api/errors.

KodeHva det betyr
401 missing_credentialsIngen nøkkel på kallet, eller en vi ikke kjenner igjen.
403 insufficient_scopeNøkkelen mangler et scope; `details.required_scopes` navngir det.
422 validation_failedEt felt er feil; `details.issues` lister hvert eneste ett.
402 insufficient_creditsFor lite kreditter til renderen. Fyll på, eller bruk en testnøkkel.
429 rate_limit_exceededFor mange kall. Vent `Retry-After` sekunder, så prøv igjen.
502 upstream_errorEn leverandør vi er avhengige av feilet. Prøv igjen med backoff.
{
  "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"
  }
}

Feilkoder

Webhooks

Slutt å polle

En rendring tar minutter. La den komme til deg.

Signert, verifiserbart på ti linjer

`X-Autostud-Signature: t=<unix>,v1=<hex>` er en HMAC-SHA256 over `"<timestamp>.<rå body>"`. Verifiser mot den rå bodyen, før du parser den.

Prøvd på nytt for deg

Fem forsøk over rundt to timer, og leveringsraden skrives før det første. Et endepunkt som feiler tjue ganger på rad slås av i stedet for å bli hamret.

Dedupliser på leverings-id

Hvert forsøk bærer `X-Autostud-Delivery`. Samme id betyr samme hendelse: behandle den som primærnøkkel for arbeidet du starter.

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')
})
Det du får

Hvorfor dette er ett kall og ikke femten

Delene som er vanskelige å bygge selv, er de vi drifter.

Ordnøyaktig timing

Hvert ord bærer sin egen start og slutt, så fremhevingen lander på stavelsen. Setningsbasert timing er grunnen til at de fleste automatiske undertekster føles sene.

116 stiler, én streng

Fra rene broadcast-undertekster til den hoppende, fremhevede looken. Forvalget setter skrift, kontur, farge og animasjon sammen, skalert til lerretet ditt.

KI-en velger aksentene

En andre gjennomgang leser transkripsjonen og markerer ordene som bærer meningen. Fyllordene får være i fred. En boolean slår det av.

To stemmer, to farger

Diarisering er et flagg. Et intervju kommer tilbake med hver stemme i sin egen farge, så seeren vet hvem som snakker uten lyd.

De samme objektene som dashbordet

En video tekstet via API-et åpner i editoren som enhver annen. Rett et ord for hånd, render på nytt, fortsett å automatisere — begge veier skriver det samme dokumentet.

Bygd for nye forsøk

Idempotensnøkler, typede feil, testnøkler, signerte webhooks og en forespørselslogg på 30 dager. Den kjedelige halvdelen av et API, altså den man kjenner klokken tre om natten.

FAQ

Spørsmålene utviklere faktisk sender

Nei, og det er med vilje: API-et tar en URL. Legg videoen der serverne våre kan lese den — din egen bucket, en CDN, en signert lenke — og send den som `media_url`. Filer lastet opp via dashbordet har allerede en brukbar URL.

Ikke i dag. Undertekstene rendres inn i mp4-en, som er det kortformatplattformene trenger. Ordlisten med timingen ligger på videoen, så en egen fil er en omgjøring du kan gjøre selv ut fra det API-et returnerer.

En rendring er 20 credits, fast, uansett lengde. Transkripsjonen og aksentgjennomgangen logges i arbeidsområdet ditt som ethvert annet KI-kall, og `GET /api/v1/usage` viser hva en nøkkel har brukt i perioden.

Minutter, ikke sekunder: den kjører på en workerflåte, ikke inne i forespørselen. Nettopp derfor finnes `render.completed` — abonner i stedet for å holde en tilkobling åpen.

Ja. Kall `subtitles.generate` på nytt med `restyle_only: true` og et annet `style_preset`: ordene som allerede ligger på videoen gjenbrukes, så ingenting transkriberes to ganger.

Whisper oppdager språket selv, og undertekstene kommer på det som faktisk snakkes — ingenting å oppgi. Det oppdagede språket ligger i svaret hvis du vil forgrene på det.

Lever tekstet video fra din egen backend

Lag en nøkkel, kjør hurtigstarten, og den første tekstede mp4-en er minutter unna.

Trygge betalinger
Tilgang med én gang
Avslutt når du vil