Lyrics / Subtitle Sync API
The Lyrics / Subtitle Sync API turns a public audio URL into lyrics plus line-level subtitle artifacts through OmnAPI’s managed transcription and timing pipeline. It is designed for MV captions, lyric preview, and any workflow that needs SRT/VTT/LRC/JSON timing from ordinary audio.
Use this flow:
POST /api/v1/subtitles/quoteto estimate credits and public price.POST /api/v1/subtitleswith anIdempotency-Key.- Poll
GET /api/v1/subtitles/{taskId}. - Read
artifacts.srtUrl,artifacts.vttUrl,artifacts.lrcUrl, orartifacts.jsonUrlfrom the completed task.
source.durationSec is optional. If omitted, OmnAPI safely probes the public
audio URL before quote/create and uses the server-detected duration for pricing,
budget checks, and queue sizing. Send it only as a client hint when you already
know the duration.
curl -X POST https://api.omnapi.com/api/v1/subtitles/quote \ -H "x-api-key: $OMNAPI_KEY" \ -H "Content-Type: application/json" \ -d '{ "source": { "type": "audio", "audioUrl": "https://example.com/song.mp3" }, "budget": { "maxCostUsdPerMin": 0.05 } }'Response:
{ "credits": 1, "durationSec": 60, "estimatedUsd": 0.02, "maxCostUsdPerMin": 0.05, "publicUsdPerMin": 0.02}budget.maxCostUsdPerMin is a public price guard. Quote returns both the active
price and submitted ceiling so clients can decide before creating a task. Create
fails with SUBTITLE_BUDGET_EXCEEDED before credits are deducted when the
active subtitle price is above the submitted ceiling.
Create
Section titled “Create”curl -X POST https://api.omnapi.com/api/v1/subtitles \ -H "x-api-key: $OMNAPI_KEY" \ -H "Idempotency-Key: subtitle-demo-001" \ -H "Content-Type: application/json" \ -d '{ "mode": "extract", "source": { "type": "audio", "audioUrl": "https://example.com/song.mp3" }, "language": "auto", "outputs": ["srt", "json", "vtt", "lrc"], "budget": { "maxCostUsdPerMin": 0.05 }, "config": { "metadata": { "purpose": "mv-caption" } } }'Response:
{ "taskId": "task_01J...", "status": "PENDING", "creditsRequired": 1, "pollUrl": "/api/v1/subtitles/task_01J..."}| Field | Type | Required | Notes |
|---|---|---|---|
mode | "extract" | — | Default extract. |
source.type | "audio" | yes | Public audio URL input. |
source.audioUrl | string | yes | Public http(s) URL. Private/local network URLs are rejected. |
source.durationSec | number | — | Optional 1-600 second hint. If omitted, OmnAPI probes the audio before quoting or creating. |
language | string | — | Omit or use "auto" for automatic language handling. |
outputs | array | — | Any of srt, json, vtt, lrc; default is srt + json. |
budget.maxCostUsdPerMin | number | — | Per-minute public price ceiling. Use 0.05 to enforce a five-cent/minute cap. |
maxCredits | number | — | Optional create-time credit spend guard. |
config | object | — | Standard task config: priority, tags, metadata, webhookUrl. |
curl https://api.omnapi.com/api/v1/subtitles/task_01J... \ -H "x-api-key: $OMNAPI_KEY"Completed response:
{ "taskId": "task_01J...", "status": "COMPLETED", "progress": 100, "lyrics": "First lyric line\nSecond lyric line", "timeline": { "lines": [ { "index": 1, "startSec": 0.12, "endSec": 3.4, "text": "First lyric line" } ], "words": [] }, "artifacts": { "srt": { "url": "https://cdn.omnapi.com/...", "expiresAt": "2026-07-12T00:00:00.000Z", "retentionDays": 7 }, "json": { "url": "https://cdn.omnapi.com/...", "expiresAt": "2026-07-12T00:00:00.000Z", "retentionDays": 7 }, "srtUrl": "https://cdn.omnapi.com/...", "jsonUrl": "https://cdn.omnapi.com/..." }, "warnings": []}Current extraction returns line-level timing. timeline.words is included for a
stable response shape and may be empty.
MV Auto Subtitles
Section titled “MV Auto Subtitles”MV Fast and Studio use the same Subtitle Sync capability when a request enables
subtitles but does not provide srtUrl.
{ "mode": "fast", "source": { "type": "audio", "audioUrl": "https://example.com/song.mp3" }, "subtitles": true, "subtitle": { "mode": "auto", "language": "auto", "maxCostUsdPerMin": 0.05, "fallback": "continue_without_subtitles" }}Use subtitle.mode="provided" when your product requires caller-supplied timing
only. Use subtitle.mode="off" to disable subtitles even if a legacy
subtitles toggle is present.
Error Codes
Section titled “Error Codes”| Code | HTTP | Meaning |
|---|---|---|
SUBTITLE_BUDGET_EXCEEDED | 400 | Active public subtitle price is above budget.maxCostUsdPerMin. |
AUDIO_DURATION_INVALID | 400 | source.durationSec is outside the subtitle extraction range or does not match the probed duration. |
AUDIO_DURATION_PROBE_FAILED | 400 | OmnAPI could not determine duration from the submitted audio. |
AUDIO_FILE_TOO_LARGE | 413 | Submitted audio exceeds the Subtitle Sync audio size limit. |
AUDIO_URL_INVALID | 400 | The audio URL is invalid, private/local, or otherwise not allowed. |
AUDIO_URL_UNREACHABLE | 400 / 408 / 502 | OmnAPI could not fetch or inspect the audio URL. |
SERVICE_UNAVAILABLE | 503 | Subtitle Sync is disabled, temporarily unavailable, or all extraction slots are busy. |
SUBTITLE_GENERATION_FAILED | 400 / 502 | Audio download, transcription, or subtitle artifact generation failed. |
SUBTITLE_NO_SPEECH_DETECTED | 422 | The audio did not produce usable lyric or speech content. |