|
43 | 43 | ApiEndpoint, |
44 | 44 | download_url_to_image_tensor, |
45 | 45 | download_url_to_video_output, |
| 46 | + downscale_video_to_max_pixels, |
46 | 47 | get_number_of_images, |
47 | 48 | image_tensor_pair_to_batch, |
48 | 49 | poll_op, |
49 | | - resize_video_to_pixel_budget, |
50 | 50 | sync_op, |
51 | 51 | upload_audio_to_comfyapi, |
52 | 52 | upload_image_to_comfyapi, |
53 | 53 | upload_images_to_comfyapi, |
54 | 54 | upload_video_to_comfyapi, |
| 55 | + upscale_video_to_min_pixels, |
55 | 56 | validate_image_aspect_ratio, |
56 | 57 | validate_image_dimensions, |
57 | 58 | validate_string, |
@@ -110,12 +111,13 @@ def _validate_ref_video_pixels(video: Input.Video, model_id: str, resolution: st |
110 | 111 | max_px = limits.get("max") |
111 | 112 | if min_px and pixels < min_px: |
112 | 113 | raise ValueError( |
113 | | - f"Reference video {index} is too small: {w}x{h} = {pixels:,}px. " f"Minimum is {min_px:,}px for this model." |
| 114 | + f"Reference video {index} is too small: {w}x{h} = {pixels:,} total pixels. " |
| 115 | + f"Minimum for this model is {min_px:,} total pixels." |
114 | 116 | ) |
115 | 117 | if max_px and pixels > max_px: |
116 | 118 | raise ValueError( |
117 | | - f"Reference video {index} is too large: {w}x{h} = {pixels:,}px. " |
118 | | - f"Maximum is {max_px:,}px for this model. Try downscaling the video." |
| 119 | + f"Reference video {index} is too large: {w}x{h} = {pixels:,} total pixels. " |
| 120 | + f"Maximum for this model is {max_px:,} total pixels. Try downscaling the video." |
119 | 121 | ) |
120 | 122 |
|
121 | 123 |
|
@@ -1676,14 +1678,14 @@ def define_schema(cls): |
1676 | 1678 | "first_frame_asset_id", |
1677 | 1679 | default="", |
1678 | 1680 | tooltip="Seedance asset_id to use as the first frame. " |
1679 | | - "Mutually exclusive with the first_frame image input.", |
| 1681 | + "Mutually exclusive with the first_frame image input.", |
1680 | 1682 | optional=True, |
1681 | 1683 | ), |
1682 | 1684 | IO.String.Input( |
1683 | 1685 | "last_frame_asset_id", |
1684 | 1686 | default="", |
1685 | 1687 | tooltip="Seedance asset_id to use as the last frame. " |
1686 | | - "Mutually exclusive with the last_frame image input.", |
| 1688 | + "Mutually exclusive with the last_frame image input.", |
1687 | 1689 | optional=True, |
1688 | 1690 | ), |
1689 | 1691 | IO.Int.Input( |
@@ -1865,11 +1867,20 @@ def _seedance2_reference_inputs(resolutions: list[str], default_ratio: str = "16 |
1865 | 1867 | IO.Boolean.Input( |
1866 | 1868 | "auto_downscale", |
1867 | 1869 | default=False, |
1868 | | - advanced=True, |
1869 | 1870 | optional=True, |
1870 | 1871 | tooltip="Automatically downscale reference videos that exceed the model's pixel budget " |
1871 | 1872 | "for the selected resolution. Aspect ratio is preserved; videos already within limits are untouched.", |
1872 | 1873 | ), |
| 1874 | + IO.Boolean.Input( |
| 1875 | + "auto_upscale", |
| 1876 | + default=False, |
| 1877 | + advanced=True, |
| 1878 | + optional=True, |
| 1879 | + tooltip="Automatically upscale reference videos that are below the model's minimum pixel count " |
| 1880 | + "for the selected resolution. Aspect ratio is preserved; videos already meeting the minimum are " |
| 1881 | + "untouched. Note: upscaling a low-resolution source does not add real detail and may produce " |
| 1882 | + "lower-quality generations.", |
| 1883 | + ), |
1873 | 1884 | IO.Autogrow.Input( |
1874 | 1885 | "reference_assets", |
1875 | 1886 | template=IO.Autogrow.TemplateNames( |
@@ -2030,7 +2041,13 @@ async def execute( |
2030 | 2041 | max_px = SEEDANCE2_REF_VIDEO_PIXEL_LIMITS.get(model_id, {}).get(model["resolution"], {}).get("max") |
2031 | 2042 | if max_px: |
2032 | 2043 | for key in reference_videos: |
2033 | | - reference_videos[key] = resize_video_to_pixel_budget(reference_videos[key], max_px) |
| 2044 | + reference_videos[key] = downscale_video_to_max_pixels(reference_videos[key], max_px) |
| 2045 | + |
| 2046 | + if model.get("auto_upscale") and reference_videos: |
| 2047 | + min_px = SEEDANCE2_REF_VIDEO_PIXEL_LIMITS.get(model_id, {}).get(model["resolution"], {}).get("min") |
| 2048 | + if min_px: |
| 2049 | + for key in reference_videos: |
| 2050 | + reference_videos[key] = upscale_video_to_min_pixels(reference_videos[key], min_px) |
2034 | 2051 |
|
2035 | 2052 | total_video_duration = 0.0 |
2036 | 2053 | for i, key in enumerate(reference_videos, 1): |
|
0 commit comments