Preview and Render Flow
FreshOverview
Many Creatify endpoints support a two-phase generation process: first generate a cheaper preview, then render the final high-quality version. This pattern saves credits and allows review before committing to full render costs.
The Pattern
Endpoints That Support Preview + Render
| Endpoint | Preview Cost | Render Cost | Total | Direct Cost |
|---|---|---|---|---|
| URL to Video | 1/30s | 4/30s | 5/30s | 5/30s |
| AI Editing | 1/30s | 4/30s | 5/30s | 5/30s |
| AI Avatar v2 | -- | 4/30s | 5+4/30s | 5/30s |
| Custom Templates | 1/30s | 4/30s | 5/30s | 5/30s |
When to Use Preview
Use preview when:
- Testing a new URL or content for the first time
- Iterating on creative direction
- Budget-conscious and want to review before full render
- Generating multiple variations to pick from
Use direct create when:
- You have a proven template/content combination
- Speed is more important than cost optimization
- The content has been previewed successfully before
Preview List (Async) Pattern
Some endpoints support generating multiple preview variations at once:
Code Example: Preview-Render Pattern
python
import time
import requests
def preview_and_render(endpoint, create_params, headers, poll_interval=10, timeout=600):
"""
Generic preview-and-render pattern for any Creatify endpoint.
Args:
endpoint: API endpoint path (e.g., "url_to_videos")
create_params: dict of creation parameters
headers: auth headers
poll_interval: seconds between polls
timeout: max seconds to wait
"""
base = f"https://api.creatify.ai/api/{endpoint}"
# Step 1: Create task (generates preview)
task = requests.post(f"{base}/", headers=headers, json=create_params).json()
task_id = task["id"]
print(f"Task created: {task_id}")
# Step 2: Poll for preview completion
result = poll_until_done(f"{base}/{task_id}/", headers, poll_interval, timeout)
print(f"Preview ready. Previews: {len(result.get('previews', []))}")
# Step 3: Review (in production, this would be a human review step)
previews = result.get("previews", [])
selected = previews[0]["id"] if previews else None
# Step 4: Render
render_params = {"preview_id": selected} if selected else {}
requests.post(f"{base}/{task_id}/render/", headers=headers, json=render_params)
print("Render started...")
# Step 5: Poll for render completion
final = poll_until_done(f"{base}/{task_id}/", headers, poll_interval, timeout)
print(f"Final video: {final['output']}")
return final
def poll_until_done(url, headers, interval=10, timeout=600):
"""Poll a task URL until status is done or failed."""
elapsed = 0
while elapsed < timeout:
result = requests.get(url, headers=headers).json()
if result["status"] == "done":
return result
if result["status"] == "failed":
raise Exception(f"Failed: {result.get('failed_reason')}")
time.sleep(interval)
elapsed += interval
raise TimeoutError("Polling timeout exceeded")Error Handling
| Stage | Error | Recovery |
|---|---|---|
| Preview creation | 402 Insufficient credits | Check balance, top up |
| Preview polling | Timeout | Increase timeout or retry later |
| Preview polling | failed status | Read failed_reason, adjust inputs |
| Render | Invalid preview ID | Re-fetch task to get current preview IDs |
| Render polling | Timeout | Renders may take longer; increase timeout |
See Also
- URL to Video Pipeline -- Full URL-to-video sequence
- Batch Production -- Scale preview+render at volume
- Status Codes Reference -- All status values explained