support final frame

This commit is contained in:
Concedo 2026-05-30 09:27:51 +08:00
parent c30a386932
commit 5dc1a89001
3 changed files with 18 additions and 2 deletions

View file

@ -256,6 +256,7 @@ struct sd_generation_outputs
int animated = 0;
const char * data = "";
const char * data_extra = "";
const char * final_frame = ""; //for videos to allow extend
const char * info = "";
};
struct sd_upscale_inputs

View file

@ -438,6 +438,7 @@ class sd_generation_outputs(ctypes.Structure):
("animated", ctypes.c_int),
("data", ctypes.c_char_p),
("data_extra", ctypes.c_char_p),
("final_frame", ctypes.c_char_p),
("info", ctypes.c_char_p)]
class sd_upscale_inputs(ctypes.Structure):
@ -2859,15 +2860,17 @@ def sd_generate(genparams):
ret = handle.sd_generate(inputs)
data_main = ""
data_extra = ""
final_frame = ""
info = {}
animated = False
if ret.status==1:
data_main = ret.data.decode("UTF-8","ignore")
data_extra = ret.data_extra.decode("UTF-8","ignore")
final_frame = ret.final_frame.decode("UTF-8","ignore")
info = json.loads(ret.info.decode("UTF-8","ignore"))
animated = True if ret.animated else False
info["job_timestamp"] = job_timestamp
return {"animated": animated, "data":data_main, "data_extra":data_extra, "info": info}
return {"animated": animated, "data":data_main, "data_extra":data_extra, "final_frame":final_frame, "info": info}
def whisper_load_model(model_filename):
@ -6936,6 +6939,7 @@ Change Mode<br>
gendat = gen["data"]
genanim = gen["animated"]
gendatextra = gen["data_extra"]
genfinalframe = gen["final_frame"]
geninfo = json.dumps(gen["info"]) # sdapi really expects a stringified JSON
genresp = None
if is_comfyui_imggen:
@ -6947,7 +6951,7 @@ Change Mode<br>
elif is_oai_imggen:
genresp = (json.dumps({"created":int(time.time()),"data":[{"b64_json":gendat}],"background":"opaque","output_format":"png","size":"1024x1024","quality":"medium"}).encode())
else:
genresp = (json.dumps({"images":[gendat],"parameters":{},"info":geninfo,"animated":genanim,"extra_data":gendatextra}).encode())
genresp = (json.dumps({"images":[gendat],"parameters":{},"info":geninfo,"animated":genanim,"extra_data":gendatextra, "final_frame":genfinalframe}).encode())
self.send_response(200)
self.send_header('content-length', str(len(genresp)))
self.end_headers(content_type='application/json')

View file

@ -161,11 +161,13 @@ static bool remove_limits = false;
static struct {
std::string data;
std::string data_extra;
std::string final_frame;
std::string info;
bool animated;
void reset() {
data = "";
data_extra = "";
final_frame = "";
info = "{}";
animated = false;
}
@ -174,6 +176,7 @@ static struct {
output.status = status;
output.data = data.c_str();
output.data_extra = data_extra.c_str();
output.final_frame = final_frame.c_str();
output.info = info.c_str();
output.animated = animated;
return output;
@ -1529,6 +1532,7 @@ sd_generation_outputs sdtype_generate(const sd_generation_inputs inputs)
upscaled_image.data = nullptr;
std::string gen_data;
std::string gen_data2;
std::string final_frame_data;
if (is_passthrough)
{
@ -1573,6 +1577,12 @@ sd_generation_outputs sdtype_generate(const sd_generation_inputs inputs)
status2 = create_mjpg_avi_membuf_from_sd_images(results, generated_num_results, vid_fps, 40, &out_data2,&out_len2, generated_audio);
}
if(generated_num_results>1)
{
sd_image_t *final_frame_image = &results[generated_num_results-1];
final_frame_data = raw_image_to_png_base64(*final_frame_image);
}
if(!sd_is_quiet && sddebugmode==1)
{
printf("Video Output Sizes: GIF=%zu AVI=%zu\n",out_len,out_len2);
@ -1641,6 +1651,7 @@ sd_generation_outputs sdtype_generate(const sd_generation_inputs inputs)
sd_generation.data = gen_data;
sd_generation.data_extra = gen_data2;
sd_generation.final_frame = final_frame_data;
sd_generation.animated = isanim;
sd_generation.info = jsoninfo.dump();
return sd_generation.outputs(1);