|
44 | 44 | ApiEndpoint, |
45 | 45 | download_url_to_image_tensor, |
46 | 46 | download_url_to_video_output, |
| 47 | + downscale_image_tensor_by_max_side, |
47 | 48 | downscale_video_to_max_pixels, |
48 | 49 | get_number_of_images, |
49 | 50 | image_tensor_pair_to_batch, |
@@ -122,6 +123,14 @@ def _validate_ref_video_pixels(video: Input.Video, model_id: str, resolution: st |
122 | 123 | ) |
123 | 124 |
|
124 | 125 |
|
| 126 | +def _prepare_seedance_image(image: Input.Image) -> Input.Image: |
| 127 | + """Auto-downscale a Seedance image input to the per-side limits, then validate it.""" |
| 128 | + validate_image_aspect_ratio(image, (2, 5), (5, 2), strict=False) # 0.4 to 2.5 |
| 129 | + image = downscale_image_tensor_by_max_side(image, max_side=6000) |
| 130 | + validate_image_dimensions(image, min_width=300, min_height=300, max_width=6000, max_height=6000) |
| 131 | + return image |
| 132 | + |
| 133 | + |
125 | 134 | async def _resolve_reference_assets( |
126 | 135 | cls: type[IO.ComfyNode], |
127 | 136 | asset_ids: list[str], |
@@ -1781,6 +1790,11 @@ async def execute( |
1781 | 1790 | if last_frame is not None and last_frame_asset_id: |
1782 | 1791 | raise ValueError("Provide only one of last_frame or last_frame_asset_id, not both.") |
1783 | 1792 |
|
| 1793 | + if first_frame is not None: |
| 1794 | + first_frame = _prepare_seedance_image(first_frame) |
| 1795 | + if last_frame is not None: |
| 1796 | + last_frame = _prepare_seedance_image(last_frame) |
| 1797 | + |
1784 | 1798 | asset_ids_to_resolve = [a for a in (first_frame_asset_id, last_frame_asset_id) if a] |
1785 | 1799 | image_assets: dict[str, str] = {} |
1786 | 1800 | if asset_ids_to_resolve: |
@@ -1887,7 +1901,7 @@ def _seedance2_reference_inputs(resolutions: list[str], default_ratio: str = "16 |
1887 | 1901 | ), |
1888 | 1902 | IO.Boolean.Input( |
1889 | 1903 | "auto_downscale", |
1890 | | - default=False, |
| 1904 | + default=True, |
1891 | 1905 | optional=True, |
1892 | 1906 | tooltip="Automatically downscale reference videos that exceed the model's pixel budget " |
1893 | 1907 | "for the selected resolution. Aspect ratio is preserved; videos already within limits are untouched.", |
@@ -2055,6 +2069,9 @@ async def execute( |
2055 | 2069 | f"(audios={len(reference_audios)}, audio assets={len(reference_audio_assets)}). Maximum is 3." |
2056 | 2070 | ) |
2057 | 2071 |
|
| 2072 | + for key in reference_images: |
| 2073 | + reference_images[key] = _prepare_seedance_image(reference_images[key]) |
| 2074 | + |
2058 | 2075 | model_id = SEEDANCE_MODELS[model["model"]] |
2059 | 2076 | has_video_input = total_videos > 0 |
2060 | 2077 |
|
|
0 commit comments