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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +71 -77
app.py CHANGED
@@ -22,92 +22,68 @@ 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)}"
52
 
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
 
@@ -118,8 +94,8 @@ def generate_image(image_path, prompt):
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
 
@@ -127,10 +103,10 @@ def generate_image(image_path, prompt):
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
@@ -140,14 +116,14 @@ def generate_image(image_path, prompt):
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")
@@ -155,55 +131,73 @@ def generate_image(image_path, prompt):
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
  )
209
 
 
22
  """Generate JWT token for API authentication"""
23
  payload = {
24
  "iss": ACCESS_KEY_ID,
25
+ "exp": int(time.time()) + 1800,
26
+ "nbf": int(time.time()) - 5
27
  }
28
+ return jwt.encode(payload, ACCESS_KEY_SECRET, algorithm="HS256")
 
 
 
 
 
29
 
30
+ # ===== FACE VALIDATION =====
31
+ def validate_face_image(image_path):
32
+ """Check if image contains exactly one face"""
33
  try:
34
+ # In production, you'd use face detection here
35
+ # For demo, we'll just check basic image properties
36
  size_mb = os.path.getsize(image_path) / (1024 * 1024)
37
  if size_mb > 10:
38
  return False, "Image too large (max 10MB)"
 
 
 
 
 
 
39
  return True, ""
40
  except Exception as e:
41
  return False, f"Image validation error: {str(e)}"
42
 
43
  # ===== API FUNCTIONS =====
44
+ def create_face_transform_task(image_base64, prompt, strength=0.97):
45
+ """Create face transformation task with high reference strength"""
 
 
 
 
46
  headers = {
47
+ "Authorization": f"Bearer {generate_jwt_token()}",
48
  "Content-Type": "application/json"
49
  }
50
 
51
  payload = {
52
+ "model_name": "kling-v2-1", # Best for face transformation
53
+ "prompt": prompt,
54
  "image": image_base64,
55
+ "image_reference": "face", # Critical for face transformation
56
+ "image_fidelity": strength, # 0.97 = 97% reference strength
57
+ "resolution": "1k",
58
  "aspect_ratio": "1:1",
59
  "n": 1
60
  }
61
 
62
  try:
63
+ response = requests.post(CREATE_TASK_ENDPOINT, json=payload, headers=headers)
 
 
 
 
 
64
  response.raise_for_status()
65
  return response.json(), None
66
  except requests.exceptions.RequestException as e:
67
  logger.error(f"API request failed: {str(e)}")
68
+ return None, f"API Error: {str(e)}"
 
 
69
 
70
  def check_task_status(task_id):
71
  """Check task completion status"""
72
+ headers = {"Authorization": f"Bearer {generate_jwt_token()}"}
 
 
 
 
73
  status_url = f"{API_BASE_URL}/v1/images/generations/{task_id}"
74
 
75
  try:
76
+ response = requests.get(status_url, headers=headers)
77
  response.raise_for_status()
78
  return response.json(), None
79
  except requests.exceptions.RequestException as e:
 
80
  return None, f"Status check failed: {str(e)}"
81
 
82
  # ===== MAIN PROCESSING =====
83
+ def transform_face(image_path, prompt, strength=0.97):
84
+ """Handle face transformation workflow"""
85
  # Validate image
86
+ is_valid, error_msg = validate_face_image(image_path)
87
  if not is_valid:
88
  return None, error_msg
89
 
 
94
  except Exception as e:
95
  return None, f"Failed to process image: {str(e)}"
96
 
97
+ # Create task with face reference
98
+ task_response, error = create_face_transform_task(image_base64, prompt, strength)
99
  if error:
100
  return None, error
101
 
 
103
  return None, f"API error: {task_response.get('message', 'Unknown error')}"
104
 
105
  task_id = task_response["data"]["task_id"]
106
+ logger.info(f"Face transformation task created: {task_id}")
107
 
108
+ # Poll for results
109
+ for _ in range(30): # Max 5 minutes (10s intervals)
110
  task_data, error = check_task_status(task_id)
111
  if error:
112
  return None, error
 
116
  if status == "succeed":
117
  image_url = task_data["data"]["task_result"]["images"][0]["url"]
118
  try:
119
+ response = requests.get(image_url)
120
  response.raise_for_status()
121
+ output_path = Path(f"/tmp/kling_face_{task_id}.png")
122
  with open(output_path, "wb") as f:
123
  f.write(response.content)
124
  return str(output_path), None
125
  except Exception as e:
126
+ return None, f"Failed to save result: {str(e)}"
127
 
128
  elif status in ("failed", "canceled"):
129
  error_msg = task_data["data"].get("task_status_msg", "Unknown error")
 
131
 
132
  time.sleep(10)
133
 
134
+ return None, "Task timed out after 5 minutes"
135
 
136
  # ===== GRADIO INTERFACE =====
137
+ def process_interface(image, prompt, strength):
138
  if not image:
139
+ return None, None, "Please upload an image with a clear face"
140
 
141
+ output_path, error = transform_face(image, prompt, strength/100)
142
  if error:
 
143
  return None, None, error
144
 
145
+ return output_path, output_path, "Face transformation successful!"
146
 
147
+ with gr.Blocks(title="Kling AI Face Transformer") as app:
148
+ gr.Markdown("## 👤 Kling AI Face Transformation")
149
+ gr.Markdown("Transform faces with high precision (97% reference strength)")
150
 
151
  with gr.Row():
152
  with gr.Column():
153
  gr.Markdown("### Input Settings")
154
  image_input = gr.Image(
155
  type="filepath",
156
+ label="Upload Face Image",
157
+ sources=["upload"],
158
+ height=300
159
  )
160
  prompt_input = gr.Textbox(
161
+ label="Transformation Style",
162
+ placeholder="Describe the new style (e.g. 'anime character', 'oil painting portrait')"
163
+ )
164
+ strength_slider = gr.Slider(
165
+ minimum=80,
166
+ maximum=100,
167
+ value=97,
168
+ step=1,
169
+ label="Reference Strength (%)",
170
+ info="Higher values preserve more facial features"
171
  )
172
+ generate_btn = gr.Button("Transform Face", variant="primary")
173
 
174
  gr.Markdown("### Requirements")
175
  gr.Markdown("""
176
+ - **Must contain exactly one clear face**
177
+ - Max size: 10MB
178
+ - Formats: JPG, PNG
179
+ - Min resolution: 300x300px
 
180
  """)
181
 
182
  with gr.Column():
183
  gr.Markdown("### Output")
184
+ output_image = gr.Image(
185
+ label="Transformed Face",
186
+ interactive=False,
187
+ height=400
188
+ )
189
+ output_file = gr.File(
190
+ label="Download Result",
191
+ file_types=["image/png"]
192
+ )
193
+ status_output = gr.Textbox(
194
+ label="Status",
195
+ interactive=False
196
+ )
197
 
198
  generate_btn.click(
199
  fn=process_interface,
200
+ inputs=[image_input, prompt_input, strength_slider],
201
  outputs=[output_image, output_file, status_output]
202
  )
203