Openai Sora 2 Pro Text To Video
Playground
Try it on WaveSpeedAI!OpenAI Sora 2 Pro is a state-of-the-art text-to-video model with realistic physics, synchronized audio, and strong steerability. Supports multiple resolutions up to 1080p and durations up to 20 seconds. Ready-to-use REST inference API, best performance, no coldstarts, affordable pricing.
Features
> Notice — Service Stability > > The Sora 2 family is currently unstable. Generations may fall back to alternative models without notice and the service can be temporarily unavailable. OpenAI is also expected to discontinue this model in the future. > > If you need an equally capable, stable alternative, we recommend Seedance 2: bytedance/seedance-2.0/text-to-video.
OpenAI Sora 2 Pro Text-to-Video
Sora 2 Pro is OpenAI’s premium video and audio generator. It advances prior video models with more accurate physics, sharper realism, synchronized audio, stronger steerability, and a wider stylistic range — built on the original Sora foundation.
Now with character consistency — create reusable character IDs and feature them across multiple videos with the same identity.
Why It Looks Great
- Physics-aware motion: learns contact, inertia, and momentum so objects move and collide believably.
- Temporal consistency: stable identities, minimal flicker/ghosting, and clean frame-to-frame transitions.
- Synchronized audio: lip-sync alignment, beat-aware cuts, and ambience that matches on-screen action.
- High-frequency detail: preserves fine textures (skin, fabric, foliage) without plastic over-sharpening.
- Complex scene reasoning: handles multiple subjects, occlusions, depth, and long camera moves coherently.
- Cinematic camera literacy: natural pans, push-ins, and handheld vibes without warping or jelly-artifacts.
- Wide stylistic range: from photoreal and documentary to anime, 3D, and illustrative aesthetics.
- Strong steerability: responds predictably to prompt edits and control settings (duration, fps, motion strength).
Parameters
| Parameter | Required | Description |
|---|---|---|
| prompt | Yes | Describe scene, style, camera, and audio cues |
| size | No | Output resolution (see options below) |
| duration | No | Video length: 4, 8, 12, 16, or 20 seconds |
| characters | No | List of character IDs for consistent identity |
Size Options
- 720×1280 / 1280×720 (720p)
- 1024×1792 / 1792×1024 (1024p)
- 1080×1920 / 1920×1080 (1080p)
How to Use
- Write your prompt — describe scene, style, camera movement, and audio cues.
- Select size — choose resolution and orientation.
- Set duration — select 4, 8, 12, 16, or 20 seconds.
- Add characters (optional) — paste character IDs to include for consistent characters.
- Submit — generate, preview, and download when ready.
Pricing
| Duration | 720p | 1024p | 1080p |
|---|---|---|---|
| 4 s | $1.20 | $2.00 | $2.80 |
| 8 s | $2.40 | $4.00 | $5.60 |
| 12 s | $3.60 | $6.00 | $8.40 |
| 16 s | $4.80 | $8.00 | $11.20 |
| 20 s | $6.00 | $10.00 | $14.00 |
Billing Rules
- 720p rate: $0.30 per second
- 1024p rate: $0.50 per second
- 1080p rate: $0.70 per second
- Duration options: 4, 8, 12, 16, or 20 seconds
Notes
- Prompt is the only required field.
- Please follow OpenAI’s usage policies: What images are permitted and prohibited in Sora-2
Related Models
- Sora 2 Text-to-Video — Standard version at lower cost.
- Sora 2 Pro Image-to-Video — Animate images with Sora Pro quality.
Authentication
For authentication details, please refer to the Authentication Guide.
API Endpoints
Submit Task & Query Result
set -euo pipefail
export WAVESPEED_API_KEY="your-api-key"
REQUEST_BODY=$(cat <<'JSON'
{
"prompt": "A cinematic ocean wave at sunrise, highly detailed",
"size": "1280*720",
"duration": 4
}
JSON
)
# 1. Submit the prediction.
SUBMIT_RESPONSE=$(curl --silent --show-error --fail-with-body \
-X POST "https://api.wavespeed.ai/api/v3/openai/sora-2-pro/text-to-video" \
-H "Authorization: Bearer ${WAVESPEED_API_KEY}" \
-H "Content-Type: application/json" \
-d "${REQUEST_BODY}")
TASK=$(printf '%s' "${SUBMIT_RESPONSE}" | jq 'if type == "object" and has("data") then .data else . end')
PREDICTION_ID=$(printf '%s' "${TASK}" | jq -r '.id // empty')
if [ -z "${PREDICTION_ID}" ]; then
printf 'Submission response did not contain a prediction id
' >&2
exit 1
fi
RESULT_URL=$(printf '%s' "${TASK}" | jq -r '.urls.get // empty')
if [ -z "${RESULT_URL}" ]; then RESULT_URL="https://api.wavespeed.ai/api/v3/predictions/${PREDICTION_ID}/result"; fi
# 2. Poll until the prediction finishes.
while true; do
RESPONSE=$(curl --silent --show-error --fail-with-body \
"${RESULT_URL}" \
-H "Authorization: Bearer ${WAVESPEED_API_KEY}")
RESULT=$(printf '%s' "${RESPONSE}" | jq 'if type == "object" and has("data") then .data else . end')
STATUS=$(printf '%s' "${RESULT}" | jq -r '.status // empty')
case "${STATUS}" in
completed) printf '%s\n' "${RESULT}" | jq '.outputs'; break ;;
failed|cancelled|timeout) printf '%s\n' "${RESULT}" | jq . >&2; exit 1 ;;
created|processing) sleep 2 ;;
*) printf 'Unexpected status: %s
' "${STATUS}" >&2; exit 1 ;;
esac
doneParameters
Task Submission Parameters
Request Parameters
| Parameter | Type | Required | Default | Range | Description |
|---|---|---|---|---|---|
| prompt | string | Yes | - | The positive prompt for the generation. | |
| size | string | No | 1280*720 | 720*1280, 1280*720, 1024*1792, 1792*1024, 1920*1080, 1080*1920 | The size of the generated media in pixels (width*height). |
| duration | integer | No | 4 | 4, 8, 12, 16, 20 | The duration of the generated video in seconds. |
| characters | array<object> | No | - | - | Element reference list of character IDs to include for consistent characters. |
Response Parameters
| Parameter | Type | Description |
|---|---|---|
| code | integer | HTTP status code (e.g., 200 for success) |
| message | string | Status message (e.g., “success”) |
| data.id | string | Unique identifier for the prediction, Task Id |
| data.model | string | Model ID used for the prediction |
| data.outputs | array | Output values, usually URL strings; some models return text strings or structured result objects (empty when status is not completed) |
| data.urls | object | Object containing related API endpoints |
| data.urls.get | string | URL to retrieve the prediction result |
| data.status | string | Status of the task: created, processing, completed, or failed |
| data.created_at | string | ISO timestamp of when the request was created (e.g., “2023-04-01T12:34:56.789Z”) |
| data.error | string | Error message (empty if no error occurred) |
| data.timings | object | Object containing timing details |
| data.timings.inference | integer | Inference time in milliseconds |
Result Request Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| id | string | Yes | - | Task ID |
Result Response Parameters
| Parameter | Type | Description |
|---|---|---|
| code | integer | HTTP status code (e.g., 200 for success) |
| message | string | Status message (e.g., “success”) |
| data | object | The prediction data object containing all details |
| data.id | string | Unique identifier for the prediction |
| data.model | string | Model ID used for the prediction |
| data.outputs | array<string | object> | Array of generated outputs (empty when status is not completed). Items are usually URL strings, but may be text strings or structured result objects, depending on the model. |
| data.urls | object | Object containing related API endpoints |
| data.urls.get | string | URL to poll for the prediction result |
| data.status | string | Status: created, processing, completed, or failed |
| data.created_at | string | ISO timestamp of when the request was created |
| data.error | string | Error message (empty if no error occurred) |
| data.timings | object | Object containing timing details |
| data.timings.inference | integer | Inference time in milliseconds |