Python Code Example
import json
import os
import time
import requests
MODEL = "happyhorse-1.0"
PROMPT = (
"A miniature city built from cardboard and bottle caps comes alive at night. "
"A tiny cardboard train rolls through the streets while warm lights glow from "
"paper windows, physically realistic motion, detailed tabletop cinematography."
)
SECONDS = "3"
SIZE = "1280x720"
BASE_URL = "https://api.cometapi.com"
OUTPUT_DIR = "./output"
POLL_INTERVAL_SECONDS = 10
RETRY_DELAY_SECONDS = 5
MAX_CREATE_ATTEMPTS = 5
TERMINAL_STATUSES = {"completed", "failed", "error", "success"}
SUCCESS_STATUSES = {"completed", "success"}
try:
COMETAPI_KEY = os.environ["COMETAPI_KEY"]
except KeyError:
print("Set COMETAPI_KEY before running this example.")
raise SystemExit(0)
headers = {"Authorization": f"Bearer {COMETAPI_KEY}"}
def is_progress_complete(progress):
if isinstance(progress, (int, float)):
return progress >= 100
if isinstance(progress, str):
try:
return float(progress.rstrip("%")) >= 100
except ValueError:
return False
return False
def is_transient_status(status_code):
return status_code == 429 or 500 <= status_code < 600
def create_task():
fields = {
"model": (None, MODEL),
"prompt": (None, PROMPT),
"seconds": (None, SECONDS),
"size": (None, SIZE),
}
for attempt in range(1, MAX_CREATE_ATTEMPTS + 1):
try:
response = requests.post(
f"{BASE_URL}/v1/videos",
headers=headers,
files=fields,
timeout=30,
)
except requests.RequestException as error:
if attempt == MAX_CREATE_ATTEMPTS:
raise
print(f"Create request failed: {error}, retrying...")
time.sleep(RETRY_DELAY_SECONDS)
continue
if response.ok:
return response
if not is_transient_status(response.status_code) or attempt == MAX_CREATE_ATTEMPTS:
response.raise_for_status()
print(f"Create request returned {response.status_code}, retrying...")
time.sleep(RETRY_DELAY_SECONDS)
raise SystemExit("Failed to create task.")
def get_task(task_id):
while True:
try:
response = requests.get(
f"{BASE_URL}/v1/videos/{task_id}",
headers=headers,
timeout=15,
)
except requests.RequestException as error:
print(f"Status request failed: {error}, retrying...")
time.sleep(RETRY_DELAY_SECONDS)
continue
if response.ok:
return response
if not is_transient_status(response.status_code):
response.raise_for_status()
print(f"Status request returned {response.status_code}, retrying...")
time.sleep(RETRY_DELAY_SECONDS)
def download_video(content_url, output_path):
while True:
try:
with requests.get(content_url, headers=headers, timeout=120, stream=True) as response:
if response.ok:
with open(output_path, "wb") as output_file:
for chunk in response.iter_content(chunk_size=8192):
if chunk:
output_file.write(chunk)
return
if not is_transient_status(response.status_code):
response.raise_for_status()
print(f"Content request returned {response.status_code}, retrying...")
except requests.RequestException as error:
print(f"Content request failed: {error}, retrying...")
time.sleep(RETRY_DELAY_SECONDS)
create_response = create_task()
create_result = create_response.json()
task_id = create_result.get("id") or create_result.get("task_id")
if not task_id:
print(json.dumps(create_result, indent=2))
raise SystemExit("No task id returned.")
print(f"Task created: {task_id}")
print(f"Initial status: {create_result.get('status')}")
while True:
task_response = get_task(task_id)
task = task_response.json()
status = str(task.get("status") or "unknown")
normalized_status = status.lower()
progress = task.get("progress")
should_download = normalized_status in SUCCESS_STATUSES or (
normalized_status == "unknown" and is_progress_complete(progress)
)
print(f"Status: {status}, progress: {progress}")
if should_download or normalized_status in TERMINAL_STATUSES:
if not should_download:
print(json.dumps(task, indent=2))
raise SystemExit(1)
content_url = f"{BASE_URL}/v1/videos/{task_id}/content"
output_path = os.path.join(OUTPUT_DIR, f"{task_id}.mp4")
os.makedirs(OUTPUT_DIR, exist_ok=True)
download_video(content_url, output_path)
print(f"Video URL: {task.get('video_url') or ''}")
print(f"Content endpoint: {content_url}")
print(f"Saved to {output_path}")
print(f"File size: {os.path.getsize(output_path)} bytes")
break
time.sleep(POLL_INTERVAL_SECONDS)
JavaScript Code Example
import fs from "fs";
import path from "path";
const model = "happyhorse-1.0";
const prompt = "A miniature city built from cardboard and bottle caps comes alive at night. A tiny cardboard train rolls through the streets while warm lights glow from paper windows, physically realistic motion, detailed tabletop cinematography.";
const seconds = "3";
const size = "1280x720";
const api_key = process.env.COMETAPI_KEY;
const base_url = "https://api.cometapi.com";
const output_dir = "./output";
const poll_interval_ms = 10_000;
const retry_delay_ms = 5_000;
const max_create_attempts = 5;
const terminal_statuses = new Set(["completed", "failed", "error", "success"]);
const success_statuses = new Set(["completed", "success"]);
if (!api_key) {
console.log("Set COMETAPI_KEY before running this example.");
process.exit(0);
}
function is_progress_complete(progress) {
if (typeof progress === "number") {
return progress >= 100;
}
if (typeof progress === "string") {
const numeric = Number(progress.replace(/%$/, ""));
return Number.isFinite(numeric) && numeric >= 100;
}
return false;
}
function is_transient_status(status) {
return status === 429 || status >= 500;
}
async function sleep(ms) {
await new Promise((resolve) => setTimeout(resolve, ms));
}
async function fetch_with_retry(url, options, attempts, label) {
for (let attempt = 1; attempt <= attempts; attempt += 1) {
try {
const response = await fetch(url, options);
if (response.ok) {
return response;
}
if (!is_transient_status(response.status) || attempt === attempts) {
return response;
}
console.log(`${label} returned ${response.status}, retrying...`);
} catch (error) {
if (attempt === attempts) {
throw error;
}
console.log(`${label} failed: ${error.message}, retrying...`);
}
await sleep(retry_delay_ms);
}
throw new Error(`${label} failed`);
}
async function fetch_status(task_id) {
while (true) {
try {
const response = await fetch(`${base_url}/v1/videos/${task_id}`, { headers });
if (response.ok) {
return response;
}
if (!is_transient_status(response.status)) {
return response;
}
console.log(`Status request returned ${response.status}, retrying...`);
} catch (error) {
console.log(`Status request failed: ${error.message}, retrying...`);
}
await sleep(retry_delay_ms);
}
}
async function download_video(content_url, output_path) {
while (true) {
try {
const response = await fetch(content_url, { headers });
if (response.ok) {
const video_buffer = Buffer.from(await response.arrayBuffer());
fs.writeFileSync(output_path, video_buffer);
return;
}
if (!is_transient_status(response.status)) {
console.log(await response.text());
process.exit(1);
}
console.log(`Content request returned ${response.status}, retrying...`);
} catch (error) {
console.log(`Content request failed: ${error.message}, retrying...`);
}
await sleep(retry_delay_ms);
}
}
const form = new FormData();
form.set("model", model);
form.set("prompt", prompt);
form.set("seconds", seconds);
form.set("size", size);
const headers = { Authorization: `Bearer ${api_key}` };
const create_response = await fetch_with_retry(`${base_url}/v1/videos`, {
method: "POST",
headers,
body: form,
}, max_create_attempts, "Create request");
if (!create_response.ok) {
console.log(await create_response.text());
process.exit(1);
}
const create_result = await create_response.json();
const task_id = create_result.id || create_result.task_id;
if (!task_id) {
console.log(JSON.stringify(create_result, null, 2));
process.exit(1);
}
console.log(`Task created: ${task_id}`);
console.log(`Initial status: ${create_result.status}`);
while (true) {
const task_response = await fetch_status(task_id);
if (!task_response.ok) {
console.log(await task_response.text());
process.exit(1);
}
const task = await task_response.json();
const status = String(task.status || "unknown");
const normalized_status = status.toLowerCase();
const progress = task.progress;
const should_download = success_statuses.has(normalized_status) || (
normalized_status === "unknown" && is_progress_complete(progress)
);
console.log(`Status: ${status}, progress: ${progress}`);
if (should_download || terminal_statuses.has(normalized_status)) {
if (!should_download) {
console.log(JSON.stringify(task, null, 2));
process.exit(1);
}
const content_url = `${base_url}/v1/videos/${task_id}/content`;
const output_path = path.join(output_dir, `${task_id}.mp4`);
fs.mkdirSync(output_dir, { recursive: true });
await download_video(content_url, output_path);
console.log(`Video URL: ${task.video_url || ""}`);
console.log(`Content endpoint: ${content_url}`);
console.log(`Saved to ${output_path}`);
console.log(`File size: ${fs.statSync(output_path).size} bytes`);
break;
}
await sleep(poll_interval_ms);
}
Curl Code Example
#!/bin/bash
set -euo pipefail
if [[ -z "${COMETAPI_KEY:-}" ]]; then
echo "Set COMETAPI_KEY before running this example."
exit 0
fi
MODEL="happyhorse-1.0"
PROMPT='A miniature city built from cardboard and bottle caps comes alive at night. A tiny cardboard train rolls through the streets while warm lights glow from paper windows, physically realistic motion, detailed tabletop cinematography.'
VIDEO_SECONDS="3"
SIZE="1280x720"
BASE_URL="https://api.cometapi.com"
OUTPUT_DIR="./output"
POLL_INTERVAL_SECONDS=10
RETRY_DELAY_SECONDS=5
MAX_CREATE_ATTEMPTS=5
is_progress_complete() {
local progress="$1"
local normalized="${progress%%%}"
if [[ -z "$normalized" ]]; then
return 1
fi
[[ "$normalized" =~ ^[0-9]+([.][0-9]+)?$ ]] || return 1
awk -v value="$normalized" 'BEGIN { exit !(value >= 100) }'
}
is_transient_status() {
local status_code="$1"
[[ "$status_code" == "429" || "$status_code" =~ ^5 ]]
}
create_task() {
local attempt=1
while (( attempt <= MAX_CREATE_ATTEMPTS )); do
local response
local status_code
if ! response=$(curl -sS -w $'
%{http_code}' "${BASE_URL}/v1/videos" -H "Authorization: Bearer $COMETAPI_KEY" -F "model=${MODEL}" -F "prompt=${PROMPT}" -F "seconds=${VIDEO_SECONDS}" -F "size=${SIZE}"); then
if (( attempt == MAX_CREATE_ATTEMPTS )); then
return 1
fi
echo "Create request failed, retrying..."
sleep "$RETRY_DELAY_SECONDS"
(( attempt += 1 ))
continue
fi
status_code=$(echo "$response" | tail -n 1)
CREATE_RESPONSE=$(echo "$response" | sed '$d')
if [[ "$status_code" =~ ^2 ]]; then
return 0
fi
if is_transient_status "$status_code" && (( attempt < MAX_CREATE_ATTEMPTS )); then
echo "Create request returned ${status_code}, retrying..."
sleep "$RETRY_DELAY_SECONDS"
(( attempt += 1 ))
continue
fi
echo "$CREATE_RESPONSE"
return 1
done
}
get_task() {
local task_id="$1"
while true; do
local response
local status_code
if ! response=$(curl -sS -w $'
%{http_code}' "${BASE_URL}/v1/videos/${task_id}" -H "Authorization: Bearer $COMETAPI_KEY"); then
echo "Status request failed, retrying..."
sleep "$RETRY_DELAY_SECONDS"
continue
fi
status_code=$(echo "$response" | tail -n 1)
TASK_RESPONSE=$(echo "$response" | sed '$d')
if [[ "$status_code" =~ ^2 ]]; then
return 0
fi
if is_transient_status "$status_code"; then
echo "Status request returned ${status_code}, retrying..."
sleep "$RETRY_DELAY_SECONDS"
continue
fi
echo "$TASK_RESPONSE"
return 1
done
}
download_video() {
local content_url="$1"
local output_path="$2"
while true; do
if curl -fsS "$content_url" -H "Authorization: Bearer $COMETAPI_KEY" -o "$output_path"; then
if [[ -s "$output_path" ]]; then
return 0
fi
echo "Content download was empty, retrying..."
else
echo "Content request failed, retrying..."
fi
sleep "$RETRY_DELAY_SECONDS"
done
}
create_task
TASK_ID=$(echo "$CREATE_RESPONSE" | jq -r '.id // .task_id // empty')
if [[ -z "$TASK_ID" ]]; then
echo "$CREATE_RESPONSE" | jq .
echo "No task id returned."
exit 1
fi
echo "Task created: $TASK_ID"
echo "Initial status: $(echo "$CREATE_RESPONSE" | jq -r '.status // empty')"
while true; do
get_task "$TASK_ID"
STATUS=$(echo "$TASK_RESPONSE" | jq -r '.status // empty')
NORMALIZED_STATUS=$(echo "$STATUS" | tr '[:upper:]' '[:lower:]')
PROGRESS=$(echo "$TASK_RESPONSE" | jq -r '.progress // empty')
SHOULD_DOWNLOAD=0
if [[ "$NORMALIZED_STATUS" == "completed" || "$NORMALIZED_STATUS" == "success" ]]; then
SHOULD_DOWNLOAD=1
elif [[ "$NORMALIZED_STATUS" == "unknown" ]] && is_progress_complete "$PROGRESS"; then
SHOULD_DOWNLOAD=1
fi
echo "Status: ${STATUS}, progress: ${PROGRESS}"
if [[ "$SHOULD_DOWNLOAD" == "1" || "$NORMALIZED_STATUS" == "failed" || "$NORMALIZED_STATUS" == "error" ]]; then
if [[ "$SHOULD_DOWNLOAD" != "1" ]]; then
echo "$TASK_RESPONSE" | jq .
exit 1
fi
VIDEO_URL=$(echo "$TASK_RESPONSE" | jq -r '.video_url // empty')
CONTENT_URL="${BASE_URL}/v1/videos/${TASK_ID}/content"
OUTPUT_PATH="${OUTPUT_DIR}/${TASK_ID}.mp4"
mkdir -p "$OUTPUT_DIR"
download_video "$CONTENT_URL" "$OUTPUT_PATH"
echo "Video URL: ${VIDEO_URL}"
echo "Content endpoint: ${CONTENT_URL}"
echo "Saved to ${OUTPUT_PATH}"
echo "File size: $(wc -c < "$OUTPUT_PATH" | tr -d ' ') bytes"
break
fi
sleep "$POLL_INTERVAL_SECONDS"
done