Muhammad Waqas commited on
Commit
01fbb1a
·
1 Parent(s): 1298b7e

Added: Generate image to video

Browse files
.gitignore CHANGED
@@ -1 +1,2 @@
1
- /static
 
 
1
+ /static
2
+ /sample-response.json
app.py CHANGED
@@ -114,9 +114,9 @@ def get_images(ws, workflow, token):
114
  def home():
115
  return render_template('home.html')
116
 
117
- ###############################################
118
- # Generate text to image using FLUX1.DEV Model#
119
- ###############################################
120
 
121
  # Generate image route
122
  @app.route('/generate_image', methods=['POST'])
@@ -265,14 +265,151 @@ def get_video_data(filename, subfolder, token):
265
  def image_to_video():
266
  data = request.json
267
 
268
- time.sleep(900)
269
- # Prepare the response with the video URL
270
- response_data = {
271
- 'video_url': 'https://gosign-de-comfyui-stg.hf.space/view?filename=CogVideoX-I2V_00010.mp4',
272
- 'message': 'Video generated successfully'
273
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
274
 
275
- return jsonify(response_data), 200
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
276
 
277
  # Extract and validate token
278
  token = request.headers.get('Authorization')
@@ -377,7 +514,7 @@ def image_to_video():
377
  raise ValueError('Failed to generate video')
378
 
379
  # Save the video locally
380
- local_video_path = f"static/generated_video_{prompt_id}.mp4"
381
  with open(local_video_path, 'wb') as f:
382
  f.write(video_data)
383
  # Construct the public URL for the video
@@ -410,5 +547,6 @@ def image_to_video():
410
  os.remove(image_path)
411
  print(f"Deleted temporary image: {image_path}", flush=True)
412
 
 
413
  if __name__ == '__main__':
414
- app.run(host='0.0.0.0', port=7860, debug=True) # Removed 'debug=True'
 
114
  def home():
115
  return render_template('home.html')
116
 
117
+ ################################################
118
+ # Generate text to image using FLUX1.DEV Model #
119
+ ################################################
120
 
121
  # Generate image route
122
  @app.route('/generate_image', methods=['POST'])
 
265
  def image_to_video():
266
  data = request.json
267
 
268
+ # Extract and validate token
269
+ token = request.headers.get('Authorization')
270
+ if not token or not token.startswith("Bearer "):
271
+ return jsonify({'error': 'Valid Bearer token required'}), 400
272
+ token = token.split(" ")[1]
273
+
274
+ # Validate text prompt
275
+ text_prompt = data.get('text_prompt')
276
+ if not text_prompt:
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')
282
+
283
+ image_path = None # Initialize image path
284
+
285
+ try:
286
+ if image_file:
287
+ # Check if the file has an allowed extension
288
+ if not allowed_file(image_file.filename):
289
+ return jsonify({'error': 'Unsupported image format'}), 400
290
+
291
+ # Secure the filename
292
+ filename = secure_filename(image_file.filename)
293
+
294
+ # Generate a unique path for the image
295
+ unique_filename = f"{uuid.uuid4()}_{filename}"
296
+ image_path = os.path.join('static', unique_filename)
297
+
298
+ # Ensure the 'static' directory exists
299
+ os.makedirs('static', exist_ok=True)
300
+
301
+ # Save the image to the static directory
302
+ image_file.save(image_path)
303
+
304
+ # Construct the public URL to access the image
305
+ image_url = f"https://gosign-de-comfyui-api.hf.space/{image_path}"
306
+
307
+ elif base64_image:
308
+ # Save base64 image
309
+ try:
310
+ image_path, image_url = save_base64_image(base64_image)
311
+ except Exception as e:
312
+ raise ValueError(f'Invalid base64 image data: {str(e)}')
313
+
314
+ else:
315
+ return jsonify({'error': 'Image is required (file or base64)'}), 400
316
 
317
+ # Load workflow configuration
318
+ current_dir = os.path.dirname(os.path.abspath(__file__))
319
+ workflow_path = os.path.join(current_dir, 'workflows/cogvideox_image_to_video_workflow_api.json')
320
+ with open(workflow_path, 'r', encoding='utf-8') as f:
321
+ workflow = json.load(f)
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()
330
+ ws.connect(f"{ws_address}?clientId={client_id}&token={token}",
331
+ header={"Authorization": f"Bearer {token}"})
332
+
333
+ # Queue the prompt
334
+ prompt_id = queue_prompt(workflow, token)
335
+
336
+ return jsonify({'prompt_id': prompt_id, 'message': 'Prompt queued successfully', 'get_video_url': f'https://gosign-de-comfyui-api.hf.space/get_video/{prompt_id}'}), 202
337
+
338
+ except Exception as e:
339
+ return jsonify({'message': 'Unbale to connect to the server. Make sure the server is running', 'error': str(e)}), 500
340
+
341
+ finally:
342
+ # Always delete the image if it was saved
343
+ if image_path and os.path.exists(image_path):
344
+ os.remove(image_path)
345
+ print(f"Deleted temporary image: {image_path}", flush=True)
346
+
347
+ # Get video route
348
+ @app.route('/get_video/<prompt_id>', methods=['GET'])
349
+ def get_video(prompt_id):
350
+ token = request.headers.get('Authorization')
351
+ if not token or not token.startswith("Bearer "):
352
+ return jsonify({'error': 'Valid Bearer token required'}), 400
353
+ token = token.split(" ")[1]
354
+
355
+ try:
356
+
357
+ # Establish WebSocket connection to fetch real-time status
358
+ ws = websocket.WebSocket()
359
+ ws.connect(f"{ws_address}?clientId={client_id}&token={token}",
360
+ header={"Authorization": f"Bearer {token}"})
361
+
362
+ # Request current status of the specific prompt
363
+ ws.send(json.dumps({"type": "get_status", "prompt_id": prompt_id}))
364
+ response = json.loads(ws.recv())
365
+
366
+ # Extract the necessary fields for the specific prompt
367
+ queue_remaining = response.get('data', {}).get('status', {}).get('exec_info', {}).get('queue_remaining', 0)
368
+
369
+ # Now proceed to check if the prompt has completed successfully
370
+ history = get_history(prompt_id, token).get(prompt_id, {})
371
+
372
+ if not history:
373
+ return jsonify({
374
+ 'message': 'Video is being generated.',
375
+ 'status': 'pending',
376
+ 'prompts_in_queue': queue_remaining
377
+ }), 202
378
+ video_data = None
379
+
380
+ # Extract video or GIF details
381
+ for node_id, node_output in history.get('outputs', {}).items():
382
+ if 'gifs' in node_output:
383
+ video = node_output['gifs'][0] # Take the first available GIF/video
384
+ try:
385
+ video_data = get_video_data(video['filename'], video['subfolder'], token)
386
+ break # Stop after fetching the first valid video
387
+ except Exception as e:
388
+ print(f"Failed to retrieve video: {str(e)}")
389
+
390
+ if not video_data:
391
+ return jsonify({'error': 'Failed to retrieve video data.'}), 500
392
+
393
+ # Save the video locally
394
+ local_video_path = f"static/generated_image_to_video_{prompt_id}.mp4"
395
+ with open(local_video_path, 'wb') as f:
396
+ f.write(video_data)
397
+
398
+ # Send the video as an HTTP response
399
+ return send_file(
400
+ io.BytesIO(video_data),
401
+ mimetype='video/mp4',
402
+ as_attachment=True,
403
+ download_name='generated_video.mp4'
404
+ )
405
+
406
+ except Exception as e:
407
+ return jsonify({'error': str(e)}), 500
408
+
409
+ # Route: Image to Video old
410
+ @app.route('/image_to_video_old', methods=['POST'])
411
+ def image_to_video_old():
412
+ data = request.json
413
 
414
  # Extract and validate token
415
  token = request.headers.get('Authorization')
 
514
  raise ValueError('Failed to generate video')
515
 
516
  # Save the video locally
517
+ local_video_path = f"static/generated_image_to_video_{prompt_id}.mp4"
518
  with open(local_video_path, 'wb') as f:
519
  f.write(video_data)
520
  # Construct the public URL for the video
 
547
  os.remove(image_path)
548
  print(f"Deleted temporary image: {image_path}", flush=True)
549
 
550
+
551
  if __name__ == '__main__':
552
+ app.run(host='0.0.0.0', port=7860, debug=True)
workflows/cogvideox_image_to_video_workflow_api.json CHANGED
@@ -118,7 +118,7 @@
118
  "height": 480,
119
  "width": 720,
120
  "num_frames": 49,
121
- "steps": 50,
122
  "cfg": 6,
123
  "seed": 65334758276105,
124
  "scheduler": "DPM++",
 
118
  "height": 480,
119
  "width": 720,
120
  "num_frames": 49,
121
+ "steps": 10,
122
  "cfg": 6,
123
  "seed": 65334758276105,
124
  "scheduler": "DPM++",