bewizz commited on
Commit
ae8d7bd
·
verified ·
1 Parent(s): 994053d

Upload folder using huggingface_hub

Browse files
Files changed (2) hide show
  1. app.py +4 -1
  2. sd3.json +184 -273
app.py CHANGED
@@ -10,7 +10,7 @@ import zipfile
10
  from typing import List
11
 
12
  # Define constants
13
- COMFYUI_DIR = r"C:\Users\bewiz\OneDrive\Desktop\AI\ComfyUI_windows_portable\ComfyUI"
14
  WORKFLOW_PATH = os.path.join(COMFYUI_DIR, 'sd3.json')
15
  OUTPUT_DIR = os.path.join(COMFYUI_DIR, 'output')
16
  URL = "http://127.0.0.1:8188/prompt"
@@ -23,6 +23,9 @@ cancel_processing = False
23
 
24
  def read_workflow(file_path):
25
  logging.info(f"Reading workflow from {file_path}")
 
 
 
26
  with open(file_path, 'r') as file:
27
  workflow = json.load(file)
28
  return workflow
 
10
  from typing import List
11
 
12
  # Define constants
13
+ COMFYUI_DIR = r"/mnt/data"
14
  WORKFLOW_PATH = os.path.join(COMFYUI_DIR, 'sd3.json')
15
  OUTPUT_DIR = os.path.join(COMFYUI_DIR, 'output')
16
  URL = "http://127.0.0.1:8188/prompt"
 
23
 
24
  def read_workflow(file_path):
25
  logging.info(f"Reading workflow from {file_path}")
26
+ if not os.path.exists(file_path):
27
+ logging.error(f"Workflow file not found: {file_path}")
28
+ raise FileNotFoundError(f"Workflow file not found: {file_path}")
29
  with open(file_path, 'r') as file:
30
  workflow = json.load(file)
31
  return workflow
