Skip to main content

POST /api/process

Submits a video (via URL or file upload) for asynchronous processing. The API will:
  1. Download/upload the video
  2. Transcribe audio with Whisper (word-level timestamps)
  3. Detect scene boundaries with PySceneDetect
  4. Use Gemini AI to identify 3-15 viral moments (15-60 seconds each)
  5. Extract and vertically reframe clips to 9:16 format
  6. Upload artifacts to S3 (silent background task)
This endpoint returns immediately with a job_id. Use /api/status/{job_id} to poll for completion.

Authentication

X-Gemini-Key
string
required
Your Google Gemini API key for AI analysis

Request Parameters

JSON Body (for URLs)

url
string
YouTube URL or direct video link to process
{
  "url": "https://youtube.com/watch?v=dQw4w9WgXcQ"
}

Form Data (for File Uploads)

file
file
Video file to upload (max 2048 MB)
url
string
Alternative to file upload - YouTube URL
You must provide either url or file, not both.

Response

job_id
string
required
Unique identifier for tracking this processing job
status
string
required
Initial status (always “queued” for new jobs)
{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "queued"
}

Processing Flow

Error Codes

CodeDescription
400Missing X-Gemini-Key header
400Neither url nor file provided
413File exceeds 2048 MB limit
500Processing error (download failed, API quota exceeded, etc.)

Examples

Process YouTube Video

curl -X POST http://localhost:8000/api/process \
  -H "X-Gemini-Key: AIzaSy..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://youtube.com/watch?v=dQw4w9WgXcQ"
  }'
Response:
{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "queued"
}

Upload Local Video

curl -X POST http://localhost:8000/api/process \
  -H "X-Gemini-Key: AIzaSy..." \
  -F "file=@/path/to/video.mp4"

Python SDK Example

import requests

url = "http://localhost:8000/api/process"
headers = {"X-Gemini-Key": "AIzaSy..."}

# Option 1: YouTube URL
response = requests.post(
    url,
    headers=headers,
    json={"url": "https://youtube.com/watch?v=dQw4w9WgXcQ"}
)

# Option 2: File Upload
with open("video.mp4", "rb") as f:
    response = requests.post(
        url,
        headers=headers,
        files={"file": f}
    )

job_id = response.json()["job_id"]
print(f"Job submitted: {job_id}")

JavaScript/Fetch Example

// Submit YouTube URL
const response = await fetch('http://localhost:8000/api/process', {
  method: 'POST',
  headers: {
    'X-Gemini-Key': 'AIzaSy...',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    url: 'https://youtube.com/watch?v=dQw4w9WgXcQ'
  })
});

const { job_id } = await response.json();
console.log('Job ID:', job_id);

// Upload file
const formData = new FormData();
formData.append('file', fileInput.files[0]);

const uploadResponse = await fetch('http://localhost:8000/api/process', {
  method: 'POST',
  headers: {
    'X-Gemini-Key': 'AIzaSy...'
  },
  body: formData
});

Next Steps

After submitting a job:
  1. Poll job status to check progress
  2. Once completed, apply AI effects to clips
  3. Add subtitles with custom styling
  4. Translate videos to other languages
  5. Post to social media

Advanced Configuration

The processing pipeline is controlled server-side via environment variables:
  • MAX_CONCURRENT_JOBS: Limit parallel processing (default: 5)
  • JOB_RETENTION_SECONDS: Auto-cleanup delay (default: 3600)
  • MAX_FILE_SIZE_MB: Upload size limit (default: 2048)

Build docs developers (and LLMs) love