import os import requests import json import base64 import time from flask import Flask, request, jsonify, send_file app = Flask(__name__) # ===== SECRETS ===== AGNES_API_KEY = os.environ.get("AGNES_API_KEY") if not AGNES_API_KEY: print("⚠️ AGNES_API_KEY not set! Get from agnes-ai.com") # ===== AGNES AI API ===== AGNES_BASE = "https://apihub.agnes-ai.com/v1" def get_valid_num_frames(duration): valid_values = [9, 17, 25, 33, 41, 49, 57, 65, 73, 81, 89, 97, 105, 113, 121] target = duration * 8 closest = min(valid_values, key=lambda x: abs(x - target)) return closest def generate_video_agnes(prompt, duration=20): headers = { "Authorization": f"Bearer {AGNES_API_KEY}", "Content-Type": "application/json" } num_frames = get_valid_num_frames(duration) print(f"🎬 Duration: {duration}s → {num_frames} frames") # Try with model models = ["agnes-video-v2.0", "agnes-video-2.0", "video", "agnes-video"] for model in models: try: payload = { "model": model, "prompt": prompt, "num_frames": num_frames, "frame_rate": 8, "width": 1152, "height": 768, "guidance_scale": 7.5, "negative_prompt": "low quality, blurry, distorted, ugly" } response = requests.post(f"{AGNES_BASE}/videos", json=payload, headers=headers, timeout=30) if response.status_code == 200: data = response.json() video_id = data.get("video_id") or data.get("id") if video_id: print(f"✅ Task created! video_id: {video_id}") return poll_for_video(video_id, headers) video_url = data.get("video_url") or data.get("url") or data.get("output") if video_url: return video_url elif response.status_code == 400: error = response.json() if "model" in str(error).lower(): continue except: continue # Try without model try: payload = { "prompt": prompt, "num_frames": num_frames, "frame_rate": 8, "width": 1152, "height": 768, "guidance_scale": 7.5, "negative_prompt": "low quality, blurry, distorted, ugly" } response = requests.post(f"{AGNES_BASE}/videos", json=payload, headers=headers, timeout=30) if response.status_code == 200: data = response.json() video_id = data.get("video_id") or data.get("id") if video_id: print("✅ Task created without model!") return poll_for_video(video_id, headers) video_url = data.get("video_url") or data.get("url") or data.get("output") if video_url: return video_url except: pass raise Exception("All attempts failed") def poll_for_video(video_id, headers): for attempt in range(40): time.sleep(3) print(f"⏳ Polling attempt {attempt + 1}/40...") poll_response = requests.get( f"{AGNES_BASE}/agnesapi?video_id={video_id}", headers=headers, timeout=30 ) if poll_response.status_code == 200: result = poll_response.json() status = result.get("status") or result.get("state") if status in ["completed", "succeeded", "done"]: video_url = result.get("video_url") or result.get("url") or result.get("output") if video_url: return video_url if result.get("data") and isinstance(result["data"], list): for item in result["data"]: if isinstance(item, dict) and item.get("url"): return item["url"] raise Exception("No video URL found") elif status in ["failed", "error"]: error_msg = result.get("error") or result.get("message") or "Unknown" raise Exception(f"Video generation failed: {error_msg}") else: print(f"⚠️ Poll failed: {poll_response.status_code}") raise Exception("Video generation timed out") @app.route('/') def index(): return send_file('index.html') @app.route('/generate-video', methods=['POST']) def generate_video(): try: data = request.json prompt = data.get('prompt') duration = int(data.get('duration', 20)) if not prompt: return jsonify({'error': 'Prompt is required'}), 400 if not AGNES_API_KEY: return jsonify({'error': 'AGNES_API_KEY not configured'}), 500 video_url = generate_video_agnes(prompt, duration) return jsonify({ 'success': True, 'video_url': video_url }) except Exception as e: return jsonify({'error': str(e)}), 500 if __name__ == '__main__': app.run(host='0.0.0.0', port=7860, debug=False)