diff --git a/localAPIRun.py b/localAPIRun.py new file mode 100644 index 0000000..6d033ba --- /dev/null +++ b/localAPIRun.py @@ -0,0 +1,163 @@ +from datetime import datetime +import urllib.request +import base64 +import json +import time +import os +url="pop-os.local" +webui_server_url = f'http://{url}:7860' + +out_dir = 'api_out' +out_dir_t2i = os.path.join(out_dir, 'txt2img') +out_dir_i2i = os.path.join(out_dir, 'img2img') +os.makedirs(out_dir_t2i, exist_ok=True) +os.makedirs(out_dir_i2i, exist_ok=True) + + +def timestamp(): + return datetime.fromtimestamp(time.time()).strftime("%Y%m%d-%H%M%S") + + +def encode_file_to_base64(path): + with open(path, 'rb') as file: + return base64.b64encode(file.read()).decode('utf-8') + + +def decode_and_save_base64(base64_str, save_path): + with open(save_path, "wb") as file: + file.write(base64.b64decode(base64_str)) + + +def call_api(api_endpoint, **payload): + data = json.dumps(payload).encode('utf-8') + request = urllib.request.Request( + f'{webui_server_url}/{api_endpoint}', + headers={'Content-Type': 'application/json'}, + data=data, + ) + response = urllib.request.urlopen(request) + return json.loads(response.read().decode('utf-8')) + + +def call_txt2img_api(**payload): + response = call_api('sdapi/v1/txt2img', **payload) + for index, image in enumerate(response.get('images')): + save_path = os.path.join(out_dir_t2i, f'txt2img-{timestamp()}-{index}.png') + decode_and_save_base64(image, save_path) + + +def call_img2img_api(**payload): + response = call_api('sdapi/v1/img2img', **payload) + for index, image in enumerate(response.get('images')): + save_path = os.path.join(out_dir_i2i, f'img2img-{timestamp()}-{index}.png') + decode_and_save_base64(image, save_path) + + +if __name__ == '__main__': + payload = { + "prompt": "masterpiece, (best quality:1.1), 1girl ", # extra networks also in prompts + "negative_prompt": "", + "seed": 1, + "steps": 20, + "width": 512, + "height": 512, + "cfg_scale": 7, + "sampler_name": "DPM++ 2M", + "n_iter": 1, + "batch_size": 1, + + # example args for x/y/z plot + # "script_name": "x/y/z plot", + # "script_args": [ + # 1, + # "10,20", + # [], + # 0, + # "", + # [], + # 0, + # "", + # [], + # True, + # True, + # False, + # False, + # 0, + # False + # ], + + # example args for Refiner and ControlNet + # "alwayson_scripts": { + # "ControlNet": { + # "args": [ + # { + # "batch_images": "", + # "control_mode": "Balanced", + # "enabled": True, + # "guidance_end": 1, + # "guidance_start": 0, + # "image": { + # "image": encode_file_to_base64(r"B:\path\to\control\img.png"), + # "mask": None # base64, None when not need + # }, + # "input_mode": "simple", + # "is_ui": True, + # "loopback": False, + # "low_vram": False, + # "model": "control_v11p_sd15_canny [d14c016b]", + # "module": "canny", + # "output_dir": "", + # "pixel_perfect": False, + # "processor_res": 512, + # "resize_mode": "Crop and Resize", + # "threshold_a": 100, + # "threshold_b": 200, + # "weight": 1 + # } + # ] + # }, + # "Refiner": { + # "args": [ + # True, + # "sd_xl_refiner_1.0", + # 0.5 + # ] + # } + # }, + # "enable_hr": True, + # "hr_upscaler": "R-ESRGAN 4x+ Anime6B", + # "hr_scale": 2, + # "denoising_strength": 0.5, + # "styles": ['style 1', 'style 2'], + # "override_settings": { + # 'sd_model_checkpoint': "sd_xl_base_1.0", # this can use to switch sd model + # }, + } + call_txt2img_api(**payload) + + init_images = [ + encode_file_to_base64(r"../stable-diffusion-webui/output/img2img-images/2024-05-15/00012-357584826.png"), + # encode_file_to_base64(r"B:\path\to\img_2.png"), + # "https://image.can/also/be/a/http/url.png", + ] + + batch_size = 2 + payload = { + "prompt": "1girl, blue hair", + "seed": 1, + "steps": 20, + "width": 512, + "height": 512, + "denoising_strength": 0.5, + "n_iter": 1, + "init_images": init_images, + "batch_size": batch_size if len(init_images) == 1 else len(init_images), + # "mask": encode_file_to_base64(r"B:\path\to\mask.png") + } + # if len(init_images) > 1 then batch_size should be == len(init_images) + # else if len(init_images) == 1 then batch_size can be any value int >= 1 + call_img2img_api(**payload) + + # there exist a useful extension that allows converting of webui calls to api payload + # particularly useful when you wish setup arguments of extensions and scripts + # https://github.com/huchenlei/sd-webui-api-payload-display