AkashKumarave commited on
Commit
7dc8355
·
verified ·
1 Parent(s): ae39b5f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +100 -71
app.py CHANGED
@@ -7,34 +7,45 @@ import jwt
7
  import logging
8
  from pathlib import Path
9
 
10
- # Set up logging
11
  logging.basicConfig(level=logging.INFO)
12
  logger = logging.getLogger(__name__)
13
 
14
- # ===== CONFIGURATION =====
15
  ACCESS_KEY_ID = "AFyHfnQATghFdCMyAG3gRPbNY4TNKFGB"
16
  ACCESS_KEY_SECRET = "TTepeLyBterLNM3brYPGmdndBnnyKJBA"
17
- BASE_URL = "https://api-singapore.klingai.com"
18
- CREATE_TASK_URL = f"{BASE_URL}/v1/images/generations"
19
 
20
- # ===== UTILITY FUNCTIONS =====
21
  def generate_jwt_token():
22
  """Generate JWT token for API authentication"""
23
  payload = {
24
  "iss": ACCESS_KEY_ID,
25
- "exp": int(time.time()) + 1800, # Expires in 30 mins
26
- "nbf": int(time.time()) - 5 # Not before 5 seconds ago
27
  }
28
- return jwt.encode(payload, ACCESS_KEY_SECRET, algorithm="HS256")
 
 
 
 
 
29
 
 
30
  def validate_image(image_path):
31
- """Check image meets API requirements"""
32
  try:
33
- img_size = os.path.getsize(image_path) / 1024 / 1024 # MB
34
- if img_size > 10:
 
35
  return False, "Image too large (max 10MB)"
36
 
37
- # Add actual dimension check if possible (requires PIL)
 
 
 
 
38
  return True, ""
39
  except Exception as e:
40
  return False, f"Image validation error: {str(e)}"
@@ -42,137 +53,156 @@ def validate_image(image_path):
42
  # ===== API FUNCTIONS =====
43
  def create_image_task(image_base64, prompt):
44
  """Create image generation task"""
 
 
 
 
45
  headers = {
46
- "Authorization": f"Bearer {generate_jwt_token()}",
47
  "Content-Type": "application/json"
48
  }
49
 
50
  payload = {
51
- "model_name": "kling-v2", # Best for image-to-image
52
- "prompt": prompt,
53
  "image": image_base64,
54
- "resolution": "2k",
55
- "n": 1,
56
- "aspect_ratio": "1:1"
57
  }
58
 
59
  try:
60
- response = requests.post(CREATE_TASK_URL, json=payload, headers=headers)
 
 
 
 
 
61
  response.raise_for_status()
62
- return response.json()
63
  except requests.exceptions.RequestException as e:
64
  logger.error(f"API request failed: {str(e)}")
65
- return None
 
 
66
 
67
- def get_task_result(task_id):
68
- """Retrieve task results"""
69
- headers = {"Authorization": f"Bearer {generate_jwt_token()}"}
70
- task_url = f"{BASE_URL}/v1/images/generations/{task_id}"
 
 
 
 
71
 
72
  try:
73
- response = requests.get(task_url, headers=headers)
74
  response.raise_for_status()
75
- return response.json()
76
  except requests.exceptions.RequestException as e:
77
- logger.error(f"Task status check failed: {str(e)}")
78
- return None
79
 
80
  # ===== MAIN PROCESSING =====
81
- def generate_image(image_path, prompt=""):
82
- """Handle end-to-end image generation"""
83
- # Validate input image
84
  is_valid, error_msg = validate_image(image_path)
85
  if not is_valid:
86
  return None, error_msg
87
-
88
- # Prepare image data
89
  try:
90
  with open(image_path, "rb") as img_file:
91
- image_base64 = base64.b64encode(img_file.read()).decode("utf-8")
92
  except Exception as e:
93
- return None, f"Image processing error: {str(e)}"
94
-
95
- # Create generation task
96
- task_response = create_image_task(image_base64, prompt or "Transform into a vibrant cartoon style")
97
- if not task_response or task_response.get("code") != 0:
98
- return None, "Failed to create task"
99
-
 
 
 
100
  task_id = task_response["data"]["task_id"]
101
- logger.info(f"Created task: {task_id}")
102
-
103
- # Poll for results (max 10 mins)
104
  for _ in range(60):
105
- task_data = get_task_result(task_id)
106
- if not task_data:
107
- time.sleep(5)
108
- continue
109
 
110
  status = task_data["data"]["task_status"]
111
 
112
  if status == "succeed":
113
  image_url = task_data["data"]["task_result"]["images"][0]["url"]
114
  try:
115
- img_data = requests.get(image_url).content
 
116
  output_path = Path(f"/tmp/kling_output_{task_id}.png")
117
  with open(output_path, "wb") as f:
118
- f.write(img_data)
119
  return str(output_path), None
120
  except Exception as e:
121
- return None, f"Failed to save image: {str(e)}"
122
 
123
  elif status in ("failed", "canceled"):
124
- return None, f"Task failed: {task_data.get('task_status_msg', 'Unknown error')}"
 
125
 
126
  time.sleep(10)
