Skicka en video-URL och få tillbaka en mp4 med undertexter inbrända ord för ord. Whisper tajmar varje ord, en AI-genomgång väljer vilka som ska framhävas, och renderingen kör på vår workerflotta.
POSThttps://autostud.ai/api/v1/actions/subtitles.generateKlistra in, sätt din nyckel, kör. Inget här är pseudokod.
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)Bas-URL: https://autostud.ai/api/v1 — autentisera med `Authorization: Bearer sk_live_…`. En `sk_test_`-nyckel går exakt samma väg och stannar innan något förbrukas.
Sex steg, fyra av dem ett anrop var.
Dashboard, Inställningar, API-nycklar. Ta förinställningen "Automation" om du inte vill välja scopes för hand: den täcker videor, renderingar och filer. Hemligheten visas en gång. `sk_live_` förbrukar, `sk_test_` validerar hela anropet och stannar före skrivningen.
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 finns ingen uppladdningsendpoint: API:et läser en URL. Din bucket, ditt CDN, en signerad länk — allt våra servrar kan hämta. Att registrera den i arbetsytans bibliotek är valfritt och ändrar inget i flödet.
# 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` returnerar det `video_id` som allt annat hänger på. Skicka en `Idempotency-Key` så ger ett omtaget anrop första svaret i stället för att skapa ett andra projekt.
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` gör hela jobbet på servern: Whisper transkriberar med ordexakt tajming, en AI-genomgång markerar orden som ska framhävas, och en av 116 stilar appliceras. Svaret innehåller antal ord, exakt längd och identifierat 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` lägger jobbet på workerflottan och svarar direkt med `render_id`. En rendering kostar 20 credits, oavsett längd.
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"
}'Prenumerera på `render.completed` så skickas den färdiga URL:en signerad till dig. Vill du hellre hämta själv: lista videons renderingar och läs `render_status` tills den säger `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 är vad nyckeln måste bära, inte vad du skickar.
| Anrop | Scope | Vad det gör |
|---|---|---|
| GET /api/v1 | - | Discovery: vad nyckeln får göra, dess gränser och förbrukning. |
| POST /api/v1/actions/videos.create | videos:write | Skapar videoprojektet och returnerar dess id. |
| POST /api/v1/actions/subtitles.generate | videos:execute | Transkriberar, framhäver, stilsätter och sparar undertextspåret. |
| POST /api/v1/actions/renders.create | renders:execute | Köar renderingen på workerflottan. 20 credits. |
| GET /api/v1/renders?video_id=… | renders:read | En videos renderingar, nyaste först, med status och URL. |
| POST /api/v1/webhooks | webhooks:write | Registrerar en https-endpoint och returnerar dess signeringsnyckel, en gång. |
Skicka ett som `style_preset`. Varje förval sätter typsnitt, kontur, accentfärg och animation på en gång — det finns inget mer att konfigurera.
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 · simpleAlla fel har samma form: en stabil `code` att grena på, en `hint` som pekar ut anropet som löser det, och ett `request_id` att hänvisa till. Hela ordlistan finns på /docs/api/errors.
| Kod | Vad det betyder |
|---|---|
| 401 missing_credentials | Ingen nyckel i anropet, eller en vi inte känner igen. |
| 403 insufficient_scope | Nyckeln saknar en scope; `details.required_scopes` namnger den. |
| 422 validation_failed | Ett fält är fel; `details.issues` listar vartenda ett. |
| 402 insufficient_credits | För lite krediter för renderingen. Fyll på, eller kör en testnyckel. |
| 429 rate_limit_exceeded | För många anrop. Vänta `Retry-After` sekunder och försök igen. |
| 502 upstream_error | En leverantör vi hänger på fallerade. Försök igen 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 rendering tar minuter. Låt den komma till dig.
`X-Autostud-Signature: t=<unix>,v1=<hex>` är en HMAC-SHA256 över `"<timestamp>.<rå body>"`. Verifiera mot den råa bodyn, innan du parsar den.
Fem försök över ungefär två timmar, och leveransraden skrivs före det första. En endpoint som fallerar tjugo gånger i rad stängs av i stället för att bombarderas.
Varje försök bär `X-Autostud-Delivery`. Samma id betyder samma händelse: behandla det som primärnyckeln för arbetet du startar.
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')
})Delarna som är svåra att bygga om är de vi driver.
Varje ord bär sin egen start och slut, så markeringen landar på stavelsen. Meningsbaserad tajming är varför de flesta automatiska undertexter känns sena.
Från rena broadcast-undertexter till den studsande markerade looken. Förvalet sätter typsnitt, kontur, färg och animation ihop, skalat till din canvas.
En andra genomgång läser transkriptet och markerar orden som bär betydelsen. Utfyllnadsorden får vara i fred. En boolean stänger av det.
Diarisering är en flagga. En intervju kommer tillbaka med varje röst i sin egen färg, så tittaren vet vem som pratar utan ljud.
En video som textats via API:et öppnas i editorn som vilken annan som helst. Rätta ett ord för hand, rendera om, fortsätt automatisera — båda vägarna skriver samma dokument.
Idempotensnycklar, typade fel, testnycklar, signerade webhooks och en förfrågningslogg på 30 dagar. Den tråkiga halvan av ett API, alltså den man känner klockan tre på natten.
Nej, och det är avsiktligt: API:et tar en URL. Lägg videon där våra servrar kan läsa den — din egen bucket, ett CDN, en signerad länk — och skicka den som `media_url`. Filer du laddat upp via dashboarden har redan en användbar URL.
Inte idag. Undertexterna renderas in i mp4:an, vilket är vad kortformatsplattformarna behöver. Ordlistan med tajming ligger kvar på videon, så en separat fil är en omvandling du kan göra själv utifrån det API:et returnerar.
En rendering är 20 credits, fast pris oavsett längd. Transkriberingen och accentgenomgången loggas i din arbetsyta som varje annat AI-anrop, och `GET /api/v1/usage` visar vad en nyckel förbrukat under perioden.
Minuter, inte sekunder: den kör på en workerflotta, inte inne i anropet. Det är precis därför `render.completed` finns — prenumerera i stället för att hålla en uppkoppling öppen.
Ja. Anropa `subtitles.generate` igen med `restyle_only: true` och ett annat `style_preset`: orden som redan ligger på videon återanvänds, så inget transkriberas två gånger.
Whisper identifierar språket på egen hand och undertexterna kommer på det som faktiskt talas — inget att deklarera. Det identifierade språket finns i svaret om du vill förgrena på det.
Alla körs i webbläsaren, inget konto krävs för att testa.
Gör vilket ämne som helst till en quizvideo
Quizvideor i 16:9 eller som Shorts
Gör en ordlista till en språkvideo
Gör tweets och X-inlägg till videor
Gör vilken låt som helst till en karaokevideo
Gör en Reddit-tråd till en short
Gör ett kalkylark till en topplistevideo
Gör ett TikTok-kommentarsfält till en låtvideo
Skapa virala fruktquizvideor med AI
Skapa en nyckel, kör snabbstarten, och första textade mp4:an är minuter bort.