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.generateLim 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.
Seks steg, fire av dem ett kall hver.
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"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"
}'`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"
}'`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
}'`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"
}'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.Scopes er det nøkkelen må bære, ikke det du sender.
| Kall | Scope | Hva det gjør |
|---|---|---|
| GET /api/v1 | - | Discovery: hva nøkkelen kan gjøre, grensene og forbruket. |
| POST /api/v1/actions/videos.create | videos:write | Oppretter videoprosjektet og returnerer id-en. |
| POST /api/v1/actions/subtitles.generate | videos:execute | Transkriberer, fremhever, styler og lagrer undertekstsporet. |
| POST /api/v1/actions/renders.create | renders:execute | Køer rendringen på workerflåten. 20 credits. |
| GET /api/v1/renders?video_id=… | renders:read | En videos rendringer, nyeste først, med status og URL. |
| POST /api/v1/webhooks | webhooks:write | Registrerer et https-endepunkt og returnerer signeringsnøkkelen, én gang. |
Send ett som `style_preset`. Hvert forvalg setter skrift, kontur, aksentfarge og animasjon samtidig — det er ikke mer å konfigurere.
default4 ord · simplebold3 ord · simpleimpact3 ord · focus_on_one_wordbeast1 ord · focus_on_one_wordkaraoke5 ord · focus_on_one_wordkaraoke_fill5 ord · karaokeneon4 ord · progressively_visibleminimal6 ord · simplepop5 ord · progressively_visiblepill5 ord · simplecinematic9 ord · simpleAlle 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.
| Kode | Hva det betyr |
|---|---|
| 401 missing_credentials | Ingen nøkkel på kallet, eller en vi ikke kjenner igjen. |
| 403 insufficient_scope | Nøkkelen mangler et scope; `details.required_scopes` navngir det. |
| 422 validation_failed | Et felt er feil; `details.issues` lister hvert eneste ett. |
| 402 insufficient_credits | For lite kreditter til renderen. Fyll på, eller bruk en testnøkkel. |
| 429 rate_limit_exceeded | For mange kall. Vent `Retry-After` sekunder, så prøv igjen. |
| 502 upstream_error | En 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"
}
}En rendring tar minutter. La den komme til deg.
`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.
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.
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')
})Delene som er vanskelige å bygge selv, er de vi drifter.
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.
Fra rene broadcast-undertekster til den hoppende, fremhevede looken. Forvalget setter skrift, kontur, farge og animasjon sammen, skalert til lerretet ditt.
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.
Diarisering er et flagg. Et intervju kommer tilbake med hver stemme i sin egen farge, så seeren vet hvem som snakker uten lyd.
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.
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.
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.
Alle kjører i nettleseren, og du trenger ingen konto for å prøve.
Gjør ethvert tema om til en quizvideo
Quizvideoer i 16:9 eller som Shorts
Gjør en ordliste om til en språkvideo
Gjør tweets og X-innlegg om til videoer
Gjør hvilken som helst låt om til en karaokevideo
Gjør en Reddit-tråd om til en short
Gjør et regneark om til en rangeringsvideo
Gjør et TikTok-kommentarfelt om til en sangvideo
Lag virale fruktquizvideoer med AI
Lag en nøkkel, kjør hurtigstarten, og den første tekstede mp4-en er minutter unna.