127
 
128
  return None, "Task timed out after 10 minutes"
129
 
130
  # ===== GRADIO INTERFACE =====
131
- def chatbot_interface(image, prompt):
132
  if not image:
133
  return None, None, "Please upload an image first"
134
 
135
  output_path, error = generate_image(image, prompt)
136
  if error:
 
137
  return None, None, error
138
 
139
- return output_path, output_path, "Generation successful!"
140
 
141
- with gr.Blocks(title="Kling AI Image Transformer") as app:
142
- gr.Markdown("# 🎨 Kling AI Image-to-Image Generator")
143
- gr.Markdown("Transform images using Kling AI's Kolors technology")
144
 
145
  with gr.Row():
146
  with gr.Column():
147
- gr.Markdown("## Input Settings")
148
  image_input = gr.Image(
149
- type="filepath",
150
  label="Upload Image",
151
- sources=["upload"],
152
  )
153
  prompt_input = gr.Textbox(
154
- lines=2,
155
  label="Transformation Prompt",
156
- placeholder="Describe how you want to transform the image (e.g. 'vibrant watercolor painting')"
157
  )
158
  generate_btn = gr.Button("Generate", variant="primary")
159
 
160
  gr.Markdown("### Requirements")
161
  gr.Markdown("""
162
- - Max image size: 10MB
163
- - Min dimensions: 300x300px
164
- - Supported formats: JPG, PNG
165
- - Aspect ratio: Between 1:2.5 and 2.5:1
 
166
  """)
167
 
168
  with gr.Column():
169
- gr.Markdown("## Output")
170
  output_image = gr.Image(label="Generated Image", interactive=False)
171
  output_file = gr.File(label="Download Result", file_types=["image/png"])
172
  status_output = gr.Textbox(label="Status", interactive=False)
173
 
174
  generate_btn.click(
175
- fn=chatbot_interface,
176
  inputs=[image_input, prompt_input],
177
  outputs=[output_image, output_file, status_output]
178
  )
@@ -181,6 +211,5 @@ if __name__ == "__main__":
181
  app.launch(
182
  server_name="0.0.0.0",
183
  server_port=7860,
184
- share=False,
185
- show_error=True
186
  )
 
7
  import logging
8
  from pathlib import Path
9
 
10
+ # Configure logging
11
  logging.basicConfig(level=logging.INFO)
12
  logger = logging.getLogger(__name__)
13
 
14
+ # ===== API CONFIGURATION =====
15
  ACCESS_KEY_ID = "AFyHfnQATghFdCMyAG3gRPbNY4TNKFGB"
16
  ACCESS_KEY_SECRET = "TTepeLyBterLNM3brYPGmdndBnnyKJBA"
17
+ API_BASE_URL = "https://api-singapore.klingai.com"
18
+ CREATE_TASK_ENDPOINT = f"{API_BASE_URL}/v1/images/generations"
19
 
20
+ # ===== AUTHENTICATION =====
21
  def generate_jwt_token():
22
  """Generate JWT token for API authentication"""
23
  payload = {
24
  "iss": ACCESS_KEY_ID,
25
+ "exp": int(time.time()) + 1800, # 30 minutes expiration
26
+ "nbf": int(time.time()) - 5 # Not before 5 seconds ago
27
  }
28
+ try:
29
+ token = jwt.encode(payload, ACCESS_KEY_SECRET, algorithm="HS256")
30
+ return token if isinstance(token, str) else token.decode('utf-8')
31
+ except Exception as e:
32
+ logger.error(f"JWT generation failed: {str(e)}")
33
+ return None
34
 
35
+ # ===== IMAGE VALIDATION =====
36
  def validate_image(image_path):
37
+ """Check if image meets API requirements"""
38
  try:
39
+ # Check file size
40
+ size_mb = os.path.getsize(image_path) / (1024 * 1024)
41
+ if size_mb > 10:
42
  return False, "Image too large (max 10MB)"
43
 
44
+ # Check file extension
45
+ ext = os.path.splitext(image_path)[1].lower()
46
+ if ext not in ['.jpg', '.jpeg', '.png']:
47
+ return False, "Invalid format (only JPG/PNG)"
48
+
49
  return True, ""
50
  except Exception as e:
51
  return False, f"Image validation error: {str(e)}"
 
53
  # ===== API FUNCTIONS =====
54
  def create_image_task(image_base64, prompt):
55
  """Create image generation task"""
56
+ token = generate_jwt_token()
57
+ if not token:
58
+ return None, "Authentication failed"
59
+
60
  headers = {
61
+ "Authorization": f"Bearer {token}",
62
  "Content-Type": "application/json"
63
  }
64
 
65
  payload = {
66
+ "model_name": "kling-v2", # Recommended model
67
+ "prompt": prompt or "Transform into a vibrant artistic style",
68
  "image": image_base64,
69
+ "resolution": "1k", # Start with 1k for faster results
70
+ "aspect_ratio": "1:1",
71
+ "n": 1
72
  }
73
 
74
  try:
75
+ response = requests.post(
76
+ CREATE_TASK_ENDPOINT,
77
+ json=payload,
78
+ headers=headers,
79
+ timeout=30
80
+ )
81
  response.raise_for_status()
