fffiloni commited on
Commit
9bf20a6
·
verified ·
1 Parent(s): ac52ec9

feat: preserve original video fps by reusing the input fps in AniDoc generation and final resized output

Browse files
Files changed (1) hide show
  1. gradio_app.py +22 -2
gradio_app.py CHANGED
@@ -188,7 +188,7 @@ def cleanup_runtime_models(models) -> None:
188
  pass
189
 
190
  # -----------------------------------------------------------------------------
191
- # Video post-processing
192
  # -----------------------------------------------------------------------------
193
 
194
  def get_video_dimensions(video_path: str) -> tuple[int, int]:
@@ -206,11 +206,26 @@ def get_video_dimensions(video_path: str) -> tuple[int, int]:
206
  return width, height
207
 
208
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
  def resize_output_video_to_input_size(
210
  output_video_path: str,
211
  input_video_path: str,
212
  ) -> str:
213
  target_width, target_height = get_video_dimensions(input_video_path)
 
214
  resized_output_path = os.path.splitext(output_video_path)[0] + "_resized.mp4"
215
 
216
  cmd = [
@@ -218,6 +233,7 @@ def resize_output_video_to_input_size(
218
  "-y",
219
  "-i", output_video_path,
220
  "-vf", f"scale={target_width}:{target_height}",
 
221
  "-c:v", "libx264",
222
  "-pix_fmt", "yuv420p",
223
  resized_output_path,
@@ -437,6 +453,10 @@ def run_anidoc(
437
  max_points=max_points,
438
  )
439
 
 
 
 
 
440
  generator = torch.manual_seed(seed)
441
 
442
  with torch.inference_mode():
@@ -448,7 +468,7 @@ def run_anidoc(
448
  num_frames=num_frames,
449
  decode_chunk_size=DEFAULT_DECODE_CHUNK_SIZE,
450
  motion_bucket_id=DEFAULT_MOTION_BUCKET_ID,
451
- fps=DEFAULT_FPS,
452
  noise_aug_strength=DEFAULT_NOISE_AUG,
453
  generator=generator,
454
  ).frames[0]
 
188
  pass
189
 
190
  # -----------------------------------------------------------------------------
191
+ # Video metadata / post-processing
192
  # -----------------------------------------------------------------------------
193
 
194
  def get_video_dimensions(video_path: str) -> tuple[int, int]:
 
206
  return width, height
207
 
208
 
209
+ def get_video_fps(video_path: str) -> float:
210
+ cap = cv2.VideoCapture(video_path)
211
+ if not cap.isOpened():
212
+ raise ValueError(f"Unable to open input video: {video_path}")
213
+
214
+ fps = cap.get(cv2.CAP_PROP_FPS)
215
+ cap.release()
216
+
217
+ if fps <= 0:
218
+ fps = DEFAULT_FPS
219
+
220
+ return round(float(fps), 2)
221
+
222
+
223
  def resize_output_video_to_input_size(
224
  output_video_path: str,
225
  input_video_path: str,
226
  ) -> str:
227
  target_width, target_height = get_video_dimensions(input_video_path)
228
+ target_fps = get_video_fps(input_video_path)
229
  resized_output_path = os.path.splitext(output_video_path)[0] + "_resized.mp4"
230
 
231
  cmd = [
 
233
  "-y",
234
  "-i", output_video_path,
235
  "-vf", f"scale={target_width}:{target_height}",
236
+ "-r", str(target_fps),
237
  "-c:v", "libx264",
238
  "-pix_fmt", "yuv420p",
239
  resized_output_path,
 
453
  max_points=max_points,
454
  )
455
 
456
+ input_fps = DEFAULT_FPS
457
+ if control_path.lower().endswith(".mp4"):
458
+ input_fps = get_video_fps(control_path)
459
+
460
  generator = torch.manual_seed(seed)
461
 
462
  with torch.inference_mode():
 
468
  num_frames=num_frames,
469
  decode_chunk_size=DEFAULT_DECODE_CHUNK_SIZE,
470
  motion_bucket_id=DEFAULT_MOTION_BUCKET_ID,
471
+ fps=input_fps,
472
  noise_aug_strength=DEFAULT_NOISE_AUG,
473
  generator=generator,
474
  ).frames[0]