From 74988b290e40155fe2313914e44b979b750e958b Mon Sep 17 00:00:00 2001 From: leejet Date: Mon, 21 Sep 2026 21:48:42 +0800 Subject: [PATCH] fix: reject video models in image generation (#2017) --- docs/troubleshooting.md | 9 +++++++++ docs/wan.md | 2 ++ src/model.h | 8 ++++++++ src/pipeline/image.cpp | 12 +++--------- src/stable-diffusion.cpp | 8 -------- 5 files changed, 22 insertions(+), 17 deletions(-) diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 22007db2..86d42925 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -1,5 +1,14 @@ # Troubleshooting +## Video model used in image generation mode + +If generation reports that a model cannot be run with `generate_image()`, add +`--mode vid_gen` to the CLI command. `--video-frames` alone does not select video +mode. Video models require this mode even when generating a single frame. +Library callers must use `generate_video()` for these models; use +`sd_ctx_supports_image_generation()` and `sd_ctx_supports_video_generation()` to +check the available generation modes. + ## Completely black or white images or videos / NaNs Some ggml backends can encounter numerical overflow during inference, producing diff --git a/docs/wan.md b/docs/wan.md index c7cf1dd9..13c26a20 100644 --- a/docs/wan.md +++ b/docs/wan.md @@ -1,5 +1,7 @@ # How to Use +Wan models require `-M vid_gen`, including single-frame generation. `--video-frames` alone does not select video mode. Library callers must use `generate_video()` instead of `generate_image()`. + ## Download weights - Download Wan diff --git a/src/model.h b/src/model.h index 3fdf1a63..fcba8620 100644 --- a/src/model.h +++ b/src/model.h @@ -252,6 +252,14 @@ static inline bool sd_version_is_sensenova_u1(SDVersion version) { return version == VERSION_SENSENOVA_U1_5; } +static inline bool sd_version_supports_video_generation(SDVersion version) { + return version == VERSION_SVD || sd_version_is_wan(version) || sd_version_is_hunyuan_video(version) || sd_version_is_lingbot_video(version) || sd_version_is_ltxav(version) || sd_version_is_minimax_h3(version); +} + +static inline bool sd_version_supports_image_generation(SDVersion version) { + return !sd_version_supports_video_generation(version); +} + static inline bool sd_version_uses_flux_vae(SDVersion version) { if (sd_version_is_flux(version) || sd_version_is_z_image(version) || sd_version_is_boogu_image(version) || sd_version_is_longcat(version)) { return true; diff --git a/src/pipeline/image.cpp b/src/pipeline/image.cpp index a48d04d1..4c90150e 100644 --- a/src/pipeline/image.cpp +++ b/src/pipeline/image.cpp @@ -789,15 +789,9 @@ namespace sd::pipeline { return false; } - // MiniMax-H3 is video-only. Its denoiser always splits the packed latent into a video and an - // audio half, and only generate_video ever computes the audio length, so reaching this - // function with an H3 checkpoint is guaranteed to die on - // GGML_ASSERT(!audio_input_cache.empty()) with a core dump, after the several minutes it - // takes to load the weights, and with nothing in the output pointing at the missing --mode. - // (The AnimateDiff path below routes vid_gen back through here, but that is SD1.5 plus a - // motion module, never H3.) - if (sd_version_is_minimax_h3(sd->version)) { - LOG_ERROR("MiniMax-H3 is a video model and cannot be run in img_gen mode; use --mode vid_gen"); + if (!sd_version_supports_image_generation(sd->version)) { + LOG_ERROR("%s cannot be run with generate_image(); use generate_video() or --mode vid_gen in the CLI", + model_version_to_str[sd->version]); return false; } diff --git a/src/stable-diffusion.cpp b/src/stable-diffusion.cpp index a8f83336..c533f2cb 100644 --- a/src/stable-diffusion.cpp +++ b/src/stable-diffusion.cpp @@ -630,14 +630,6 @@ struct sd_ctx_t { StableDiffusionGGML* sd = nullptr; }; -static bool sd_version_supports_video_generation(SDVersion version) { - return version == VERSION_SVD || sd_version_is_wan(version) || sd_version_is_hunyuan_video(version) || sd_version_is_lingbot_video(version) || sd_version_is_ltxav(version) || sd_version_is_minimax_h3(version); -} - -static bool sd_version_supports_image_generation(SDVersion version) { - return !sd_version_supports_video_generation(version); -} - sd_ctx_t* new_sd_ctx(const sd_ctx_params_t* sd_ctx_params) { sd_ctx_t* sd_ctx = (sd_ctx_t*)malloc(sizeof(sd_ctx_t)); if (sd_ctx == nullptr) {