sd3.json CHANGED
@@ -1,276 +1,187 @@
1
- import os
2
- import json
3
- import requests
4
- import gradio as gr
5
- import random
6
- import time
7
- import logging
8
- import shutil
9
- import zipfile
10
- from typing import List
11
-
12
- # Define constants
13
- COMFYUI_DIR = r"C:\Users\bewiz\OneDrive\Desktop\AI\ComfyUI_windows_portable\ComfyUI"
14
- WORKFLOW_PATH = os.path.join(COMFYUI_DIR, 'sd3.json')
15
- OUTPUT_DIR = os.path.join(COMFYUI_DIR, 'output')
16
- URL = "http://127.0.0.1:8188/prompt"
17
-
18
- # Configure logging
19
- logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
20
-
21
- # Shared state for cancellation
22
- cancel_processing = False
23
-
24
- def read_workflow(file_path):
25
- logging.info(f"Reading workflow from {file_path}")
26
- with open(file_path, 'r') as file:
27
- workflow = json.load(file)
28
- return workflow
29
-
30
- def update_workflow(workflow, prompt, negative_prompt):
31
- logging.info(f"Updating workflow with new prompts: {prompt}, negative: {negative_prompt}")
32
- workflow["6"]["inputs"]["text"] = prompt
33
- workflow["71"]["inputs"]["text"] = negative_prompt
34
- return workflow
35
-
36
- def write_workflow(workflow, file_path):
37
- logging.info(f"Writing updated workflow to {file_path}")
38
- with open(file_path, 'w') as file:
39
- json.dump(workflow, file, indent=4)
40
-
41
- def send_workflow_to_comfyui(workflow, url):
42
- headers = {"Content-Type": "application/json"}
43
- try:
44
- response = requests.post(url, headers=headers, json={"prompt": workflow})
45
- response.raise_for_status()
46
- logging.info(f"Workflow sent successfully: {response.status_code}")
47
- logging.debug(f"Response content: {response.content}")
48
- except requests.exceptions.RequestException as e:
49
- logging.error(f"Error sending workflow to ComfyUI: {e}")
50
- raise
51
-
52
- def monitor_output_images(output_dir, previous_images, timeout=60):
53
- start_time = time.time()
54
- logging.info(f"Monitoring {output_dir} for new images...")
55
- while time.time() - start_time < timeout:
56
- current_images = os.listdir(output_dir)
57
- new_images = [img for img in current_images if img not in previous_images]
58
- if new_images:
59
- latest_image = new_images[-1]
60
- logging.info(f"New image found: {latest_image}")
61
- return latest_image
62
- time.sleep(1)
63
- logging.info(f"Timeout while waiting for new images in {output_dir}")
64
- return None
65
-
66
- def copy_file_with_retry(src, dst_dir, file_index, retries=5, delay=1):
67
- dst = os.path.join(dst_dir, f"SD3_{file_index:05d}.png")
68
- for _ in range(retries):
69
- try:
70
- shutil.copy(src, dst)
71
- return dst
72
- except PermissionError:
73
- time.sleep(delay)
74
- raise PermissionError(f"Failed to copy {src} to {dst} after {retries} retries")
75
-
76
- def zip_files(output_images: List[str], zip_interval: int, zip_folder: str):
77
- zip_files = []
78
- for i in range(0, len(output_images), zip_interval):
79
- zip_filename = os.path.join(zip_folder, f"images_{i//zip_interval + 1}_{time.time_ns()}.zip")
80
- with zipfile.ZipFile(zip_filename, 'w') as zipf:
81
- for img in output_images[i:i+zip_interval]:
82
- zipf.write(img, os.path.basename(img))
83
- zip_files.append(zip_filename)
84
- return zip_files
85
-
86
- def process_prompts(prompts_text, negative_prompt_text, user_folder, zip_interval):
87
- global cancel_processing
88
- prompts = [line.strip() for line in prompts_text.split('\n\n') if line.strip()]
89
- negative_prompts = [line.strip() for line in negative_prompt_text.split('\n') if line.strip()]
90
- output_images = []
91
- zip_files_list = []
92
- file_index = 1
93
-
94
- workflow = read_workflow(WORKFLOW_PATH)
95
-
96
- total_prompts = len(prompts)
97
- previous_images = os.listdir(OUTPUT_DIR)
98
-
99
- logs = ""
100
-
101
- try:
102
- for i, prompt in enumerate(prompts):
103
- if cancel_processing:
104
- logging.info("Processing cancelled by user.")
105
- break
106
- if not prompt.strip():
107
- continue
108
-
109
- negative_prompt = negative_prompts[i] if i < len(negative_prompts) else ""
110
-
111
- updated_workflow = update_workflow(workflow, prompt, negative_prompt)
112
- write_workflow(updated_workflow, WORKFLOW_PATH)
113
-
114
- logging.debug(f"Updated workflow: {json.dumps(updated_workflow, indent=4)}")
115
-
116
- send_workflow_to_comfyui(updated_workflow, URL)
117
- logging.info(f"Sent workflow to ComfyUI for prompt {i + 1}/{total_prompts}")
118
-
119
- new_image = None
120
- retries = 0
121
- while new_image is None and retries < 5:
122
- new_image = monitor_output_images(OUTPUT_DIR, previous_images)
123
- if new_image is None:
124
- retries += 1
125
- logging.warning(f"Retrying ({retries}/5)...")
126
- time.sleep(5)
127
- else:
128
- time.sleep(2)
129
-
130
- if new_image is None:
131
- logging.error("Error monitoring output images: Timed out waiting for new image.")
132
- continue
133
-
134
- new_image_path = os.path.join(OUTPUT_DIR, new_image)
135
- try:
136
- copied_image_path = copy_file_with_retry(new_image_path, user_folder, file_index)
137
- logging.info(f"New image generated and copied to user folder: {copied_image_path}")
138
- except PermissionError as e:
139
- logging.error(f"Failed to copy file after retries: {e}")
140
- continue
141
-
142
- output_images.append(copied_image_path)
143
- previous_images.append(new_image)
144
- file_index += 1
145
-
146
- if len(output_images) % zip_interval == 0 and not cancel_processing:
147
- zip_folder = os.path.join(user_folder, "zipped_images")
148
- os.makedirs(zip_folder, exist_ok=True)
149
- new_zip_files = zip_files(output_images[-zip_interval:], zip_interval, zip_folder)
150
- zip_files_list.extend(new_zip_files)
151
-
152
- logs += f"Processed {i + 1}/{total_prompts} - Done: {i + 1}, Left: {total_prompts - (i + 1)}\n"
153
- yield output_images, zip_files_list, logs
154
-
155
- if cancel_processing or (len(output_images) % zip_interval != 0):
156
- zip_folder = os.path.join(user_folder, "zipped_images")
157
- os.makedirs(zip_folder, exist_ok=True)
158
- new_zip_files = zip_files(output_images, zip_interval, zip_folder)
159
- zip_files_list.extend(new_zip_files)
160
-
161
- except KeyboardInterrupt:
162
- logging.info("Script interrupted by user.")
163
-
164
- return output_images, zip_files_list
165
-
166
- def cancel_processing_fn():
167
- global cancel_processing
168
- cancel_processing = True
169
-
170
- def reset_cancel_processing_fn():
171
- global cancel_processing
172
- cancel_processing = False
173
-
174
- def main():
175
- with gr.Blocks(css="""
176
- .gradio-container {font-family: Arial, sans-serif;}
177
- .psychedelic-text span {
178
- animation: colorchange 10s infinite;
179
  }
180
- @keyframes colorchange {
181
- 0% { color: #ff69b4; }
182
- 10% { color: #ba55d3; }
183
- 20% { color: #7b68ee; }
184
- 30% { color: #00bfff; }
185
- 40% { color: #3cb371; }
186
- 50% { color: #ffff54; }
187
- 60% { color: #ffa500; }
188
- 70% { color: #ff4500; }
189
- 80% { color: #ff1493; }
190
- 90% { color: #da70d6; }
191
- 100% { color: #ff69b4; }
192
  }
193
- .image-container img {
194
- width: 250px;
195
- height: 250px;
 
 
 
 
 
 
 
 
 
196
  }
197
- """) as demo:
198
- with gr.Row():
199
- with gr.Column(scale=1):
200
- gr.Markdown("### beWiZ's GroOvy SD3 Batch Imagine")
201
- gr.HTML('<div class="image-container"><img src="https://raw.githubusercontent.com/downlifted/Groovy-StyleSuite/main/groovy.png" alt="GroOvy - SD3 Batch Imagine Logo"></div>')
202
- with gr.Accordion("Developer Information", open=False):
203
- gr.Markdown("### Made by BeWiZ")
204
- gr.Markdown('<div class="image-container"><a href="https://twitter.com/AiAnarchist"><img src="https://raw.githubusercontent.com/downlifted/pictoprompt/master/aia.png" alt="BeWiZ Logo"></a></div>')
205
- gr.Markdown("Contact: [downlifted@gmail.com](mailto:downlifted@gmail.com)")
206
- gr.Markdown("Twitter: [@AiAnarchist](https://x.com/AiAnarchist)")
207
- with gr.Accordion("About SD3 Batch Imagine", open=False):
208
- gr.Markdown("""
209
- ### SD3 Batch Imagine: Batch Image Generation
210
- Produce large batches of images using the latest SD3 Medium model. This tool allows you to generate images quickly and efficiently.
211
- - **ComfyUI**: For seamless integration and image processing.
212
- - **Hugging Face**: For state-of-the-art language models.
213
- - **Gradio**: For an intuitive user interface.
214
- """)
215
-
216
- with gr.Accordion("Instructions", open=True):
217
- gr.Markdown("""
218
- **SD3 Batch Imagine Instructions**
219
- - Enter your prompts below, one per empty line.
220
- - Enter your negative prompts below, one per line. (Optional)
221
- - Set the zip interval to determine how many images will be included in each zip file.
222
- - Click "Process Prompts" to start generating images.
223
- - Click "Cancel Processing" to stop the current batch run.
224
- - Watch the progress as images are generated in real-time.
225
- - At the end of the process, zip files containing your images will be available for download.
226
- """)
227
-
228
- with gr.Column(scale=2):
229
- gr.Markdown("### Enter Prompts")
230
- prompts_text = gr.Textbox(lines=20, placeholder="Enter your prompts here, one per empty line.", label="Prompts")
231
- negative_prompts_text = gr.Textbox(lines=5, placeholder="Enter your negative prompts here, one per line.", label="Negative Prompts")
232
- zip_interval = gr.Number(value=10, label="Zip Interval", precision=0)
233
- process_btn = gr.Button("Process Prompts")
234
- cancel_btn = gr.Button("Cancel Processing")
235
- progress_text = gr.Markdown("Progress")
236
- gallery_output = gr.Gallery(label="Generated Images")
237
- zip_files_output = gr.Files(label="Zip Files")
238
-
239
- with gr.Column(scale=1):
240
- gr.Markdown("### Detailed Logs")
241
- logs_output = gr.Textbox(lines=10, interactive=False, label="Logs")
242
-
243
- def generate_user_folder():
244
- user_folder = os.path.normpath(os.path.join(OUTPUT_DIR, f'SD3{random.randint(1000, 9999)}'))
245
- os.makedirs(user_folder, exist_ok=True)
246
- logging.info(f"Generated user folder: {user_folder}")
247
- return user_folder
248
-
249
- def on_click(prompts_text, negative_prompts_text, zip_interval):
250
- reset_cancel_processing_fn()
251
- user_folder = generate_user_folder()
252
- output_images, zip_files_list = [], []
253
- logs = ""
254
- for images, zip_files, log_msg in process_prompts(prompts_text, negative_prompts_text, user_folder, zip_interval):
255
- output_images = images
256
- zip_files_list = zip_files
257
- logs = log_msg
258
- yield images, zip_files_list, logs
259
- return output_images, zip_files_list, logs
260
-
261
- process_btn.click(
262
- fn=on_click,
263
- inputs=[prompts_text, negative_prompts_text, zip_interval],
264
- outputs=[gallery_output, zip_files_output, logs_output]
265
- )
266
-
267
- cancel_btn.click(
268
- fn=cancel_processing_fn,
269
- inputs=[],
270
- outputs=[]
271
- )
272
-
273
- demo.launch(share=True)
274
-
275
- if __name__ == "__main__":
276
- main()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "6": {
3
+ "inputs": {
4
+ "text": "\"A graffiti art comparison featuring the word 'Creativity' across three different styles. First, SD1.5: a simple graffiti-style text on a plain urban wall, with basic lettering and minimal background details. BAD QUALITY.. labeled in words \"SD 1.5\" \n\nSecond, SDXL: detailed graffiti art on a vibrant wall, with bold colors, stylish fonts, and some 3D elements that add depth and creativity. GOOD QUALITY - LABELED in words \"SDXL\"\n\nThird, SD3: ultra-realistic graffiti with dynamic and intricate textures, shadows, and depth. The word 'Creativity' appears to pop out from the wall, with advanced 3D effects and lifelike details, creating a stunning visual impact.\" AMAZING QUALITY TEXT \"SD3\"\n\n",
5
+ "clip": [
6
+ "11",
7
+ 0
8
+ ]
9
+ },
10
+ "class_type": "CLIPTextEncode",
11
+ "_meta": {
12
+ "title": "CLIP Text Encode (Prompt)"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  }
14
+ },
15
+ "11": {
16
+ "inputs": {
17
+ "clip_name1": "clip_g.safetensors",
18
+ "clip_name2": "clip_l.safetensors",
19
+ "clip_name3": "t5xxl_fp16.safetensors"
20
+ },
21
+ "class_type": "TripleCLIPLoader",
22
+ "_meta": {
23
+ "title": "TripleCLIPLoader"
 
 
24
  }
25
+ },
26
+ "13": {
27
+ "inputs": {
28
+ "shift": 3,
29
+ "model": [
30
+ "252",
31
+ 0
32
+ ]
33
+ },
34
+ "class_type": "ModelSamplingSD3",
35
+ "_meta": {
36
+ "title": "ModelSamplingSD3"
37
  }
38
+ },
39
+ "67": {
40
+ "inputs": {
41
+ "conditioning": [
42
+ "71",
43
+ 0
44
+ ]
45
+ },
46
+ "class_type": "ConditioningZeroOut",
47
+ "_meta": {
48
+ "title": "ConditioningZeroOut"
49
+ }
50
+ },
51
+ "68": {
52
+ "inputs": {
53
+ "start": 0.1,
54
+ "end": 1,
55
+ "conditioning": [
56
+ "67",
57
+ 0
58
+ ]
59
+ },
60
+ "class_type": "ConditioningSetTimestepRange",
61
+ "_meta": {
62
+ "title": "ConditioningSetTimestepRange"
63
+ }
64
+ },
65
+ "69": {
66
+ "inputs": {
67
+ "conditioning_1": [
68
+ "68",
69
+ 0
70
+ ],
71
+ "conditioning_2": [
72
+ "70",
73
+ 0
74
+ ]
75
+ },
76
+ "class_type": "ConditioningCombine",
77
+ "_meta": {
78
+ "title": "Conditioning (Combine)"
79
+ }
80
+ },
81
+ "70": {
82
+ "inputs": {
83
+ "start": 0,
84
+ "end": 0.4533332519531249,
85
+ "conditioning": [
86
+ "71",
87
+ 0
88
+ ]
89
+ },
90
+ "class_type": "ConditioningSetTimestepRange",
91
+ "_meta": {
92
+ "title": "ConditioningSetTimestepRange"
93
+ }
94
+ },
95
+ "71": {
96
+ "inputs": {
97
+ "text": "bad quality, poor quality, doll, disfigured, jpg, toy, bad anatomy, missing limbs, missing fingers, 3d, cgi",
98
+ "clip": [
99
+ "11",
100
+ 0
101
+ ]
102
+ },
103
+ "class_type": "CLIPTextEncode",
104
+ "_meta": {
105
+ "title": "CLIP Text Encode (Negative Prompt)"
106
+ }
107
+ },
108
+ "135": {
109
+ "inputs": {
110
+ "width": 1024,
111
+ "height": 1024,
112
+ "batch_size": 1
113
+ },
114
+ "class_type": "EmptySD3LatentImage",
115
+ "_meta": {
116
+ "title": "EmptySD3LatentImage"
117
+ }
118
+ },
119
+ "231": {
120
+ "inputs": {
121
+ "samples": [
122
+ "271",
123
+ 0
124
+ ],
125
+ "vae": [
126
+ "252",
127
+ 2
128
+ ]
129
+ },
130
+ "class_type": "VAEDecode",
131
+ "_meta": {
132
+ "title": "VAE Decode"
133
+ }
134
+ },
135
+ "252": {
136
+ "inputs": {
137
+ "ckpt_name": "3\\sd3_medium_incl_clips_t5xxlfp8.safetensors"
138
+ },
139
+ "class_type": "CheckpointLoaderSimple",
140
+ "_meta": {
141
+ "title": "Load Checkpoint"
142
+ }
143
+ },
144
+ "271": {
145
+ "inputs": {
146
+ "seed": 945512652412924,
147
+ "steps": 28,
148
+ "cfg": 4.5,
149
+ "sampler_name": "dpmpp_2m",
150
+ "scheduler": "sgm_uniform",
151
+ "denoise": 1,
152
+ "model": [
153
+ "13",
154
+ 0
155
+ ],
156
+ "positive": [
157
+ "6",
158
+ 0
159
+ ],
160
+ "negative": [
161
+ "69",
162
+ 0
163
+ ],
164
+ "latent_image": [
165
+ "135",
166
+ 0
167
+ ]
168
+ },
169
+ "class_type": "KSampler",
170
+ "_meta": {
171
+ "title": "KSampler"
172
+ }
173
+ },
174
+ "273": {
175
+ "inputs": {
176
+ "filename_prefix": "SD3",
177
+ "images": [
178
+ "231",
179
+ 0
180
+ ]
181
+ },
182
+ "class_type": "SaveImage",
183
+ "_meta": {
184
+ "title": "Save Image"
185
+ }
186
+ }
187
+ }