貼り付けて、キーを入れて、実行するだけ。疑似コードは一行もありません。
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: https://autostud.ai/api/v1 — 認証は `Authorization: Bearer sk_live_…`。`sk_test_` キーは同じ経路をすべて通ったうえで、消費の直前で止まります。
6ステップ。うち4つはリクエスト1本です。
ダッシュボード → 設定 → APIキー。スコープを自分で選ばないなら「Automation」プリセットで十分です(動画・レンダー・ファイルを含みます)。シークレットの表示は一度きり。`sk_live_` は消費し、`sk_test_` はリクエスト全体を検証して書き込み前に止まります。
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"アップロード用エンドポイントはありません。APIが読むのはURLです。自社バケット、CDN、署名付きリンク — 当社サーバーが取得できれば何でも構いません。ワークスペースのライブラリへの登録は任意です。
# 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` が返す `video_id` に、以降すべてがぶら下がります。`Idempotency-Key` を付ければ、再送しても2つ目のプロジェクトは作られず最初の応答が返ります。
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` がサーバー側で全部やります。Whisper が単語単位で文字起こしし、AI が強調語を印し、116種類のスタイルから1つを適用。応答には単語数・正確な尺・検出言語が入ります。
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` がワーカー群にジョブを載せ、即座に `render_id` を返します。1レンダーは長さに関係なく20クレジットです。
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"
}'`render.completed` を購読すれば、完成URLが署名付きで届きます。取りに行きたい場合は、その動画のレンダー一覧を取得して `render_status` が `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.スコープは「キーが持つべき権限」であって、送る値ではありません。
| コール | スコープ | 何をするか |
|---|---|---|
| GET /api/v1 | - | ディスカバリー:このキーで何ができるか、制限、消費量。 |
| POST /api/v1/actions/videos.create | videos:write | 動画プロジェクトを作成し、そのIDを返します。 |
| POST /api/v1/actions/subtitles.generate | videos:execute | 文字起こし・強調・スタイル適用を行い、字幕トラックを保存します。 |
| POST /api/v1/actions/renders.create | renders:execute | ワーカー群にレンダーを投入します。20クレジット。 |
| GET /api/v1/renders?video_id=… | renders:read | ある動画のレンダー一覧(新しい順)。ステータスとURL付き。 |
| POST /api/v1/webhooks | webhooks:write | https エンドポイントを登録し、署名シークレットを一度だけ返します。 |
`style_preset` に1つ渡すだけです。各プリセットがフォント・縁取り・強調色・アニメーションをまとめて決めるので、他に設定するものはありません。
default4 語 · simplebold3 語 · simpleimpact3 語 · focus_on_one_wordbeast1 語 · focus_on_one_wordkaraoke5 語 · focus_on_one_wordkaraoke_fill5 語 · karaokeneon4 語 · progressively_visibleminimal6 語 · simplepop5 語 · progressively_visiblepill5 語 · simplecinematic9 語 · simpleエラーの形はどれも同じです。分岐用の安定した `code`、直し方の呼び出しを名指しする `hint`、そして問い合わせ用の `request_id`。全コードの一覧は /docs/api/errors にあります。
| コード | 意味 |
|---|---|
| 401 missing_credentials | リクエストにキーがない、または知らないキーです。 |
| 403 insufficient_scope | キーにスコープが足りません。`details.required_scopes` が示します。 |
| 422 validation_failed | フィールドが不正です。`details.issues` にすべて出ます。 |
| 402 insufficient_credits | レンダーに必要なクレジットが足りません。追加するかテストキーで。 |
| 429 rate_limit_exceeded | 呼び出しが多すぎます。`Retry-After` 秒待って再試行してください。 |
| 502 upstream_error | 依存している事業者側の障害です。バックオフして再試行を。 |
{
"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"
}
}レンダーは数分かかります。向こうから来させましょう。
`X-Autostud-Signature: t=<unix>,v1=<hex>` は `"<timestamp>.<生のボディ>"` に対する HMAC-SHA256 です。パースする前に、生のボディで検証してください。
約2時間のあいだに5回試行し、配信レコードは1回目の前に書き込まれます。20回連続で失敗したエンドポイントは、叩き続けずに無効化します。
各試行は `X-Autostud-Delivery` を持ちます。同じIDは同じイベント。処理の主キーとして扱ってください。
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')
})作り直すのが大変な部分こそ、こちらが運用している部分です。
各単語が自分の開始と終了を持つので、ハイライトが音節に乗ります。文単位のタイミングこそ、自動字幕が遅れて見える原因です。
落ち着いた放送用から、跳ねるハイライト系まで。プリセットがフォント・縁取り・色・アニメーションをまとめて、キャンバスに合わせて調整します。
2回目のパスが文字起こしを読み、意味を担う語を印します。つなぎ言葉は静かなまま。真偽値ひとつでオフにできます。
話者分離はフラグひとつ。インタビューは声ごとに色が分かれて返るので、音がなくても誰が話しているか分かります。
API で字幕を付けた動画も、エディタで普通に開けます。単語を手で直して再レンダーし、そのまま自動化を続けられます。両方の経路が同じドキュメントを書きます。
冪等キー、型付きエラー、テストキー、署名付き Webhook、30日分のリクエストログ。APIの地味な半分、つまり深夜3時に効いてくる部分です。
できません。これは意図的で、APIはURLを受け取ります。当社サーバーが読める場所(自社バケット、CDN、署名付きリンク)に置き、`media_url` に渡してください。ダッシュボードからアップロードしたファイルには、そのまま使えるURLがあります。
今はできません。字幕は mp4 に焼き込まれます(ショート動画のプラットフォームが必要とするのはこちらです)。単語とタイミングのリストは動画に保存されるので、別ファイルはAPIの返り値から自前で生成できます。
レンダーは長さに関係なく固定20クレジットです。文字起こしと強調パスは、他のAI呼び出しと同じようにワークスペースに記録され、`GET /api/v1/usage` で期間内の消費を確認できます。
秒ではなく分単位です。リクエスト内ではなくワーカー群で走ります。だからこそ `render.completed` があります。接続を開いたままにせず、購読してください。
はい。`restyle_only: true` と別の `style_preset` で `subtitles.generate` を呼び直すと、動画に保存済みの単語を再利用するので、二重に文字起こしされません。
Whisper が言語を自動判別し、字幕は話されている言語で返ります。宣言は不要です。検出された言語は応答に含まれるので、そこで分岐できます。
どれもブラウザで動き、試すのにアカウントは不要です。
どんなテーマもクイズ動画に
16:9 でもショートでもクイズ動画に
単語リストを語学動画に
ツイートやXの投稿を動画に変換
どんな曲もカラオケ動画に
Redditのスレッドをショート動画に
表計算データをランキング動画に
TikTokのコメント欄を曲の動画に変える
AIでバズるフルーツクイズ動画を作成