Sous-titrez une vidéo
en trois appels API
Envoyez l'URL d'une vidéo, récupérez un mp4 avec les sous-titres incrustés mot à mot. Whisper cale chaque mot, une passe IA choisit ceux à mettre en avant, et le rendu tourne sur notre flotte de workers.
POSThttps://autostud.ai/api/v1/actions/subtitles.generateTout le parcours, dans un seul fichier
Collez, mettez votre clé, lancez. Rien ici n'est du pseudo-code.
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)URL de base : https://autostud.ai/api/v1 — authentification avec `Authorization: Bearer sk_live_…`. Une clé `sk_test_` parcourt exactement le même chemin et s'arrête avant de dépenser quoi que ce soit.
Ce que vous avez réellement à faire
Six étapes, dont quatre tiennent en une requête.
- 1
Créer une clé API
Dashboard, Paramètres, Clés API. Prenez le préréglage « Automation » si vous ne voulez pas choisir les scopes à la main : il couvre vidéos, rendus et fichiers. Le secret n'est affiché qu'une fois. `sk_live_` dépense, `sk_test_` valide toute la requête et s'arrête avant l'écriture.
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
Mettre la vidéo derrière une URL
Il n'y a pas d'endpoint d'upload : l'API lit une URL. Votre bucket, votre CDN, un lien signé — tout ce que nos serveurs peuvent récupérer. L'enregistrer dans la bibliothèque de l'espace est facultatif et ne change rien au reste.
# 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
Créer le projet vidéo
`videos.create` renvoie le `video_id` auquel tout le reste se rattache. Envoyez un `Idempotency-Key` et une requête rejouée renvoie la première réponse au lieu de créer un second projet.
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
Ajouter les sous-titres
`subtitles.generate` fait tout le travail côté serveur : Whisper transcrit avec un calage au mot, une passe IA marque les mots à accentuer, et un des 116 styles est appliqué. La réponse donne le nombre de mots, la durée exacte et la langue détectée.
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
Lancer le rendu
`renders.create` place le job sur la flotte de workers et répond immédiatement avec le `render_id`. Un rendu coûte 20 crédits, quelle que soit la durée de la vidéo.
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
Récupérer le mp4
Abonnez-vous à `render.completed` et l'URL finale vous est poussée, signée. Si vous préférez interroger, listez les rendus de la vidéo et lisez `render_status` jusqu'à `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.
Tous les appels de cette page
Les scopes sont ce que la clé doit porter, pas ce que vous envoyez.
| Appel | Scope | Ce que ça fait |
|---|---|---|
| GET /api/v1 | - | Découverte : ce que la clé peut faire, ses limites et sa consommation. |
| POST /api/v1/actions/videos.create | videos:write | Crée le projet vidéo et renvoie son identifiant. |
| POST /api/v1/actions/subtitles.generate | videos:execute | Transcrit, accentue, style et enregistre la piste de sous-titres. |
| POST /api/v1/actions/renders.create | renders:execute | Met le rendu en file sur la flotte de workers. 20 crédits. |
| GET /api/v1/renders?video_id=… | renders:read | Les rendus d'une vidéo, du plus récent au plus ancien, avec statut et URL. |
| POST /api/v1/webhooks | webhooks:write | Enregistre un endpoint https et renvoie son secret de signature, une fois. |
Styles disponibles
Passez-en un dans `style_preset`. Chacun règle d'un coup la police, le contour, la couleur d'accent et l'animation — il n'y a rien d'autre à configurer.
default4 mots · simplebold3 mots · simpleimpact3 mots · focus_on_one_wordbeast1 mots · focus_on_one_wordkaraoke5 mots · focus_on_one_wordkaraoke_fill5 mots · karaokeneon4 mots · progressively_visibleminimal6 mots · simplepop5 mots · progressively_visiblepill5 mots · simplecinematic9 mots · simpleÀ savoir avant de coder
- Les limites de débit sont par clé et renvoyées en en-têtes : `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `Retry-After` sur un 429.
- `Idempotency-Key` sur un POST rend un rejeu sûr pendant 24 heures ; la première réponse est renvoyée à l'identique.
- Une clé `sk_test_` exerce l'authentification, les scopes, les limites et la validation, puis répond `simulated: true` sans rien écrire ni dépenser.
- Les erreurs sont typées : `invalid_request`, `insufficient_credits`, `rate_limit_exceeded`, `upstream_error` — branchez sur le code, jamais sur le message.
Quand ça échoue
Toutes les erreurs ont la même forme : un `code` stable sur lequel brancher, un `hint` qui nomme l'appel qui corrige, et un `request_id` à citer. Le vocabulaire complet est sur /docs/api/errors.
| Code | Ce que ça veut dire |
|---|---|
| 401 missing_credentials | Aucune clé sur la requête, ou une clé inconnue. |
| 403 insufficient_scope | Il manque un scope à la clé ; `details.required_scopes` le nomme. |
| 422 validation_failed | Un champ est invalide ; `details.issues` les liste tous. |
| 402 insufficient_credits | Pas assez de crédits pour le rendu. Rechargez, ou passez en clé de test. |
| 429 rate_limit_exceeded | Trop d'appels. Attendez `Retry-After` secondes, puis réessayez. |
| 502 upstream_error | Un fournisseur dont nous dépendons a échoué. Réessayez avec un 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"
}
}Arrêtez de faire du polling
Un rendu prend des minutes. Laissez-le venir à vous.
Signés, vérifiables en dix lignes
`X-Autostud-Signature: t=<unix>,v1=<hex>` est un HMAC-SHA256 sur `"<timestamp>.<corps brut>"`. Vérifiez sur le corps brut, avant de le parser.
Réessayés pour vous
Cinq tentatives sur environ deux heures, avec la ligne de livraison écrite avant la première. Un endpoint qui échoue vingt fois d'affilée est désactivé plutôt que martelé.
Dédupliquez sur l'identifiant de livraison
Chaque tentative porte `X-Autostud-Delivery`. Même identifiant, même événement : traitez-le comme la clé primaire du travail que vous déclenchez.
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')
})Pourquoi c'est un appel et pas quinze
Les morceaux difficiles à refaire sont ceux que nous opérons.
Calage au mot
Chaque mot porte son début et sa fin, donc la surbrillance tombe sur la syllabe. Le calage à la phrase est ce qui fait que la plupart des sous-titres automatiques semblent en retard.
116 styles, une chaîne de caractères
Du sous-titre broadcast sobre au style rebondissant surligné. Le préréglage règle police, contour, couleur et animation ensemble, à l'échelle de votre canvas.
L'IA choisit les accents
Une seconde passe lit la transcription et marque les mots qui portent le sens. Les mots de remplissage restent calmes. Un booléen suffit à la désactiver.
Deux voix, deux couleurs
La diarisation est un simple flag. Une interview revient avec chaque voix dans sa couleur, et le spectateur sait qui parle même sans le son.
Les mêmes objets que le dashboard
Une vidéo sous-titrée par l'API s'ouvre dans l'éditeur comme n'importe quelle autre. Corrigez un mot à la main, relancez le rendu, continuez d'automatiser : les deux chemins écrivent le même document.
Pensée pour être rejouée
Clés d'idempotence, erreurs typées, clés de test, webhooks signés et un journal de requêtes sur 30 jours. La moitié ennuyeuse d'une API, celle qu'on sent à 3 h du matin.
Les questions que les développeurs nous envoient vraiment
Non, et c'est volontaire : l'API prend une URL. Hébergez la vidéo là où nos serveurs peuvent la lire — votre bucket, un CDN, un lien signé — et passez-la dans `media_url`. Les fichiers envoyés depuis le dashboard ont déjà une URL utilisable.
Pas aujourd'hui. Les sous-titres sont incrustés dans le mp4, ce qu'attendent les plateformes de format court. La liste des mots et leur calage restent stockés sur la vidéo : un fichier séparé est une transformation que vous pouvez faire chez vous à partir de ce que l'API renvoie.
Un rendu, c'est 20 crédits, fixe, quelle que soit la durée. La transcription et la passe d'accentuation sont enregistrées dans votre espace comme tout autre appel IA, et `GET /api/v1/usage` indique ce qu'une clé a consommé sur la période.
Des minutes, pas des secondes : il tourne sur une flotte de workers, pas dans la requête. C'est exactement à ça que sert `render.completed` — abonnez-vous plutôt que de garder une connexion ouverte.
Oui. Rappelez `subtitles.generate` avec `restyle_only: true` et un autre `style_preset` : les mots déjà stockés sur la vidéo sont réutilisés, rien n'est transcrit deux fois.
Whisper détecte la langue tout seul et les sous-titres reviennent dans celle qui est parlée — rien à déclarer. La langue détectée est renvoyée dans la réponse, vous pouvez brancher dessus.
D'autres outils gratuits
Tous tournent dans le navigateur, sans compte pour essayer.
Générateur de Vidéo Quiz TikTok
Outil en directTransformez un sujet en vidéo quiz
Générateur de Vidéo Quiz YouTube
Outil en directDes vidéos quiz en 16:9 ou en Shorts
Générateur de Vidéo Quiz de Langue
Outil en directTransformez une liste de mots en vidéo de langue
Tweet en Vidéo
Outil en directTransformez vos tweets en vidéos
YouTube en Vidéo Karaoké
Outil en directTransformez un son en vidéo karaoké
Post Reddit en Vidéo
Outil en directTransformez un fil Reddit en short
CSV en Vidéo Classement
Outil en directTransformez un tableur en vidéo de classement
Commentaires TikTok en Vidéo Chanson
Outil en directTransformez les commentaires TikTok en vidéo chanson
Vidéos IA Fruits
Créez des vidéos de fruits virales avec l'IA
Produisez de la vidéo sous-titrée depuis votre propre backend
Créez une clé, lancez le quickstart, et le premier mp4 sous-titré est à quelques minutes.