Uygulamanıza video üretimi eklemek, görüntü üretimi eklemekle aynı değildir. API çağrısı anında döner — ancak video henüz hazır değildir. Bir görev kimliği (task ID) alırsınız ve hazır olana kadar “bitti mi?” diye sormaya devam etmeniz gerekir.
Çoğu geliştirici ilk kez bir video API’sini çağırdığında, gövdede bir video URL’si bekler, bunun yerine bir görev kimliği alır. Bu rehber tüm akışı adım adım anlatır: görevi göndermek, sonuçları sorgulamak, hataları ele almak ve URL süresi dolmadan çıktıyı depolamak.
Ne oluşturacaksınız
Bir backend hizmeti: bir metin istemi veya görüntü alır, bir video üretim görevini gönderir, tamamlanana kadar sorgular ve nihai video URL’sini döndürür. Dört modelle çalışacaksınız — Veo 3 Fast, Sora 2, Kling Video ve Runway — hepsi tek bir API anahtarıyla.
Önkoşullar:
- Python 3.8+ veya Node.js 18+
- Bir CometAPI anahtarı
- REST API’lerine temel düzeyde aşinalık
Video üretiminin neden farklı olduğunu anlayın
Görüntü üretiminde bir istek gönderir ve aynı yanıtta görüntüyü geri alırsınız. Video üretimi ise eşzamansız bir görev kuyruğu kullanır:
- Üretim isteğini gönderin → size bir
task_iddöner - Her birkaç saniyede bir durum uç noktasını sorgulayın
- Durum bir terminal duruma ulaştığında video URL’sini alırsınız
- Videoyu indirin ve saklayın — URL geçicidir
Video üretimini görüntü üretimi gibi ele alır ve ilk yanıtta videonun gelmesini beklerseniz, isteğiniz her seferinde zaman aşımına uğrar.
Üretim ortamında bu sorgulama döngüsü, istek işleyicide değil bir arka plan işçisi (Celery, Bull veya benzeri) içinde çalışmalıdır. Aşağıdaki örnekler eşzamanlı sorgulama kullanır — betikler ve prototipler için uygundur, ancak eşzamanlı kullanıcıları idare etmek için uygun değildir.
Bir model seçin
| Model | Sağlayıcı | Maksimum süre | Fiyat (CometAPI üzerinden) | En uygun kullanım |
|---|---|---|---|---|
| Veo 3 Fast | 8 sec | $0.05/sec | Hızlı prototipleme, sosyal klipler | |
| Sora 2 | OpenAI (CometAPI model ID’si) | ~10 sec | $0.08/sec | Yüksek kaliteli yaratıcı kısa videolar |
| Kling Video | Kuaishou | 10 sec | $0.13–$2.64/task | Pazarlama içeriği, ayrıntılı kontrol |
| Runway Gen-3A Turbo | Runway | 5 veya 10 sec | $0.32/task | Görüntüden videoya, ticari içerik |
Kaynak**: CometAPI model sayfaları, Mayıs 2026. Not: "Sora 2" CometAPI’nin model kimliğidir — temel model ayrıntıları için onların model sayfasına bakın.
- Veo 3 Fast hem metinden videoya hem de görüntüden videoya destekler. Saniye başına en ucuz, iyi bir başlangıç noktası.
- Sora 2 videoyla birlikte sesi yerel olarak üretir — ayrı bir TTS adımına gerek kalmadan diyalog, ortam sesi ve efektler.
- Kling Video
negative_prompt,cfg_scale, kamera hareketi ayarları vepromodu sunar. Dördü arasında en fazla kontrolü sağlar. - Runway CometAPI üzerinden yalnızca görüntüden videoya çalışır. Sabit bir görüntü ve bir hareket açıklaması verin, onu canlandırsın.
Bir Veo görevi gönderin
Veo multipart/form-data kullanır. Python requests’te doğru göndermek için files= kullanın — data=dict application/x-www-form-urlencoded gönderir, bu aynı şey değildir:
import requestsimport osfrom dotenv import load_dotenvload_dotenv()def submit_veo_task(prompt: str, size: str = "16x9") -> str: """Veo 3 Fast metinden videoya bir görev gönderin. task_id döndürür.""" api_key = os.getenv("COMETAPI_KEY") if not api_key: raise ValueError("COMETAPI_KEY ortam değişkeni ayarlanmamış") response = requests.post( "https://api.cometapi.com/v1/videos", headers={"Authorization": f"Bearer {api_key}"}, files={ "prompt": (None, prompt), "model": (None, "veo3-fast"), "size": (None, size) }, timeout=30 ) response.raise_for_status() return response.json()["id"]task_id = submit_veo_task("Rüzgarlı bir öğleden sonra bir buğday tarlası üzerinde süzülen bir kâğıt uçurtma")print(f"Görev gönderildi: {task_id}")
Sonucu sorgulayın
import timedef poll_veo_task(task_id: str, interval: int = 10, max_wait: int = 600) -> str: """Veo görevi tamamlanana kadar sorgular. Video URL’sini döndürür.""" api_key = os.getenv("COMETAPI_KEY") if not api_key: raise ValueError("COMETAPI_KEY ortam değişkeni ayarlanmamış") headers = {"Authorization": f"Bearer {api_key}"} url = f"https://api.cometapi.com/v1/videos/{task_id}" elapsed = 0 while elapsed < max_wait: response = requests.get(url, headers=headers, timeout=30) response.raise_for_status() result = response.json() status = result.get("status") if status == "succeeded": return result["output"][0] elif status in ("failed", "cancelled"): raise RuntimeError( f"Görev {task_id} şu durumla başarısız oldu '{status}': " f"{result.get('error', 'hata ayrıntısı döndürülmedi')}" ) time.sleep(interval) elapsed += interval raise TimeoutError(f"Görev {task_id}, {max_wait} saniye içinde tamamlanmadı")video_url = poll_veo_task(task_id)print(f"Video hazır: {video_url}")
Daha fazla kontrol için Kling Video kullanın
Kling farklı bir uç nokta yapısı kullanır ve JSON ile çalışır. Kling’in terminal durum dizesinin "succeed" ( "succeeded" değil) olduğunu unutmayın — bu, API’nin gerçek yanıt formatıyla eşleşir:
def submit_kling_task(prompt: str, duration: str = "5", mode: str = "std") -> str: """Kling metinden videoya bir görev gönderir. task_id döndürür.""" api_key = os.getenv("COMETAPI_KEY") if not api_key: raise ValueError("COMETAPI_KEY ortam değişkeni ayarlanmamış") response = requests.post( "https://api.cometapi.com/kling/v1/videos/text2video", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" }, json={ "model_name": "kling-v1-6", "prompt": prompt, "negative_prompt": "blurry, low quality, watermark", "cfg_scale": 0.5, "mode": mode, # "std" veya "pro" "aspect_ratio": "16:9", "duration": duration # "5" veya "10" }, timeout=30 ) response.raise_for_status() return response.json()["data"]["task_id"]def poll_kling_task(task_id: str, interval: int = 10, max_wait: int = 600) -> str: """Kling görevini tamamlanana kadar sorgular. Video URL’sini döndürür.""" api_key = os.getenv("COMETAPI_KEY") if not api_key: raise ValueError("COMETAPI_KEY ortam değişkeni ayarlanmamış") headers = {"Authorization": f"Bearer {api_key}"} url = f"https://api.cometapi.com/kling/v1/videos/text2video/{task_id}" elapsed = 0 while elapsed < max_wait: response = requests.get(url, headers=headers, timeout=30) response.raise_for_status() result = response.json() status = result["data"]["task_status"] if status == "succeed": # Kling "succeed" kullanır, "succeeded" değil return result["data"]["task_result"]["videos"][0]["url"] elif status == "failed": error_detail = result.get("data", {}).get("task_result", "no detail") raise RuntimeError( f"Kling görevi {task_id} başarısız: {error_detail}" ) time.sleep(interval) elapsed += interval raise TimeoutError(f"Kling görevi {task_id}, {max_wait}s sonra zaman aşımına uğradı")
Kaynak**: CometAPI Kling Video dokümanları
Runway ile statik bir görüntüyü canlandırın
Runway yalnızca görüntüden videoya çalışır. Ayrıca ekstra bir başlık (X-Runway-Version) gerektirir:
def submit_runway_task(image_url: str, motion_prompt: str, duration: int = 5) -> str: """Runway görüntüden videoya bir görev gönderir. task_id döndürür.""" api_key = os.getenv("COMETAPI_KEY") if not api_key: raise ValueError("COMETAPI_KEY ortam değişkeni ayarlanmamış") response = requests.post( "https://api.cometapi.com/runwayml/v1/image_to_video", headers={ "Authorization": f"Bearer {api_key}", "X-Runway-Version": "2024-11-06", "Content-Type": "application/json" }, json={ "model": "gen3a_turbo", "promptImage": image_url, # stabil bir HTTPS URL olmalı "promptText": motion_prompt, "duration": duration, "ratio": "1280:720", "watermark": False }, timeout=30 ) response.raise_for_status() return response.json()["id"]def poll_runway_task(task_id: str, interval: int = 5, max_wait: int = 600) -> str: """Runway görevini sorgular. Tamamlandığında video URL’sini döndürür.""" api_key = os.getenv("COMETAPI_KEY") if not api_key: raise ValueError("COMETAPI_KEY ortam değişkeni ayarlanmamış") headers = { "Authorization": f"Bearer {api_key}", "X-Runway-Version": "2024-11-06" } url = f"https://api.cometapi.com/runwayml/v1/tasks/{task_id}" elapsed = 0 while elapsed < max_wait: response = requests.get(url, headers=headers, timeout=30) response.raise_for_status() result = response.json() status = result.get("status") if status == "task_not_exist": # CometAPI'ye özgü: görev hâlâ başlatılıyor, birkaç saniye sonra yeniden dene time.sleep(interval) elapsed += interval continue elif status == "succeeded": return result["output"][0] elif status in ("failed", "cancelled"): raise RuntimeError(f"Runway görevi {task_id} başarısız: {result.get('error', 'ayrıntı yok')}") time.sleep(interval) elapsed += interval raise TimeoutError(f"Runway görevi {task_id}, {max_wait}s sonra zaman aşımına uğradı")
Kaynak**: CometAPI Runway dokümanları
URL’nin süresi dolmadan videoyu kaydedin
Üretim API’lerinden gelen video URL’leri geçicidir. Dosyayı hemen indirin ve kontrolünüzde bir yerde saklayın:
import requestsimport pathlibdef download_video(url: str, output_path: str) -> None: """Akış kullanarak videoyu URL’den yerel dosyaya indirir.""" out = pathlib.Path(output_path) if out.parent != pathlib.Path("."): out.parent.mkdir(parents=True, exist_ok=True) with requests.get(url, stream=True, timeout=60) as r: r.raise_for_status() with open(out, "wb") as f: for chunk in r.iter_content(chunk_size=8192): f.write(chunk) print(f"{output_path} konumuna kaydedildi")# Tüm akıştask_id = submit_veo_task("Bir şehir silüeti üzerinde hareket eden bulutların hızlandırılmış çekimi")video_url = poll_veo_task(task_id)download_video(video_url, "output/city_timelapse.mp4")
Üretimde, yerel dosyaya yazmayı S3, Cloudflare R2 veya seçtiğiniz başka bir depolamaya yüklemeyle değiştirin. Akış deseni aynı kalır — tüm videoyu belleğe almak yerine baytları doğrudan yönlendirin.
Hataları ele alın
| Belirti | Olası neden | Çözüm |
|---|---|---|
| Görev 10+ dk boyunca queued durumunda takılı kaldı | Sunucu yükü veya model kullanılamıyor | Farklı bir modelle yeniden deneyin |
| İlk Runway sorgusunda task_not_exist | Görev hâlâ başlatılıyor | 5 sn bekleyip yeniden deneyin — CometAPI’de belgelidir |
| Hata mesajı olmadan başarısız oldu | İstem (prompt) içerik filtresini tetikledi | İstemi yeniden ifade edin |
| Video URL’si 403 döndürüyor | URL indirilmeden önce süresi doldu | URL’yi alır almaz indirin |
| 10 dk sonra zaman aşımı | Üretim çok uzun sürdü | max_wait’i artırın veya Veo 3 Fast’e geçin |
| Kling "succeed" döndürüyor, "succeeded" değil | Kling’in API’si standart dışı durum dizesi kullanıyor | Bu doğrudur — yukarıdaki Kling sorgulama koduna bakın |
Kaynak: CometAPI video üretim dokümanları
Node.js sürümü
Node.js 18+ yerleşik olarak fetch ve FormData içerir. Bu örnek dört modeli de kapsar:
// Node.js 18+ — ek paket gerekmezconst API_KEY = process.env.COMETAPI_KEY;if (!API_KEY) throw new Error('COMETAPI_KEY ayarlı değil');// --- Veo 3 Fast ---async function submitVeoTask(prompt, size = '16x9') { const form = new FormData(); form.append('prompt', prompt); form.append('model', 'veo3-fast'); form.append('size', size); const res = await fetch('https://api.cometapi.com/v1/videos', { method: 'POST', headers: { 'Authorization': `Bearer ${API_KEY}` }, body: form }); if (!res.ok) throw new Error(`Veo gönderimi başarısız: ${res.status}`); return (await res.json()).id;}async function pollVeoTask(taskId, intervalMs = 10000, maxWaitMs = 600000) { let elapsed = 0; while (elapsed < maxWaitMs) { const res = await fetch(`https://api.cometapi.com/v1/videos/${taskId}`, { headers: { 'Authorization': `Bearer ${API_KEY}` } }); if (!res.ok) throw new Error(`Sorgulama başarısız: ${res.status}`); const result = await res.json(); if (result.status === 'succeeded') return result.output[0]; if (['failed', 'cancelled'].includes(result.status)) { throw new Error(`Görev ${taskId} başarısız: ${result.error ?? 'ayrıntı yok'}`); } await new Promise(r => setTimeout(r, intervalMs)); elapsed += intervalMs; } throw new Error(`Görev ${taskId} zaman aşımına uğradı`);}// --- Kling Video ---async function submitKlingTask(prompt, duration = '5', mode = 'std') { const res = await fetch('https://api.cometapi.com/kling/v1/videos/text2video', { method: 'POST', headers: { 'Authorization': `Bearer ${API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ model_name: 'kling-v1-6', prompt, negative_prompt: 'blurry, low quality, watermark', cfg_scale: 0.5, mode, aspect_ratio: '16:9', duration }) }); if (!res.ok) throw new Error(`Kling gönderimi başarısız: ${res.status}`); return (await res.json()).data.task_id;}async function pollKlingTask(taskId, intervalMs = 10000, maxWaitMs = 600000) { let elapsed = 0; while (elapsed < maxWaitMs) { const res = await fetch( `https://api.cometapi.com/kling/v1/videos/text2video/${taskId}`, { headers: { 'Authorization': `Bearer ${API_KEY}` } } ); if (!res.ok) throw new Error(`Kling sorgulaması başarısız: ${res.status}`); const result = await res.json(); const status = result.data.task_status; if (status === 'succeed') return result.data.task_result.videos[0].url; if (status === 'failed') { throw new Error(`Kling görevi ${taskId} başarısız: ${JSON.stringify(result.data.task_result ?? 'ayrıntı yok')}`); } await new Promise(r => setTimeout(r, intervalMs)); elapsed += intervalMs; } throw new Error(`Kling görevi ${taskId} zaman aşımına uğradı`);}// --- Runway (görüntüden videoya) ---async function submitRunwayTask(imageUrl, motionPrompt, duration = 5) { const res = await fetch('https://api.cometapi.com/runwayml/v1/image_to_video', { method: 'POST', headers: { 'Authorization': `Bearer ${API_KEY}`, 'X-Runway-Version': '2024-11-06', 'Content-Type': 'application/json' }, body: JSON.stringify({ model: 'gen3a_turbo', promptImage: imageUrl, promptText: motionPrompt, duration, ratio: '1280:720', watermark: false }) }); if (!res.ok) throw new Error(`Runway gönderimi başarısız: ${res.status}`); return (await res.json()).id;}async function pollRunwayTask(taskId, intervalMs = 5000, maxWaitMs = 600000) { let elapsed = 0; while (elapsed < maxWaitMs) { const res = await fetch( `https://api.cometapi.com/runwayml/v1/tasks/${taskId}`, { headers: { 'Authorization': `Bearer ${API_KEY}`, 'X-Runway-Version': '2024-11-06' } } ); if (!res.ok) throw new Error(`Runway sorgulaması başarısız: ${res.status}`); const result = await res.json(); const status = result.status; if (status === 'task_not_exist') { // CometAPI’ye özgü: görev hâlâ başlatılıyor await new Promise(r => setTimeout(r, intervalMs)); elapsed += intervalMs; continue; } if (status === 'succeeded') return result.output[0]; if (['failed', 'cancelled'].includes(status)) { throw new Error(`Runway görevi ${taskId} başarısız: ${result.error ?? 'ayrıntı yok'}`); } await new Promise(r => setTimeout(r, intervalMs)); elapsed += intervalMs; } throw new Error(`Runway görevi ${taskId} zaman aşımına uğradı`);}// Kullanım örneğiconst taskId = await submitVeoTask('Bir buğday tarlası üzerinde süzülen bir kâğıt uçurtma');const videoUrl = await pollVeoTask(taskId);console.log('Video hazır:', videoUrl);
Sırada ne var
Artık dört video modeli için çalışan kodunuz, hataları ele alan bir sorgulama döngünüz ve üretilen içeriği kaybetmemenizi sağlayan bir indirme adımınız var.
Geliştiricilerin bir sonraki karşılaştığı sorun: tek bir modeli sabitlemişlerdir ve daha ucuz veya daha hızlı bir seçeneğe geçmek, birden çok dosyaya dokunmayı gerektirir. Bir sonraki makale, kodunuzu yeniden yazmadan istekleri modeller arasında nasıl yönlendireceğinizi anlatır.
Sonraki: Kodunuzu Yeniden Yazmadan Yapay Zeka Modelleri Arasında Nasıl Geçiş Yaparsınız
SSS
S: API yanıtında neden bir video yerine görev kimliği alıyorum?
Video üretimi eşzamansızdır — Veo, Sora, Kling ve Runway gibi modeller render için 2–5 dakika alır. İsteğiniz zaman aşımına uğramasın diye API hemen bir görev kimliği döndürür. Görev bir terminal duruma (succeeded, succeed, failed) ulaşana kadar ayrı bir durum uç noktasını sorgularsınız.
S: Üretilen bir video URL’si ne kadar süre geçerli kalır?
Video üretim API’lerinden gelen URL’ler geçicidir. URL’yi aldıktan hemen sonra dosyayı indirin ve kendi depolamanızda (S3, Cloudflare R2, vb.) saklayın. URL’yi saklayıp saatler sonra çalışmasını beklemeyin.
S: Veo 3 Fast ile Kling Video arasındaki fark nedir?
Veo 3 Fast daha ucuz ($0.05/sec), daha hızlı ve çağırması daha basittir. Kling Video daha fazla kontrol sunar: negative_prompt, cfg_scale, kamera hareketi ayarları ve pro kalite modu. Çıktıyı ince ayarlamanız gerekiyorsa Kling’i kullanın. Hız ve düşük maliyet gerekiyorsa Veo 3 Fast’i kullanın.
S: Metin istemi yerine bir görüntüden video üretebilir miyim?
Evet. Veo, bir input_reference dosyası geçerek görüntüden videoya destekler. Kling, image parametresi (URL veya base64) ile /kling/v1/videos/image2video uç noktası üzerinden destekler. Runway yalnızca görüntüden videoya çalışır — CometAPI üzerinden metinle tek başına istem kabul etmez.
S: Runway neden ilk sorgulamada task_not_exist döndürüyor?
Bu, CometAPI’de belgelenmiş bir davranıştır — görev arka uçta hâlâ başlatılıyor. Birkaç saniye bekleyip yeniden deneyin. Bu bir hata değildir. Yukarıdaki sorgulama kodu bunu otomatik olarak ele alır.
S: Kling neden "succeed" yerine "succeeded" kullanıyor?
Bu, Kling’in gerçek API yanıt formatıdır. Yazım hatası değildir. Veo ve Runway "succeeded" kullanır — Kling "succeed" kullanır. Birleştirilmiş bir sorgulama sarmalayıcısı kuruyorsanız her iki dizeyi de ele almanız gerekir.
S: Eşzamanlı sorgulama döngüsü bir web sunucusunda kullanmak için güvenli midir?
Hayır. Bu rehberdeki sorgulama döngüsü iş parçacığını dakikalarca bloke eder. Eşzamanlı kullanıcıların olduğu gerçek bir web hizmetinde sorgulamayı bir arka plan işçisinde (Python için Celery, Node.js için Bull) çalıştırın. Görevi istek işleyicide gönderin, görev kimliğini istemciye döndürün ve video hazır olduğunda istemciyi işçi bildirsin.
