fix: reject video models in image generation (#2017)

This commit is contained in:
leejet 2026-09-21 21:48:42 +08:00 committed by GitHub
parent c678dfe704
commit 74988b290e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 22 additions and 17 deletions

View File

@ -1,5 +1,14 @@
# Troubleshooting # 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 ## Completely black or white images or videos / NaNs
Some ggml backends can encounter numerical overflow during inference, producing Some ggml backends can encounter numerical overflow during inference, producing

View File

@ -1,5 +1,7 @@
# How to Use # 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 weights
- Download Wan - Download Wan

View File

@ -252,6 +252,14 @@ static inline bool sd_version_is_sensenova_u1(SDVersion version) {
return version == VERSION_SENSENOVA_U1_5; 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) { 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)) { 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; return true;

View File

@ -789,15 +789,9 @@ namespace sd::pipeline {
return false; return false;
} }
// MiniMax-H3 is video-only. Its denoiser always splits the packed latent into a video and an if (!sd_version_supports_image_generation(sd->version)) {
// audio half, and only generate_video ever computes the audio length, so reaching this LOG_ERROR("%s cannot be run with generate_image(); use generate_video() or --mode vid_gen in the CLI",
// function with an H3 checkpoint is guaranteed to die on model_version_to_str[sd->version]);
// 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");
return false; return false;
} }

View File

@ -630,14 +630,6 @@ struct sd_ctx_t {
StableDiffusionGGML* sd = nullptr; 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* new_sd_ctx(const sd_ctx_params_t* sd_ctx_params) {
sd_ctx_t* sd_ctx = (sd_ctx_t*)malloc(sizeof(sd_ctx_t)); sd_ctx_t* sd_ctx = (sd_ctx_t*)malloc(sizeof(sd_ctx_t));
if (sd_ctx == nullptr) { if (sd_ctx == nullptr) {