Spaces:
Paused
Paused
feat: preserve original video fps by reusing the input fps in AniDoc generation and final resized output
Browse files- 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=
|
| 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]
|