TDN-M commited on
Commit
826a6c1
·
verified ·
1 Parent(s): 3bb7349

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +82 -22
app.py CHANGED
@@ -29,7 +29,7 @@ def validate_tdn_key(user_key):
29
  return True, "Khóa bí mật được xác thực thành công."
30
 
31
  # Hàm kiểm tra yêu cầu hình ảnh
32
- def validate_image(image_path, max_size_mb=10):
33
  if not image_path:
34
  return False, "Lỗi: Chưa cung cấp hình ảnh."
35
 
@@ -42,10 +42,12 @@ def validate_image(image_path, max_size_mb=10):
42
  if mime_type not in ["image/png", "image/webp", "image/jpeg", "image/jpg"]:
43
  return False, "Lỗi: Định dạng hình ảnh không được hỗ trợ. Sử dụng PNG, WebP, JPEG hoặc JPG."
44
 
45
- # Kiểm tra tỷ lệ khung hình
46
  try:
47
  img = Image.open(image_path)
48
  width, height = img.size
 
 
49
  aspect_ratio = width / height
50
  if aspect_ratio < 0.25 or aspect_ratio > 4:
51
  return False, "Lỗi: Tỷ lệ khung hình phải nằm trong khoảng 1:4 đến 4:1."
@@ -153,10 +155,10 @@ def start_end_to_video(start_image, end_image, prompt, resolution="720p", durati
153
  return None, error_message
154
 
155
  # Tải hình ảnh lên TDNM
156
- start_uri, start_message = upload_image_to_vidu(start_image)
157
  if not start_uri:
158
  return None, start_message
159
- end_uri, end_message = upload_image_to_vidu(end_image)
160
  if not end_uri:
161
  return None, end_message
162
 
@@ -208,7 +210,7 @@ def img_to_video(image, prompt, resolution="720p", duration=4, movement_amplitud
208
  if prompt and len(prompt) > 1500:
209
  return None, "Lỗi: Mô tả văn bản không được vượt quá 1500 ký tự."
210
 
211
- # Tải hình ảnh lên TDNM (giới hạn 50MB cho img2video)
212
  image_uri, image_message = upload_image_to_vidu(image, max_size_mb=50)
213
  if not image_uri:
214
  return None, image_message
@@ -245,13 +247,68 @@ def img_to_video(image, prompt, resolution="720p", duration=4, movement_amplitud
245
  logger.error(f"Phản hồi API: {response.text}")
246
  return None, f"Lỗi: {str(e)} - {response.text}"
247
 
248
- # Placeholder cho References to Video
249
- def references_to_video(reference_images, prompt, resolution="720p", duration=4, user_key=None):
250
  # Kiểm tra TDNM_KEY
251
  valid_key, key_message = validate_tdn_key(user_key)
252
  if not valid_key:
253
  return None, key_message
254
- return None, "Lỗi: Chức năng References to Video chưa được triển khai. Vui lòng cung cấp chi tiết API."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
255
 
256
  # Hàm kiểm tra trạng thái tác vụ
257
  def check_task_status(task_id):
@@ -314,14 +371,14 @@ def gradio_img_to_video(image, prompt, resolution, duration, movement_amplitude,
314
  video_url, status_message = check_task_status(task_id)
315
  return video_url, status_message
316
 
317
- # Hàm giao diện Gradio cho References to Video
318
- def gradio_references_to_video(image1, image2, image3, prompt, resolution, duration, user_key):
319
  reference_images = [img for img in [image1, image2, image3] if img]
320
  if not reference_images:
321
  return None, "Lỗi: Cần cung cấp ít nhất một hình ảnh tham chiếu."
322
  if not prompt:
323
  return None, "Lỗi: Cần cung cấp mô tả văn bản."
324
- task_id, message = references_to_video(reference_images, prompt, resolution, duration, user_key)
325
  if not task_id:
326
  return None, message
327
  video_url, status_message = check_task_status(task_id)
@@ -341,8 +398,8 @@ with gr.Blocks(title="Trình Tạo Video TDNM") as demo:
341
  start_image = gr.Image(type="filepath", label="Hình Ảnh Đầu")
342
  end_image = gr.Image(type="filepath", label="Hình Ảnh Cuối")
343
  prompt_se = gr.Textbox(label="Mô Tả Văn Bản (Tùy Chọn)", placeholder="Ví dụ: 'Chuyển đổi mượt mà từ khung xe thành xe hoàn chỉnh.'")
344
- resolution_se = gr.Dropdown(choices=["360p", "720p", "1080p"], label="Độ Phân Giải", value="720p")
345
- duration_se = gr.Dropdown(choices=[4, 8], label="Thời Lượng (giây)", value=4)
346
  movement_amplitude_se = gr.Dropdown(choices=["auto", "small", "medium", "large"], label="Biên Độ Chuyển Động", value="auto")
347
  seed_se = gr.Number(label="Hạt Giống (Tùy Chọn)", value=None, precision=0)
348
  se_button = gr.Button("Tạo Video")
@@ -360,8 +417,8 @@ with gr.Blocks(title="Trình Tạo Video TDNM") as demo:
360
  gr.Markdown("Tải lên một hình ảnh và mô tả văn bản để tạo video. Hình ảnh phải là PNG, WebP, JPEG hoặc JPG, kích thước dưới 50MB, tỷ lệ khung hình từ 1:4 đến 4:1.")
361
  image_i2v = gr.Image(type="filepath", label="Hình Ảnh")
362
  prompt_i2v = gr.Textbox(label="Mô Tả Văn Bản (Tùy Chọn)", placeholder="Ví dụ: 'Phi hành gia vẫy tay và camera di chuyển lên.'")
363
- resolution_i2v = gr.Dropdown(choices=["360p", "720p", "1080p"], label="Độ Phân Giải", value="720p")
364
- duration_i2v = gr.Dropdown(choices=[4, 8], label="Thời Lượng (giây)", value=4)
365
  movement_amplitude_i2v = gr.Dropdown(choices=["auto", "small", "medium", "large"], label="Biên Độ Chuyển Động", value="auto")
366
  seed_i2v = gr.Number(label="Hạt Giống (Tùy Chọn)", value=None, precision=0)
367
  i2v_button = gr.Button("Tạo Video")
@@ -374,22 +431,25 @@ with gr.Blocks(title="Trình Tạo Video TDNM") as demo:
374
  outputs=[i2v_video_output, i2v_message]
375
  )
376
 
377
- # Tab cho References to Video (Placeholder)
378
  with gr.Tab("Video Từ Hình Ảnh Tham Chiếu"):
379
- gr.Markdown("Tải lên 1–3 hình ảnh tham chiếu và mô tả văn bản để tạo video. (Chưa được triển khai.)")
380
  image1 = gr.Image(type="filepath", label="Hình Ảnh Tham Chiếu 1")
381
  image2 = gr.Image(type="filepath", label="Hình Ảnh Tham Chiếu 2 (Tùy Chọn)")
382
  image3 = gr.Image(type="filepath", label="Hình Ảnh Tham Chiếu 3 (Tùy Chọn)")
383
- prompt_ref = gr.Textbox(label="Mô Tả Văn Bản", placeholder="Ví dụ: 'Một nhân vật đi bộ trong rừng.'")
384
- resolution_ref = gr.Dropdown(choices=["360p", "720p", "1080p"], label="Độ Phân Giải", value="720p")
385
- duration_ref = gr.Dropdown(choices=[4, 8], label="Thời Lượng (giây)", value=4)
 
 
 
386
  ref_button = gr.Button("Tạo Video")
387
  ref_video_output = gr.Video(label="Video Được Tạo")
388
  ref_message = gr.Textbox(label="Trạng Thái")
389
 
390
  ref_button.click(
391
- fn=gradio_references_to_video,
392
- inputs=[image1, image2, image3, prompt_ref, resolution_ref, duration_ref, user_key],
393
  outputs=[ref_video_output, ref_message]
394
  )
395
 
 
29
  return True, "Khóa bí mật được xác thực thành công."
30
 
31
  # Hàm kiểm tra yêu cầu hình ảnh
32
+ def validate_image(image_path, max_size_mb=10, min_dimensions=(128, 128)):
33
  if not image_path:
34
  return False, "Lỗi: Chưa cung cấp hình ảnh."
35
 
 
42
  if mime_type not in ["image/png", "image/webp", "image/jpeg", "image/jpg"]:
43
  return False, "Lỗi: Định dạng hình ảnh không được hỗ trợ. Sử dụng PNG, WebP, JPEG hoặc JPG."
44
 
45
+ # Kiểm tra kích thước và tỷ lệ khung hình
46
  try:
47
  img = Image.open(image_path)
48
  width, height = img.size
49
+ if width < min_dimensions[0] or height < min_dimensions[1]:
50
+ return False, f"Lỗi: Kích thước hình ảnh phải ít nhất {min_dimensions[0]}x{min_dimensions[1]} pixel."
51
  aspect_ratio = width / height
52
  if aspect_ratio < 0.25 or aspect_ratio > 4:
53
  return False, "Lỗi: Tỷ lệ khung hình phải nằm trong khoảng 1:4 đến 4:1."
 
155
  return None, error_message
156
 
157
  # Tải hình ảnh lên TDNM
158
+ start_uri, start_message = upload_image_to_vidu(start_image, max_size_mb=10)
159
  if not start_uri:
160
  return None, start_message
161
+ end_uri, end_message = upload_image_to_vidu(end_image, max_size_mb=10)
162
  if not end_uri:
163
  return None, end_message
164
 
 
210
  if prompt and len(prompt) > 1500:
211
  return None, "Lỗi: Mô tả văn bản không được vượt quá 1500 ký tự."
212
 
213
+ # Tải hình ảnh lên TDNM
214
  image_uri, image_message = upload_image_to_vidu(image, max_size_mb=50)
215
  if not image_uri:
216
  return None, image_message
 
247
  logger.error(f"Phản hồi API: {response.text}")
248
  return None, f"Lỗi: {str(e)} - {response.text}"
249
 
250
+ # Hàm gọi API TDNM cho Reference to Video
251
+ def reference_to_video(reference_images, prompt, resolution="720p", duration=4, aspect_ratio="16:9", movement_amplitude="auto", seed=None, user_key=None):
252
  # Kiểm tra TDNM_KEY
253
  valid_key, key_message = validate_tdn_key(user_key)
254
  if not valid_key:
255
  return None, key_message
256
+
257
+ if not VIDU_API_KEY:
258
+ return None, "Lỗi: Khóa API TDNM chưa được cấu hình."
259
+
260
+ if not reference_images:
261
+ return None, "Lỗi: Cần cung cấp ít nhất một hình ảnh tham chiếu."
262
+
263
+ if len(reference_images) > 3:
264
+ return None, "Lỗi: Chỉ được cung cấp tối đa 3 hình ảnh tham chiếu."
265
+
266
+ if not prompt:
267
+ return None, "Lỗi: Cần cung cấp mô tả văn bản."
268
+
269
+ if prompt and len(prompt) > 1500:
270
+ return None, "Lỗi: Mô tả văn bản không được vượt quá 1500 ký tự."
271
+
272
+ # Tải hình ảnh lên TDNM
273
+ image_uris = []
274
+ for image in reference_images:
275
+ uri, message = upload_image_to_vidu(image, max_size_mb=50)
276
+ if not uri:
277
+ return None, message
278
+ image_uris.append(uri)
279
+
280
+ url = f"{VIDU_API_URL}/ent/v2/reference2video"
281
+ headers = {
282
+ "Authorization": f"Token {VIDU_API_KEY}",
283
+ "Content-Type": "application/json"
284
+ }
285
+
286
+ payload = {
287
+ "model": DEFAULT_MODEL,
288
+ "images": image_uris,
289
+ "prompt": prompt,
290
+ "duration": duration,
291
+ "aspect_ratio": aspect_ratio,
292
+ "resolution": resolution,
293
+ "movement_amplitude": movement_amplitude
294
+ }
295
+ if seed is not None:
296
+ payload["seed"] = seed
297
+
298
+ try:
299
+ logger.info(f"Gửi yêu cầu đến API TDNM Reference to Video: {payload}")
300
+ response = requests.post(url, json=payload, headers=headers)
301
+ response.raise_for_status()
302
+ result = response.json()
303
+ task_id = result.get("task_id")
304
+ if not task_id:
305
+ return None, "Lỗi: Không nhận được ID tác vụ."
306
+ return task_id, f"Tác vụ được tạo thành công. ID tác vụ: {task_id}"
307
+ except requests.exceptions.RequestException as e:
308
+ logger.error(f"Lỗi API: {str(e)}")
309
+ if response.text:
310
+ logger.error(f"Phản hồi API: {response.text}")
311
+ return None, f"Lỗi: {str(e)} - {response.text}"
312
 
313
  # Hàm kiểm tra trạng thái tác vụ
314
  def check_task_status(task_id):
 
371
  video_url, status_message = check_task_status(task_id)
372
  return video_url, status_message
373
 
374
+ # Hàm giao diện Gradio cho Reference to Video
375
+ def gradio_reference_to_video(image1, image2, image3, prompt, resolution, duration, aspect_ratio, movement_amplitude, seed, user_key):
376
  reference_images = [img for img in [image1, image2, image3] if img]
377
  if not reference_images:
378
  return None, "Lỗi: Cần cung cấp ít nhất một hình ảnh tham chiếu."
379
  if not prompt:
380
  return None, "Lỗi: Cần cung cấp mô tả văn bản."
381
+ task_id, message = reference_to_video(reference_images, prompt, resolution, duration, aspect_ratio, movement_amplitude, seed, user_key)
382
  if not task_id:
383
  return None, message
384
  video_url, status_message = check_task_status(task_id)
 
398
  start_image = gr.Image(type="filepath", label="Hình Ảnh Đầu")
399
  end_image = gr.Image(type="filepath", label="Hình Ảnh Cuối")
400
  prompt_se = gr.Textbox(label="Mô Tả Văn Bản (Tùy Chọn)", placeholder="Ví dụ: 'Chuyển đổi mượt mà từ khung xe thành xe hoàn chỉnh.'")
401
+ resolution_se = gr.Dropdown(choices=["360p", "720p"], label="Độ Phân Giải", value="720p")
402
+ duration_se = gr.Dropdown(choices=[4], label="Thời Lượng (giây)", value=4)
403
  movement_amplitude_se = gr.Dropdown(choices=["auto", "small", "medium", "large"], label="Biên Độ Chuyển Động", value="auto")
404
  seed_se = gr.Number(label="Hạt Giống (Tùy Chọn)", value=None, precision=0)
405
  se_button = gr.Button("Tạo Video")
 
417
  gr.Markdown("Tải lên một hình ảnh và mô tả văn bản để tạo video. Hình ảnh phải là PNG, WebP, JPEG hoặc JPG, kích thước dưới 50MB, tỷ lệ khung hình từ 1:4 đến 4:1.")
418
  image_i2v = gr.Image(type="filepath", label="Hình Ảnh")
419
  prompt_i2v = gr.Textbox(label="Mô Tả Văn Bản (Tùy Chọn)", placeholder="Ví dụ: 'Phi hành gia vẫy tay và camera di chuyển lên.'")
420
+ resolution_i2v = gr.Dropdown(choices=["360p", "720p"], label="Độ Phân Giải", value="720p")
421
+ duration_i2v = gr.Dropdown(choices=[4], label="Thời Lượng (giây)", value=4)
422
  movement_amplitude_i2v = gr.Dropdown(choices=["auto", "small", "medium", "large"], label="Biên Độ Chuyển Động", value="auto")
423
  seed_i2v = gr.Number(label="Hạt Giống (Tùy Chọn)", value=None, precision=0)
424
  i2v_button = gr.Button("Tạo Video")
 
431
  outputs=[i2v_video_output, i2v_message]
432
  )
433
 
434
+ # Tab cho Reference to Video
435
  with gr.Tab("Video Từ Hình Ảnh Tham Chiếu"):
436
+ gr.Markdown("Tải lên 1–3 hình ảnh tham chiếu và mô tả văn bản để tạo video với chủ thể nhất quán. Hình ảnh phải là PNG, WebP, JPEG hoặc JPG, kích thước dưới 50MB, độ phân giải tối thiểu 128x128, tỷ lệ khung hình từ 1:4 đến 4:1.")
437
  image1 = gr.Image(type="filepath", label="Hình Ảnh Tham Chiếu 1")
438
  image2 = gr.Image(type="filepath", label="Hình Ảnh Tham Chiếu 2 (Tùy Chọn)")
439
  image3 = gr.Image(type="filepath", label="Hình Ảnh Tham Chiếu 3 (Tùy Chọn)")
440
+ prompt_ref = gr.Textbox(label="Mô Tả Văn Bản", placeholder="Ví dụ: 'Ông già Noel gấu ôm nhau bên hồ.'")
441
+ resolution_ref = gr.Dropdown(choices=["360p", "720p"], label="Độ Phân Giải", value="720p")
442
+ duration_ref = gr.Dropdown(choices=[4], label="Thời Lượng (giây)", value=4)
443
+ aspect_ratio_ref = gr.Dropdown(choices=["16:9", "9:16", "1:1"], label="Tỷ Lệ Khung Hình", value="16:9")
444
+ movement_amplitude_ref = gr.Dropdown(choices=["auto", "small", "medium", "large"], label="Biên Độ Chuyển Động", value="auto")
445
+ seed_ref = gr.Number(label="Hạt Giống (Tùy Chọn)", value=None, precision=0)
446
  ref_button = gr.Button("Tạo Video")
447
  ref_video_output = gr.Video(label="Video Được Tạo")
448
  ref_message = gr.Textbox(label="Trạng Thái")
449
 
450
  ref_button.click(
451
+ fn=gradio_reference_to_video,
452
+ inputs=[image1, image2, image3, prompt_ref, resolution_ref, duration_ref, aspect_ratio_ref, movement_amplitude_ref, seed_ref, user_key],
453
  outputs=[ref_video_output, ref_message]
454
  )
455