import os import sys import time import argparse from typing import Optional from openai import OpenAI def get_client() -> OpenAI: api_key = "" if not api_key: raise RuntimeError("Не найден OPENAI_API_KEY в переменных окружения") return OpenAI(api_key=api_key) def start_video(prompt: str, model: Optional[str] = None, duration: Optional[int] = None, aspect_ratio: Optional[str] = None, seed: Optional[int] = None): """ Создаёт задачу на генерацию видео. Поля model/duration/aspect_ratio/seed — опциональны и зависят от вашего доступа. """ client = get_client() kwargs = {"prompt": prompt} if model: kwargs["model"] = model if duration is not None: kwargs["duration"] = duration if aspect_ratio: kwargs["aspect_ratio"] = aspect_ratio if seed is not None: kwargs["seed"] = seed # Ваша документация показывает простой вызов client.videos.create(prompt=...) # Ниже мы добавляем опциональные параметры, если они поддерживаются вашим доступом. video = client.videos.create(seconds='12', **kwargs) return video # объект с полем .id def wait_for_video_to_finish(video_id: str, poll_interval: int = 5, timeout: int = 600): """ Ожидает завершения генерации. Возвращает финальный job-объект. """ client = get_client() elapsed = 0 while elapsed < timeout: job = client.videos.retrieve(video_id) status = getattr(job, "status", None) progress = getattr(job, "progress", None) print(f"Status: {status}, {progress}%") if status == "completed": return job if status == "failed": # В разных версиях SDK/бэкенда ошибка может быть в job.error.message или job.error err = None try: err = job.error.message except Exception: err = getattr(job, "error", None) raise RuntimeError(f"Failed to generate the video: {err}") time.sleep(poll_interval) elapsed += poll_interval raise RuntimeError("Polling timed out") def download_video(video_id: str, out_path: Optional[str] = None) -> str: """ Скачивает видео и сохраняет в файл. """ client = get_client() resp = client.videos.download_content(video_id=video_id) video_bytes = resp.read() if not out_path: out_path = f"{video_id}.mp4" with open(out_path, "wb") as f: f.write(video_bytes) return out_path def main(): # parser = argparse.ArgumentParser(description="Генерация видео через Videos API (Sora/Sora 2).") # parser.add_argument("--prompt", required=True, help="Текстовый запрос для видео") # parser.add_argument("--model", default=None, help="Имя модели (например, sora-2)") # parser.add_argument("--duration", type=int, default=None, help="Длительность в секундах (если поддерживается)") # parser.add_argument("--aspect", default=None, help="Соотношение сторон, например 16:9 (если поддерживается)") # parser.add_argument("--seed", type=int, default=None, help="Фиксированный seed (если поддерживается)") # parser.add_argument("--poll-interval", type=int, default=5, help="Интервал опроса статуса, сек") # parser.add_argument("--timeout", type=int, default=600, help="Таймаут ожидания, сек") # parser.add_argument("--out", default=None, help="Путь для сохранения mp4") # # args = parser.parse_args() prompt = ("Двое военных сидят на гаупвахте") try: video = start_video( prompt=prompt, model="sora-2-pro", #duration=8, #aspect_ratio="1280x720", #seed=32 ) video_id = video.id print(f"Started generating video with id {video_id}") wait_for_video_to_finish(video_id, poll_interval=5, timeout=6000) print(f"Saving the video with id {video_id}") out_path = download_video(video_id, out_path=f"/tmp/sora_output_{video_id}.mp4") print(f"Видео сохранено: {out_path}") except KeyboardInterrupt: print("Остановка по Ctrl+C", file=sys.stderr) sys.exit(1) except Exception as e: print(f"Ошибка: {e}", file=sys.stderr) sys.exit(2) if __name__ == "__main__": main()