82
+ return response.json(), None
83
  except requests.exceptions.RequestException as e:
84
  logger.error(f"API request failed: {str(e)}")
85
+ if hasattr(e, 'response') and e.response:
86
+ logger.error(f"API response: {e.response.text}")
87
+ return None, f"API request failed: {str(e)}"
88
 
89
+ def check_task_status(task_id):
90
+ """Check task completion status"""
91
+ token = generate_jwt_token()
92
+ if not token:
93
+ return None, "Authentication failed"
94
+
95
+ headers = {"Authorization": f"Bearer {token}"}
96
+ status_url = f"{API_BASE_URL}/v1/images/generations/{task_id}"
97
 
98
  try:
99
+ response = requests.get(status_url, headers=headers, timeout=30)
100
  response.raise_for_status()
101
+ return response.json(), None
102
  except requests.exceptions.RequestException as e:
103
+ logger.error(f"Status check failed: {str(e)}")
104
+ return None, f"Status check failed: {str(e)}"
105
 
106
  # ===== MAIN PROCESSING =====
107
+ def generate_image(image_path, prompt):
108
+ """Handle complete image generation workflow"""
109
+ # Validate image
110
  is_valid, error_msg = validate_image(image_path)
111
  if not is_valid:
112
  return None, error_msg
113
+
114
+ # Read and encode image
115
  try:
116
  with open(image_path, "rb") as img_file:
117
+ image_base64 = base64.b64encode(img_file.read()).decode('utf-8')
118
  except Exception as e:
119
+ return None, f"Failed to process image: {str(e)}"
120
+
121
+ # Create task
122
+ task_response, error = create_image_task(image_base64, prompt)
123
+ if error:
124
+ return None, error
125
+
126
+ if task_response.get("code") != 0:
127
+ return None, f"API error: {task_response.get('message', 'Unknown error')}"
128
+
129
  task_id = task_response["data"]["task_id"]
130
+ logger.info(f"Task created: {task_id}")
131
+
132
+ # Poll for results (max 10 minutes)
133
  for _ in range(60):
134
+ task_data, error = check_task_status(task_id)
135
+ if error:
136
+ return None, error
 
137
 
138
  status = task_data["data"]["task_status"]
139
 
140
  if status == "succeed":
141
  image_url = task_data["data"]["task_result"]["images"][0]["url"]
142
  try:
143
+ response = requests.get(image_url, timeout=30)
144
+ response.raise_for_status()
145
  output_path = Path(f"/tmp/kling_output_{task_id}.png")
146
  with open(output_path, "wb") as f:
147
+ f.write(response.content)
148
  return str(output_path), None
149
  except Exception as e:
150
+ return None, f"Failed to download result: {str(e)}"
151
 
152
  elif status in ("failed", "canceled"):
153
+ error_msg = task_data["data"].get("task_status_msg", "Unknown error")
154
+ return None, f"Task failed: {error_msg}"
155
 
156
  time.sleep(10)
157
 
158
  return None, "Task timed out after 10 minutes"
159
 
160
  # ===== GRADIO INTERFACE =====
161
+ def process_interface(image, prompt):
162
  if not image:
163
  return None, None, "Please upload an image first"
164
 
165
  output_path, error = generate_image(image, prompt)
166
  if error:
167
+ logger.error(f"Generation failed: {error}")
168
  return None, None, error
169
 
170
+ return output_path, output_path, "Success! Image generated"
171
 
172
+ with gr.Blocks(title="Kling AI Image Generator") as app:
173
+ gr.Markdown("## 🎨 Kling AI Image-to-Image Transformation")
 
174
 
175
  with gr.Row():
176
  with gr.Column():
177
+ gr.Markdown("### Input Settings")
178
  image_input = gr.Image(
179
+ type="filepath",
180
  label="Upload Image",
181
+ sources=["upload"]
182
  )
183
  prompt_input = gr.Textbox(
 
184
  label="Transformation Prompt",
185
+ placeholder="Describe the desired style (e.g. 'watercolor painting')"
186
  )
187
  generate_btn = gr.Button("Generate", variant="primary")
188
 
189
  gr.Markdown("### Requirements")
190
  gr.Markdown("""
191
+ - **Image Requirements**:
192
+ - Max size: 10MB
193
+ - Formats: JPG, PNG
194
+ - Min dimensions: 300x300px
195
+ - Aspect ratio between 1:2.5 and 2.5:1
196
  """)
197
 
198
  with gr.Column():
199
+ gr.Markdown("### Output")
200
  output_image = gr.Image(label="Generated Image", interactive=False)
201
  output_file = gr.File(label="Download Result", file_types=["image/png"])
202
  status_output = gr.Textbox(label="Status", interactive=False)
203
 
204
  generate_btn.click(
205
+ fn=process_interface,
206
  inputs=[image_input, prompt_input],
207
  outputs=[output_image, output_file, status_output]
208
  )
 
211
  app.launch(
212
  server_name="0.0.0.0",
213
  server_port=7860,
214
+ share=False
 
215
  )