Spaces:
Sleeping
Sleeping
Muhammad Waqas
commited on
Commit
·
0e95549
1
Parent(s):
78e3b99
Added: Generate image to video
Browse files- Dockerfile +2 -1
- app.py +39 -11
- workflows/cogvideox_image_to_video_workflow_api.json +1 -2
Dockerfile
CHANGED
@@ -39,4 +39,5 @@ USER flaskuser
|
|
39 |
EXPOSE 7860
|
40 |
|
41 |
# Run the Flask app using gunicorn with an infinite request timeout
|
42 |
-
CMD ["gunicorn", "--bind", "0.0.0.0:7860", "--timeout", "0", "app:app"]
|
|
|
|
39 |
EXPOSE 7860
|
40 |
|
41 |
# Run the Flask app using gunicorn with an infinite request timeout
|
42 |
+
# CMD ["gunicorn", "--bind", "0.0.0.0:7860", "--timeout", "0", "app:app"]
|
43 |
+
CMD ["gunicorn", "--bind", "0.0.0.0:7860", "--timeout", "0", "--access-logfile", "-", "--error-logfile", "-", "app:app"]
|
app.py
CHANGED
@@ -261,8 +261,8 @@ def get_video_data(filename, subfolder, token):
|
|
261 |
##################################################
|
262 |
|
263 |
# Route: Image to Video
|
264 |
-
@app.route('/image_to_video', methods=['POST'])
|
265 |
-
def
|
266 |
data = request.json
|
267 |
|
268 |
# Extract and validate token
|
@@ -273,9 +273,21 @@ def image_to_video():
|
|
273 |
|
274 |
# Validate text prompt
|
275 |
text_prompt = data.get('text_prompt')
|
276 |
-
|
|
|
277 |
return jsonify({'error': 'Text prompt is required'}), 400
|
278 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
279 |
# Handle uploaded image or base64 image
|
280 |
image_file = request.files.get('image')
|
281 |
base64_image = data.get('base64_image')
|
@@ -322,8 +334,9 @@ def image_to_video():
|
|
322 |
|
323 |
# Modify workflow with inputs
|
324 |
workflow["30"]["inputs"]["prompt"] = text_prompt
|
|
|
325 |
workflow["73"]["inputs"]["url"] = image_url
|
326 |
-
workflow["31"]["inputs"]["prompt"] = "Low quality, watermark, strange motion"
|
327 |
|
328 |
# WebSocket connection to queue the prompt
|
329 |
ws = websocket.WebSocket()
|
@@ -345,9 +358,9 @@ def image_to_video():
|
|
345 |
# os.remove(image_path)
|
346 |
# print(f"Deleted temporary image: {image_path}", flush=True)
|
347 |
|
348 |
-
# Get
|
349 |
-
@app.route('/
|
350 |
-
def
|
351 |
token = request.headers.get('Authorization')
|
352 |
if not token or not token.startswith("Bearer "):
|
353 |
return jsonify({'error': 'Valid Bearer token required'}), 400
|
@@ -408,8 +421,8 @@ def get_video(prompt_id):
|
|
408 |
return jsonify({'error': str(e)}), 500
|
409 |
|
410 |
# Route: Image to Video old
|
411 |
-
@app.route('/
|
412 |
-
def
|
413 |
data = request.json
|
414 |
|
415 |
# Extract and validate token
|
@@ -420,9 +433,21 @@ def v1_image_to_video():
|
|
420 |
|
421 |
# Validate text prompt
|
422 |
text_prompt = data.get('text_prompt')
|
423 |
-
|
|
|
424 |
return jsonify({'error': 'Text prompt is required'}), 400
|
425 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
426 |
# Handle uploaded image or base64 image
|
427 |
image_file = request.files.get('image')
|
428 |
base64_image = data.get('base64_image')
|
@@ -469,6 +494,7 @@ def v1_image_to_video():
|
|
469 |
|
470 |
# Modify workflow with inputs
|
471 |
workflow["30"]["inputs"]["prompt"] = text_prompt
|
|
|
472 |
workflow["73"]["inputs"]["url"] = image_url
|
473 |
workflow["31"]["inputs"]["prompt"] = "Low quality, watermark, strange motion"
|
474 |
|
@@ -518,8 +544,10 @@ def v1_image_to_video():
|
|
518 |
local_video_path = f"static/generated_image_to_video_{prompt_id}.mp4"
|
519 |
with open(local_video_path, 'wb') as f:
|
520 |
f.write(video_data)
|
|
|
521 |
# Construct the public URL for the video
|
522 |
-
|
|
|
523 |
|
524 |
# Prepare the response with the video URL
|
525 |
# response_data = {
|
|
|
261 |
##################################################
|
262 |
|
263 |
# Route: Image to Video
|
264 |
+
@app.route('/v1/image_to_video', methods=['POST'])
|
265 |
+
def v1_image_to_video():
|
266 |
data = request.json
|
267 |
|
268 |
# Extract and validate token
|
|
|
273 |
|
274 |
# Validate text prompt
|
275 |
text_prompt = data.get('text_prompt')
|
276 |
+
frame_rate = data.get('frame_rate')
|
277 |
+
if not text_prompt or not text_prompt.strip():
|
278 |
return jsonify({'error': 'Text prompt is required'}), 400
|
279 |
|
280 |
+
# Check if frame_rate is missing or invalid
|
281 |
+
if not frame_rate: # If frame_rate is None, empty, or 0
|
282 |
+
frame_rate = 24 # Default to 24 fps
|
283 |
+
else:
|
284 |
+
try:
|
285 |
+
frame_rate = int(frame_rate)
|
286 |
+
if frame_rate not in [8, 12, 24]: # Ensure it's one of the allowed values
|
287 |
+
return jsonify({'error': 'Frame rate must be a valid number (8, 12, or 24).'}), 400
|
288 |
+
except ValueError:
|
289 |
+
return jsonify({'error': 'Frame rate must be a valid number (8, 12, or 24).'}), 400
|
290 |
+
|
291 |
# Handle uploaded image or base64 image
|
292 |
image_file = request.files.get('image')
|
293 |
base64_image = data.get('base64_image')
|
|
|
334 |
|
335 |
# Modify workflow with inputs
|
336 |
workflow["30"]["inputs"]["prompt"] = text_prompt
|
337 |
+
workflow["44"]["inputs"]["frame_rate"] = frame_rate
|
338 |
workflow["73"]["inputs"]["url"] = image_url
|
339 |
+
workflow["31"]["inputs"]["prompt"] = "Low quality, watermark, strange motion, blur"
|
340 |
|
341 |
# WebSocket connection to queue the prompt
|
342 |
ws = websocket.WebSocket()
|
|
|
358 |
# os.remove(image_path)
|
359 |
# print(f"Deleted temporary image: {image_path}", flush=True)
|
360 |
|
361 |
+
# Get video_tasks route
|
362 |
+
@app.route('/v1/video_tasks/<prompt_id>', methods=['GET'])
|
363 |
+
def video_tasks(prompt_id):
|
364 |
token = request.headers.get('Authorization')
|
365 |
if not token or not token.startswith("Bearer "):
|
366 |
return jsonify({'error': 'Valid Bearer token required'}), 400
|
|
|
421 |
return jsonify({'error': str(e)}), 500
|
422 |
|
423 |
# Route: Image to Video old
|
424 |
+
@app.route('/image_to_video', methods=['POST'])
|
425 |
+
def image_to_video():
|
426 |
data = request.json
|
427 |
|
428 |
# Extract and validate token
|
|
|
433 |
|
434 |
# Validate text prompt
|
435 |
text_prompt = data.get('text_prompt')
|
436 |
+
frame_rate = data.get('frame_rate')
|
437 |
+
if not text_prompt or not text_prompt.strip():
|
438 |
return jsonify({'error': 'Text prompt is required'}), 400
|
439 |
|
440 |
+
# Check if frame_rate is missing or invalid
|
441 |
+
if not frame_rate: # If frame_rate is None, empty, or 0
|
442 |
+
frame_rate = 24 # Default to 24 fps
|
443 |
+
else:
|
444 |
+
try:
|
445 |
+
frame_rate = int(frame_rate)
|
446 |
+
if frame_rate not in [8, 12, 24]:
|
447 |
+
return jsonify({'error': 'Frame rate must be a valid number (8, 12, or 24).'}), 400
|
448 |
+
except ValueError:
|
449 |
+
return jsonify({'error': 'Frame rate must be a valid number (8, 12, or 24).'}), 400
|
450 |
+
|
451 |
# Handle uploaded image or base64 image
|
452 |
image_file = request.files.get('image')
|
453 |
base64_image = data.get('base64_image')
|
|
|
494 |
|
495 |
# Modify workflow with inputs
|
496 |
workflow["30"]["inputs"]["prompt"] = text_prompt
|
497 |
+
workflow["44"]["inputs"]["frame_rate"] = frame_rate
|
498 |
workflow["73"]["inputs"]["url"] = image_url
|
499 |
workflow["31"]["inputs"]["prompt"] = "Low quality, watermark, strange motion"
|
500 |
|
|
|
544 |
local_video_path = f"static/generated_image_to_video_{prompt_id}.mp4"
|
545 |
with open(local_video_path, 'wb') as f:
|
546 |
f.write(video_data)
|
547 |
+
|
548 |
# Construct the public URL for the video
|
549 |
+
|
550 |
+
# video_url = f"https://gosign-de-comfyui-api.hf.space/{local_video_path}"
|
551 |
|
552 |
# Prepare the response with the video URL
|
553 |
# response_data = {
|
workflows/cogvideox_image_to_video_workflow_api.json
CHANGED
@@ -17,7 +17,6 @@
|
|
17 |
"clip_name": "t5\\google_t5-v1_1-xxl_encoderonly-fp8_e4m3fn.safetensors",
|
18 |
"type": "sd3"
|
19 |
},
|
20 |
-
"class_type": "CLIPLoader",
|
21 |
"_meta": {
|
22 |
"title": "Load CLIP"
|
23 |
}
|
@@ -72,7 +71,7 @@
|
|
72 |
},
|
73 |
"44": {
|
74 |
"inputs": {
|
75 |
-
"frame_rate":
|
76 |
"loop_count": 0,
|
77 |
"filename_prefix": "CogVideoX-I2V",
|
78 |
"format": "video/h264-mp4",
|
|
|
17 |
"clip_name": "t5\\google_t5-v1_1-xxl_encoderonly-fp8_e4m3fn.safetensors",
|
18 |
"type": "sd3"
|
19 |
},
|
|
|
20 |
"_meta": {
|
21 |
"title": "Load CLIP"
|
22 |
}
|
|
|
71 |
},
|
72 |
"44": {
|
73 |
"inputs": {
|
74 |
+
"frame_rate": 24,
|
75 |
"loop_count": 0,
|
76 |
"filename_prefix": "CogVideoX-I2V",
|
77 |
"format": "video/h264-mp4",
|