mirror of
				https://github.com/karl0ss/ai_image_frame_server.git
				synced 2025-10-31 14:44:09 +00:00 
			
		
		
		
	initial commit
This commit is contained in:
		
						commit
						6ada0bfb18
					
				
							
								
								
									
										9
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| venv/* | ||||
| script.log | ||||
| **/*.pyc | ||||
| *.rtf | ||||
| build/ | ||||
| dist/ | ||||
| user_config.cfg | ||||
| Dockerfile | ||||
| output/**.* | ||||
							
								
								
									
										1
									
								
								.python-version
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.python-version
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| 3.11.9 | ||||
							
								
								
									
										24
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| { | ||||
|     // Use IntelliSense to learn about possible attributes. | ||||
|     // Hover to view descriptions of existing attributes. | ||||
|     // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||||
|     "version": "0.2.0", | ||||
|     "configurations": [ | ||||
|         { | ||||
|             "name": "Python Debugger: Current File", | ||||
|             "type": "debugpy", | ||||
|             "request": "launch", | ||||
|             "program": "${file}", | ||||
|             "console": "integratedTerminal", | ||||
|             "justMyCode": false, | ||||
|             // "args": [ | ||||
|             //     "--num_inference_steps", | ||||
|             //     "6", | ||||
|             //     "--rtf_file", | ||||
|             //     "./AllInDB.rtf", | ||||
|             //     "--player_uuid", | ||||
|             //     "2000252303" | ||||
|             // ] | ||||
|         } | ||||
|     ] | ||||
| } | ||||
							
								
								
									
										35
									
								
								ai_frame_image_server.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								ai_frame_image_server.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,35 @@ | ||||
| from flask import Flask, render_template, send_from_directory, redirect, url_for | ||||
| import os | ||||
| from lib import create_image | ||||
| 
 | ||||
| app = Flask(__name__) | ||||
| 
 | ||||
| image_folder = "./output" | ||||
| 
 | ||||
| def get_latest_image(): | ||||
|     """Get the latest image file from the directory.""" | ||||
|     files = [f for f in os.listdir(image_folder) if f.endswith(('.png', '.jpg', '.jpeg'))] | ||||
|     if not files: | ||||
|         return None | ||||
|     latest_file = max(files, key=lambda f: os.path.getmtime(os.path.join(image_folder, f))) | ||||
|     return latest_file | ||||
| 
 | ||||
| 
 | ||||
| @app.route('/') | ||||
| def index(): | ||||
|     latest_image = get_latest_image() | ||||
|     return render_template("index.html", image=latest_image) | ||||
| 
 | ||||
| @app.route('/images/<filename>') | ||||
| def images(filename): | ||||
|     return send_from_directory(image_folder, filename) | ||||
| 
 | ||||
| @app.route('/create') | ||||
| def create(): | ||||
|     """Endpoint to create a new image.""" | ||||
|     create_image() | ||||
|     return redirect(url_for("index")) | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     os.makedirs(image_folder, exist_ok=True)  # Ensure the folder exists | ||||
|     app.run(debug=True) | ||||
							
								
								
									
										76
									
								
								lib.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								lib.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,76 @@ | ||||
| import random | ||||
| import configparser | ||||
| import logging | ||||
| import sys | ||||
| import litellm | ||||
| import time | ||||
| 
 | ||||
| from datetime import datetime | ||||
| 
 | ||||
| from comfy_api_simplified import ComfyApiWrapper, ComfyWorkflowWrapper | ||||
| 
 | ||||
| user_config = configparser.ConfigParser() | ||||
| try: | ||||
|     user_config.read("./user_config.cfg") | ||||
|     output_folder = user_config["comfyui"]["output_dir"] | ||||
|     logging.debug("Configuration loaded successfully.") | ||||
| except KeyError as e: | ||||
|     logging.error(f"Missing configuration key: {e}") | ||||
|     sys.exit(1) | ||||
| 
 | ||||
| 
 | ||||
| def send_prompt_to_openwebui(prompt): | ||||
|     response = litellm.completion( | ||||
|         api_base=user_config["openwebui"]["base_url"], | ||||
|         model="openai/" + user_config["openwebui"]["model"], | ||||
|         messages=[ | ||||
|             { | ||||
|                 "role": "user", | ||||
|                 "content": prompt, | ||||
|             } | ||||
|         ], | ||||
|         api_key=user_config["openwebui"]["api_key"], | ||||
|     ) | ||||
| 
 | ||||
|     return response["choices"][0]["message"]["content"].strip('"') | ||||
| 
 | ||||
| 
 | ||||
| def generate_image(file_name, comfy_prompt): | ||||
|     """Generate an image using the Comfy API.""" | ||||
|     try: | ||||
|         # Initialize API and workflow | ||||
|         api = ComfyApiWrapper(user_config["comfyui"]["comfyui_url"]) | ||||
|         wf = ComfyWorkflowWrapper("./workflow_api.json") | ||||
| 
 | ||||
|         # Set workflow parameters | ||||
|         wf.set_node_param("KSampler", "seed", random.getrandbits(32)) | ||||
|         # wf.set_node_param("KSampler", "steps", steps) | ||||
|         wf.set_node_param("CLIP Text Encode (Prompt)", "text", comfy_prompt) | ||||
|         wf.set_node_param("Save Image", "filename_prefix", file_name) | ||||
|         wf.set_node_param("Empty Latent Image", "width", user_config["comfyui"]["width"]) | ||||
|         wf.set_node_param("Empty Latent Image", "height", user_config["comfyui"]["height"]) | ||||
|         wf.set_node_param( | ||||
|             "Load Checkpoint", "ckpt_name", user_config["comfyui"]["model"] | ||||
|         ) | ||||
|         # Queue your workflow for completion | ||||
|         logging.debug(f"Generating image: {file_name}") | ||||
|         results = api.queue_and_wait_images(wf, "Save Image") | ||||
|         for filename, image_data in results.items(): | ||||
|             with open( | ||||
|                 user_config["comfyui"]["output_dir"] + file_name + ".png", "wb+" | ||||
|             ) as f: | ||||
|                 f.write(image_data) | ||||
|         logging.debug(f"Image generated successfully for UID: {file_name}") | ||||
|     except Exception as e: | ||||
|         logging.error(f"Failed to generate image for UID: {file_name}. Error: {e}") | ||||
| 
 | ||||
| 
 | ||||
| def create_image(): | ||||
|     """Main function for generating images.""" | ||||
|     prompt = send_prompt_to_openwebui(user_config["comfyui"]["prompt"]) | ||||
|     print(f"Generated prompt: {prompt}") | ||||
|     generate_image(str(time.time()), prompt) | ||||
| 
 | ||||
| 
 | ||||
| # if __name__ == "__main__": | ||||
| #     main() | ||||
							
								
								
									
										
											BIN
										
									
								
								requirements.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								requirements.txt
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										39
									
								
								templates/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								templates/index.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,39 @@ | ||||
| <!DOCTYPE html> | ||||
| <html lang="en"> | ||||
| <head> | ||||
|     <meta charset="UTF-8"> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||
|     <title>Latest Image</title> | ||||
|     <style> | ||||
|         * { | ||||
|             margin: 0; | ||||
|             padding: 0; | ||||
|             overflow: hidden; | ||||
|         } | ||||
|         body { | ||||
|             display: flex; | ||||
|             align-items: center; | ||||
|             justify-content: center; | ||||
|             height: 100vh; | ||||
|             background: black; | ||||
|         } | ||||
|         img { | ||||
|             max-width: 100vw; | ||||
|             max-height: 100vh; | ||||
|             object-fit: contain; | ||||
|         } | ||||
|     </style> | ||||
|     <script> | ||||
|         setInterval(() => { | ||||
|             location.reload(); | ||||
|         }, 30000);  // Refresh every 5 seconds | ||||
|     </script> | ||||
| </head> | ||||
| <body> | ||||
|     {% if image %} | ||||
|         <img src="{{ url_for('images', filename=image) }}" alt="Latest Image"> | ||||
|     {% else %} | ||||
|         <p style="color: white;">No images found</p> | ||||
|     {% endif %} | ||||
| </body> | ||||
| </html> | ||||
							
								
								
									
										11
									
								
								user_config.cfg.sample
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								user_config.cfg.sample
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| [comfyui] | ||||
| comfyui_url = http://comfyui | ||||
| model = zavychromaxl_v100.safetensors | ||||
| output_dir = ./output/ | ||||
| prompt = "Be explicit, only return the prompt and no other text, Generate a random detailed prompt for stable diffusion." | ||||
| width = 1568 | ||||
| height = 672 | ||||
| 
 | ||||
| [openwebui] | ||||
| base_url = https://openwebui | ||||
| api_key = sk- | ||||
							
								
								
									
										107
									
								
								workflow_api.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								workflow_api.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,107 @@ | ||||
| { | ||||
|   "3": { | ||||
|     "inputs": { | ||||
|       "seed": 676047523401976, | ||||
|       "steps": 30, | ||||
|       "cfg": 6, | ||||
|       "sampler_name": "dpmpp_3m_sde", | ||||
|       "scheduler": "karras", | ||||
|       "denoise": 1, | ||||
|       "model": [ | ||||
|         "4", | ||||
|         0 | ||||
|       ], | ||||
|       "positive": [ | ||||
|         "6", | ||||
|         0 | ||||
|       ], | ||||
|       "negative": [ | ||||
|         "7", | ||||
|         0 | ||||
|       ], | ||||
|       "latent_image": [ | ||||
|         "5", | ||||
|         0 | ||||
|       ] | ||||
|     }, | ||||
|     "class_type": "KSampler", | ||||
|     "_meta": { | ||||
|       "title": "KSampler" | ||||
|     } | ||||
|   }, | ||||
|   "4": { | ||||
|     "inputs": { | ||||
|       "ckpt_name": "zavychromaxl_v80.safetensors" | ||||
|     }, | ||||
|     "class_type": "CheckpointLoaderSimple", | ||||
|     "_meta": { | ||||
|       "title": "Load Checkpoint" | ||||
|     } | ||||
|   }, | ||||
|   "5": { | ||||
|     "inputs": { | ||||
|       "width": 1568, | ||||
|       "height": 672, | ||||
|       "batch_size": 1 | ||||
|     }, | ||||
|     "class_type": "EmptyLatentImage", | ||||
|     "_meta": { | ||||
|       "title": "Empty Latent Image" | ||||
|     } | ||||
|   }, | ||||
|   "6": { | ||||
|     "inputs": { | ||||
|       "text": "A bustling cyberpunk street at night, filled with neon signs, rain-soaked pavement, and futuristic street vendors. High detail, vivid neon colors, and realistic reflections.", | ||||
|       "clip": [ | ||||
|         "4", | ||||
|         1 | ||||
|       ] | ||||
|     }, | ||||
|     "class_type": "CLIPTextEncode", | ||||
|     "_meta": { | ||||
|       "title": "CLIP Text Encode (Prompt)" | ||||
|     } | ||||
|   }, | ||||
|   "7": { | ||||
|     "inputs": { | ||||
|       "text": "text, watermark, deformed Avoid flat colors, poor lighting, and artificial elements. No unrealistic elements, low resolution, or flat colors. Avoid generic objects, poor lighting, and inconsistent styles.", | ||||
|       "clip": [ | ||||
|         "4", | ||||
|         1 | ||||
|       ] | ||||
|     }, | ||||
|     "class_type": "CLIPTextEncode", | ||||
|     "_meta": { | ||||
|       "title": "CLIP Text Encode (Prompt)" | ||||
|     } | ||||
|   }, | ||||
|   "8": { | ||||
|     "inputs": { | ||||
|       "samples": [ | ||||
|         "3", | ||||
|         0 | ||||
|       ], | ||||
|       "vae": [ | ||||
|         "4", | ||||
|         2 | ||||
|       ] | ||||
|     }, | ||||
|     "class_type": "VAEDecode", | ||||
|     "_meta": { | ||||
|       "title": "VAE Decode" | ||||
|     } | ||||
|   }, | ||||
|   "9": { | ||||
|     "inputs": { | ||||
|       "filename_prefix": "ComfyUI", | ||||
|       "images": [ | ||||
|         "8", | ||||
|         0 | ||||
|       ] | ||||
|     }, | ||||
|     "class_type": "SaveImage", | ||||
|     "_meta": { | ||||
|       "title": "Save Image" | ||||
|     } | ||||
|   } | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Karl Hudgell
						Karl Hudgell