Generate stunning AI videos using OpenAI's Sora 2 API with this Bun-powered CLI tool.
- Bun runtime installed
- OpenAI API key with Sora 2 access
- Set your API key:
export OPENAI_API_KEY=sk-...
# Clone the repository
git clone <repository-url>
cd sora2-node
# Install dependencies
bun installbun run create-sora2-video.ts --prompt "your prompt" [options]Start the API server with authentication:
# Set environment variables
export OPENAI_API_KEY=sk-your-api-key
export AUTH_TOKEN=your-secret-auth-token
export PORT=3000 # optional, defaults to 3000
# Start the server
bun run api-server.tsThe server provides RESTful endpoints for video generation with Bearer token authentication.
| Option | Description | Default |
|---|---|---|
--prompt |
Text prompt describing the scene (required) | - |
--duration |
Video length in seconds: 4, 8, or 12 | 8 |
--orientation |
Video orientation: portrait or landscape | landscape |
--image |
Path to guide image for style reference | - |
--model |
Model version: sora-2 or sora-2-pro | sora-2 |
--outdir |
Output directory for generated videos | ./out |
--seed |
Random seed for reproducible results | - |
# Simple landscape video
bun run create-sora2-video.ts \
--prompt "A serene mountain lake at dawn with mist rising from the water"
# Portrait video for social media
bun run create-sora2-video.ts \
--prompt "Time-lapse of flowers blooming in vibrant colors" \
--orientation portrait# Action sequence
bun run create-sora2-video.ts \
--prompt "A golden retriever surfing at sunset, cinematic lighting, detailed water spray, upbeat indie rock soundtrack" \
--orientation landscape \
--duration 12
# Sci-fi cityscape
bun run create-sora2-video.ts \
--prompt "Futuristic neon-lit city with flying cars, blade runner style, rain reflections, synthwave music" \
--duration 12 \
--model sora-2-pro
# Film noir detective
bun run create-sora2-video.ts \
--prompt "1940s detective in fedora walking through foggy alley, black and white, jazz soundtrack, film noir lighting" \
--duration 8
# Epic fantasy battle
bun run create-sora2-video.ts \
--prompt "Dragon breathing fire over medieval castle at night, epic orchestral music, Game of Thrones style" \
--duration 12# Watercolor animation
bun run create-sora2-video.ts \
--prompt "Watercolor painting coming to life: koi fish swimming in a pond with lotus flowers" \
--orientation portrait \
--duration 8
# Studio Ghibli inspired
bun run create-sora2-video.ts \
--prompt "A cozy cottage in a meadow, Studio Ghibli style, soft clouds drifting by, peaceful piano melody" \
--duration 12
# Oil painting transformation
bun run create-sora2-video.ts \
--prompt "Van Gogh style starry night slowly morphing into dawn, swirling brushstrokes, classical music" \
--duration 8
# Anime action scene
bun run create-sora2-video.ts \
--prompt "Anime character with flowing hair jumping between buildings, sakura petals, dynamic camera angles, j-rock music" \
--orientation portrait \
--duration 4# Wildlife documentary
bun run create-sora2-video.ts \
--prompt "Majestic eagle soaring over snow-capped mountains, documentary style, orchestral score" \
--duration 12
# Underwater scene
bun run create-sora2-video.ts \
--prompt "Coral reef teeming with colorful tropical fish, sunlight filtering through water" \
--duration 8
# Aurora borealis
bun run create-sora2-video.ts \
--prompt "Northern lights dancing across Arctic sky, time-lapse, ethereal ambient music, ultra wide angle" \
--duration 12
# Macro nature
bun run create-sora2-video.ts \
--prompt "Extreme close-up of dewdrops on spider web at sunrise, bokeh background, nature sounds" \
--duration 4# Abstract visuals
bun run create-sora2-video.ts \
--prompt "Flowing liquid metal morphing into geometric shapes, iridescent colors, ambient electronic music" \
--duration 8
# Particle effects
bun run create-sora2-video.ts \
--prompt "Millions of glowing particles forming a phoenix, dramatic orchestral crescendo" \
--duration 12
# Fractal zoom
bun run create-sora2-video.ts \
--prompt "Infinite fractal zoom into Mandelbrot set, psychedelic colors, electronic music" \
--duration 8
# Data visualization
bun run create-sora2-video.ts \
--prompt "3D data points forming constellation patterns, holographic style, tech ambient soundtrack" \
--duration 4# Cooking montage
bun run create-sora2-video.ts \
--prompt "Chocolate lava cake being prepared, macro shots, melting chocolate center reveal, upbeat music" \
--duration 8
# Coffee art
bun run create-sora2-video.ts \
--prompt "Barista creating latte art, steam rising, warm lighting, coffee shop ambiance" \
--orientation portrait \
--duration 4
# Sushi preparation
bun run create-sora2-video.ts \
--prompt "Master sushi chef preparing omakase, precise knife work, minimalist aesthetic, traditional Japanese music" \
--duration 12# Extreme sports
bun run create-sora2-video.ts \
--prompt "Snowboarder doing backflip off mountain cliff, slow motion snow spray, adrenaline rock music" \
--duration 4
# Basketball highlight
bun run create-sora2-video.ts \
--prompt "Basketball player dunking in slow motion, stadium lights, crowd cheering, hip-hop beat" \
--orientation portrait \
--duration 4
# Parkour sequence
bun run create-sora2-video.ts \
--prompt "Parkour athlete running across rooftops at sunset, first person view, electronic music" \
--duration 8# 80s aesthetic
bun run create-sora2-video.ts \
--prompt "Retro wave sunset with palm trees, VHS glitch effects, neon grid floor, synthwave music" \
--duration 8
# Vintage film
bun run create-sora2-video.ts \
--prompt "1920s flapper dancing, sepia tone, film grain, scratches, ragtime piano music" \
--orientation portrait \
--duration 4
# Arcade nostalgia
bun run create-sora2-video.ts \
--prompt "8-bit pixel art world coming to life, retro game sprites, chiptune music, CRT TV effect" \
--duration 8# Fashion runway
bun run create-sora2-video.ts \
--prompt "Model walking runway, flowing fabric, dramatic lighting, fashion show atmosphere, electronic beats" \
--orientation portrait \
--duration 8
# Makeup transformation
bun run create-sora2-video.ts \
--prompt "Time-lapse makeup application, glitter and colors, beauty lighting, pop music" \
--orientation portrait \
--duration 4
# Jewelry showcase
bun run create-sora2-video.ts \
--prompt "Diamond necklace rotating, sparkling under studio lights, luxury presentation, elegant classical music" \
--duration 4# Modern architecture
bun run create-sora2-video.ts \
--prompt "Drone ascending modern glass skyscraper at sunset, reflective surfaces, ambient electronic" \
--duration 12
# Ancient ruins
bun run create-sora2-video.ts \
--prompt "Mayan pyramid emerging from jungle mist at dawn, mystical atmosphere, tribal drums" \
--duration 8
# City time-lapse
bun run create-sora2-video.ts \
--prompt "Tokyo intersection at night, time-lapse of people and traffic, neon signs, city sounds" \
--duration 8# Space exploration
bun run create-sora2-video.ts \
--prompt "Spacecraft approaching Saturn's rings, realistic space physics, epic orchestral score" \
--duration 12
# Microscopic world
bun run create-sora2-video.ts \
--prompt "Journey through human bloodstream, red blood cells flowing, scientific visualization, ambient music" \
--duration 8
# Robot assembly
bun run create-sora2-video.ts \
--prompt "Futuristic robot being assembled, mechanical parts fitting together, industrial sounds" \
--duration 4
# DNA visualization
bun run create-sora2-video.ts \
--prompt "DNA double helix rotating and unzipping, bioluminescent colors, scientific ambient music" \
--orientation portrait \
--duration 4# Magical forest
bun run create-sora2-video.ts \
--prompt "Enchanted forest with glowing mushrooms and fireflies, fairy tale atmosphere, mystical harp music" \
--duration 8
# Wizard spell
bun run create-sora2-video.ts \
--prompt "Wizard casting fire spell, magical particles, ancient library setting, epic fantasy music" \
--duration 4
# Crystal cave
bun run create-sora2-video.ts \
--prompt "Underground crystal cave with rainbow light refractions, ethereal atmosphere, new age music" \
--duration 12# Christmas scene
bun run create-sora2-video.ts \
--prompt "Snow falling on decorated Christmas tree in cozy living room, fireplace crackling, holiday music" \
--duration 8
# Halloween atmosphere
bun run create-sora2-video.ts \
--prompt "Spooky jack-o'-lanterns glowing in foggy graveyard, full moon, eerie ambient sounds" \
--duration 8
# Cherry blossoms
bun run create-sora2-video.ts \
--prompt "Sakura petals falling in slow motion, Japanese garden, traditional koto music" \
--orientation portrait \
--duration 4# Style transfer from image
bun run create-sora2-video.ts \
--prompt "Character walking through enchanted forest" \
--image ./reference-style.jpg \
--duration 8
# Product visualization
bun run create-sora2-video.ts \
--prompt "Luxury watch rotating 360 degrees, studio lighting, elegant presentation" \
--image ./product-photo.jpg \
--duration 4# Use seed for consistent generation
bun run create-sora2-video.ts \
--prompt "Northern lights dancing across starry sky" \
--seed 42 \
--duration 12# Save to specific folder
bun run create-sora2-video.ts \
--prompt "Timelapse of clouds over mountain range" \
--outdir ./videos/timelapse \
--duration 8-
Be Specific: Include details about lighting, camera angles, and mood
--prompt "Close-up shot of raindrops on a window, bokeh city lights in background, melancholic mood" -
Include Audio Descriptions: Sora 2 can generate synchronized audio
--prompt "Jazz band performing in smoky club, upbeat swing music, crowd chatter" -
Specify Art Styles: Reference specific artistic styles or artists
--prompt "Landscape in Van Gogh's style, swirling clouds, vibrant yellows and blues" -
Camera Movements: Describe how the camera should move
--prompt "Drone shot ascending over foggy forest, revealing mountain peak at sunrise"
- Duration: Shorter videos (4s) generate faster and are good for testing
- Model Selection: Use
sora-2-profor higher quality at increased cost - Image References: Provide high-quality images for better style matching
- Orientation: Choose based on intended platform (landscape for YouTube, portrait for TikTok/Reels)
Generated videos are saved in the output directory with the format:
sora2_<job-id>.mp4
If audio is generated separately, it will be saved as:
sora2_<job-id>.aac
The script includes comprehensive error handling:
- Validates API key presence
- Checks image file existence
- Reports API errors clearly
- Shows generation progress
- Duration options: 4, 8, or 12 seconds
- Resolutions: 1280x720 (landscape) or 720x1280 (portrait)
- Requires valid OpenAI API key with Sora 2 access
- Subject to your OpenAI account rate limits
All API endpoints (except /health) require Bearer token authentication:
-H "Authorization: Bearer your-secret-auth-token"# No authentication required
curl http://localhost:3000/health# Basic video generation
curl -X POST http://localhost:3000/api/videos \
-H "Authorization: Bearer your-secret-auth-token" \
-H "Content-Type: application/json" \
-d '{
"prompt": "A beautiful sunset over the ocean with waves crashing"
}'
# With all parameters
curl -X POST http://localhost:3000/api/videos \
-H "Authorization: Bearer your-secret-auth-token" \
-H "Content-Type: application/json" \
-d '{
"prompt": "A cyberpunk city at night, neon lights, rain",
"duration": 12,
"orientation": "landscape",
"model": "sora-2-pro",
"seed": 42
}'
# Response
{
"jobId": "job_1234567890_abc123",
"status": "queued",
"message": "Video generation started"
}# Check job progress
curl http://localhost:3000/api/videos/job_1234567890_abc123 \
-H "Authorization: Bearer your-secret-auth-token"
# Response (processing)
{
"id": "job_1234567890_abc123",
"status": "processing",
"progress": 45,
"createdAt": "2025-01-07T12:00:00Z",
"request": {
"prompt": "A beautiful sunset over the ocean with waves crashing"
}
}
# Response (completed)
{
"id": "job_1234567890_abc123",
"status": "completed",
"progress": 100,
"videoUrl": "/videos/job_1234567890_abc123.mp4",
"createdAt": "2025-01-07T12:00:00Z",
"completedAt": "2025-01-07T12:02:30Z",
"request": {
"prompt": "A beautiful sunset over the ocean with waves crashing"
}
}curl http://localhost:3000/api/videos \
-H "Authorization: Bearer your-secret-auth-token"
# Response
{
"jobs": [
{
"id": "job_1234567890_abc123",
"status": "completed",
"progress": 100,
"createdAt": "2025-01-07T12:00:00Z",
"completedAt": "2025-01-07T12:02:30Z",
"prompt": "A beautiful sunset over the ocean with waves crashing"
},
{
"id": "job_0987654321_xyz789",
"status": "processing",
"progress": 60,
"createdAt": "2025-01-07T12:05:00Z",
"prompt": "Northern lights dancing across the sky"
}
],
"total": 2
}# Download completed video
curl -O http://localhost:3000/videos/job_1234567890_abc123.mp4 \
-H "Authorization: Bearer your-secret-auth-token"
# Or use wget
wget --header="Authorization: Bearer your-secret-auth-token" \
http://localhost:3000/videos/job_1234567890_abc123.mp4curl -X DELETE http://localhost:3000/api/videos/job_1234567890_abc123 \
-H "Authorization: Bearer your-secret-auth-token"
# Response
{
"message": "Job deleted successfully"
}| Field | Type | Description | Required | Default |
|---|---|---|---|---|
prompt |
string | Text description of the video | Yes | - |
duration |
number | Video length: 4, 8, or 12 seconds | No | 8 |
orientation |
string | "portrait" or "landscape" | No | "landscape" |
model |
string | "sora-2" or "sora-2-pro" | No | "sora-2" |
seed |
number | Random seed for reproducibility | No | - |
image |
string | Base64 encoded guide image | No | - |
200- Success202- Job accepted and queued400- Bad request (invalid parameters)401- Unauthorized (missing or invalid token)404- Resource not found500- Server error
# 1. Create a video generation job
JOB_ID=$(curl -s -X POST http://localhost:3000/api/videos \
-H "Authorization: Bearer your-secret-auth-token" \
-H "Content-Type: application/json" \
-d '{"prompt": "A serene Japanese garden with koi fish"}' \
| jq -r '.jobId')
echo "Job created: $JOB_ID"
# 2. Poll for completion
while true; do
STATUS=$(curl -s http://localhost:3000/api/videos/$JOB_ID \
-H "Authorization: Bearer your-secret-auth-token" \
| jq -r '.status')
echo "Status: $STATUS"
if [ "$STATUS" = "completed" ]; then
break
elif [ "$STATUS" = "failed" ]; then
echo "Job failed!"
exit 1
fi
sleep 5
done
# 3. Download the video
curl -O http://localhost:3000/videos/$JOB_ID.mp4 \
-H "Authorization: Bearer your-secret-auth-token"
echo "Video downloaded: $JOB_ID.mp4"import requests
import time
import json
# Configuration
API_URL = "http://localhost:3000"
AUTH_TOKEN = "your-secret-auth-token"
headers = {"Authorization": f"Bearer {AUTH_TOKEN}"}
# Create video job
response = requests.post(
f"{API_URL}/api/videos",
headers={**headers, "Content-Type": "application/json"},
json={
"prompt": "A futuristic city with flying cars",
"duration": 8,
"orientation": "landscape"
}
)
job_id = response.json()["jobId"]
print(f"Job created: {job_id}")
# Poll for completion
while True:
response = requests.get(f"{API_URL}/api/videos/{job_id}", headers=headers)
data = response.json()
print(f"Status: {data['status']}, Progress: {data.get('progress', 0)}%")
if data["status"] == "completed":
video_url = data["videoUrl"]
break
elif data["status"] == "failed":
print(f"Error: {data.get('error')}")
exit(1)
time.sleep(5)
# Download video
response = requests.get(f"{API_URL}{video_url}", headers=headers)
with open(f"{job_id}.mp4", "wb") as f:
f.write(response.content)
print(f"Video saved as {job_id}.mp4")const API_URL = 'http://localhost:3000';
const AUTH_TOKEN = 'your-secret-auth-token';
async function generateVideo(prompt) {
// Create job
const createResponse = await fetch(`${API_URL}/api/videos`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${AUTH_TOKEN}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ prompt })
});
const { jobId } = await createResponse.json();
console.log(`Job created: ${jobId}`);
// Poll for completion
while (true) {
const statusResponse = await fetch(`${API_URL}/api/videos/${jobId}`, {
headers: { 'Authorization': `Bearer ${AUTH_TOKEN}` }
});
const job = await statusResponse.json();
console.log(`Status: ${job.status}, Progress: ${job.progress || 0}%`);
if (job.status === 'completed') {
return job.videoUrl;
} else if (job.status === 'failed') {
throw new Error(job.error);
}
await new Promise(resolve => setTimeout(resolve, 5000));
}
}
// Usage
generateVideo('A magical forest at twilight')
.then(videoUrl => console.log(`Video ready at: ${videoUrl}`))
.catch(error => console.error('Error:', error));export OPENAI_API_KEY=sk-your-api-key-herechmod +x create-sora2-video.tsInstall Bun from https://bun.sh:
curl -fsSL https://bun.sh/install | bashMIT
Pull requests welcome! Please ensure your code follows the existing style and includes appropriate error handling.
This project was created using bun init in bun v1.2.21. Bun is a fast all-in-one JavaScript runtime.