-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapi_client.py
More file actions
179 lines (151 loc) · 5.8 KB
/
api_client.py
File metadata and controls
179 lines (151 loc) · 5.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
"""
Replicate API Client for Video Generation
Handles text-to-video and image-to-video generation using Replicate's cloud API
"""
import os
import logging
import replicate
from pathlib import Path
import requests
from PIL import Image
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class ReplicateAPIClient:
"""Client for Replicate API video generation"""
def __init__(self, api_token=None):
"""
Initialize Replicate API client
Args:
api_token: Replicate API token (if None, reads from env)
"""
self.api_token = api_token or os.getenv('REPLICATE_API_TOKEN')
if self.api_token:
os.environ['REPLICATE_API_TOKEN'] = self.api_token
logger.info("Replicate API client initialized")
else:
logger.warning("No Replicate API token found - API mode disabled")
def is_available(self):
"""Check if API is available"""
return bool(self.api_token)
def generate_text_to_video(
self,
prompt,
negative_prompt="",
num_frames=120,
height=720,
width=1280,
fps=24,
output_path="output.mp4"
):
"""
Generate video from text using Replicate API
Args:
prompt: Text description
negative_prompt: What to avoid
num_frames: Number of frames
height: Video height
width: Video width
fps: Frames per second
output_path: Where to save
Returns:
Path to generated video
"""
if not self.is_available():
raise Exception("Replicate API token not configured")
logger.info(f"Generating text-to-video via API: {prompt}")
try:
# Using Zeroscope v2 XL for text-to-video
output = replicate.run(
"anotherjesse/zeroscope-v2-xl:9f747673945c62801b13b84701c783929c0ee784e4748ec062204894dda1a351",
input={
"prompt": prompt,
"negative_prompt": negative_prompt,
"num_frames": min(num_frames, 120), # API limit
"fps": fps,
"width": width,
"height": height,
"num_inference_steps": 50,
"guidance_scale": 17.5
}
)
# Download the video
if output:
video_url = output if isinstance(output, str) else output[0]
self._download_video(video_url, output_path)
logger.info(f"Video saved to: {output_path}")
return output_path
else:
raise Exception("No output from API")
except Exception as e:
logger.error(f"API error: {str(e)}")
raise
def generate_image_to_video(
self,
image_path,
prompt="",
num_frames=120,
height=720,
width=1280,
fps=24,
output_path="output.mp4"
):
"""
Generate video from image using Replicate API
Args:
image_path: Path to input image
prompt: Optional motion description
num_frames: Number of frames
height: Video height
width: Video width
fps: Frames per second
output_path: Where to save
Returns:
Path to generated video
"""
if not self.is_available():
raise Exception("Replicate API token not configured")
logger.info(f"Generating image-to-video via API from: {image_path}")
try:
# Open and prepare image
with open(image_path, 'rb') as f:
image_file = f
# Using Stable Video Diffusion for image-to-video
output = replicate.run(
"stability-ai/stable-video-diffusion:3f0457e4619daac51203dedb472816fd4af51f3149fa7a9e0b5ffcf1b8172438",
input={
"input_image": image_file,
"cond_aug": 0.02,
"decoding_t": 7,
"video_length": "14_frames_with_svd", # or "25_frames_with_svd_xt"
"sizing_strategy": "maintain_aspect_ratio",
"motion_bucket_id": 127,
"frames_per_second": fps
}
)
# Download the video
if output:
video_url = output if isinstance(output, str) else output[0]
self._download_video(video_url, output_path)
logger.info(f"Video saved to: {output_path}")
return output_path
else:
raise Exception("No output from API")
except Exception as e:
logger.error(f"API error: {str(e)}")
raise
def _download_video(self, url, output_path):
"""Download video from URL to local path"""
try:
logger.info(f"Downloading video from: {url}")
response = requests.get(url, stream=True)
response.raise_for_status()
# Ensure output directory exists
Path(output_path).parent.mkdir(parents=True, exist_ok=True)
# Write video file
with open(output_path, 'wb') as f:
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)
logger.info(f"Video downloaded successfully")
except Exception as e:
logger.error(f"Error downloading video: {str(e)}")
raise