mirror of
https://github.com/easydiffusion/easydiffusion.git
synced 2024-12-23 23:49:11 +01:00
commit
4f5b4f387a
15
README.md
15
README.md
@ -8,7 +8,7 @@
|
||||
|
||||
[![Discord Server](https://img.shields.io/discord/1014774730907209781?label=Discord)](https://discord.com/invite/u9yhsFmEkB) (for support, and development discussion) | [Troubleshooting guide for common problems](Troubleshooting.md)
|
||||
|
||||
️🔥🎉 **New!** Live Preview, More Samplers, In-Painting, Face Correction (GFPGAN) and Upscaling (RealESRGAN) have been added!
|
||||
️🔥🎉 **New!** Task Queue, Negative Prompt, Live Preview, More Samplers, In-Painting, Face Correction (GFPGAN) and Upscaling (RealESRGAN) have been added!
|
||||
|
||||
This distribution currently uses Stable Diffusion 1.4. Once the model for 1.5 becomes publicly available, the model in this distribution will be updated.
|
||||
|
||||
@ -17,6 +17,8 @@ This distribution currently uses Stable Diffusion 1.4. Once the model for 1.5 be
|
||||
- **Face Correction (GFPGAN) and Upscaling (RealESRGAN)**
|
||||
- **In-Painting**
|
||||
- **Live Preview**: See the image as the AI is drawing it
|
||||
- **Task Queue**: Queue up all your ideas, without waiting for the current task to finish
|
||||
- **Negative Prompt**: Specify aspects of the image to *remove*.
|
||||
- **Lots of Samplers:** ddim, plms, heun, euler, euler_a, dpm2, dpm2_a, lms
|
||||
- **Image Modifiers**: A library of *modifier tags* like *"Realistic"*, *"Pencil Sketch"*, *"ArtStation"* etc. Experiment with various styles quickly.
|
||||
- **New UI**: with cleaner design
|
||||
@ -40,7 +42,7 @@ This distribution currently uses Stable Diffusion 1.4. Once the model for 1.5 be
|
||||
You do not need anything else. You do not need WSL, Docker or Conda. The installer will take care of it.
|
||||
|
||||
# Installation
|
||||
1. **Download** [for Windows](https://github.com/cmdr2/stable-diffusion-ui/releases/download/v2.05/stable-diffusion-ui-win64.zip) or [for Linux](https://github.com/cmdr2/stable-diffusion-ui/releases/download/v2.05/stable-diffusion-ui-linux.tar.xz).
|
||||
1. **Download** [for Windows](https://github.com/cmdr2/stable-diffusion-ui/releases/download/v2.16/stable-diffusion-ui-win64.zip) or [for Linux](https://github.com/cmdr2/stable-diffusion-ui/releases/download/v2.16/stable-diffusion-ui-linux.tar.xz).
|
||||
|
||||
2. **Extract**:
|
||||
- For Windows: After unzipping the file, please move the `stable-diffusion-ui` folder to your `C:` (or any drive like D:, at the top root level), e.g. `C:\stable-diffusion-ui`. This will avoid a common problem with Windows (file path length limits).
|
||||
@ -77,12 +79,17 @@ You can use Face Correction or Upscaling to improve the image further.
|
||||
## Problems? Troubleshooting
|
||||
Please try the common [troubleshooting](Troubleshooting.md) steps. If that doesn't fix it, please ask on the [discord server](https://discord.com/invite/u9yhsFmEkB), or [file an issue](https://github.com/cmdr2/stable-diffusion-ui/issues).
|
||||
|
||||
# Advanced Settings
|
||||
You can also set the configuration like `seed`, `width`, `height`, `num_outputs`, `num_inference_steps` and `guidance_scale` using the 'show' button next to 'Advanced settings'.
|
||||
# Image Settings
|
||||
You can also set the configuration like `seed`, `width`, `height`, `num_outputs`, `num_inference_steps` and `guidance_scale` using the 'show' button next to 'Image settings'.
|
||||
|
||||
Use the same `seed` number to get the same image for a certain prompt. This is useful for refining a prompt without losing the basic image design. Enable the `random images` checkbox to get random images.
|
||||
|
||||
![Screenshot of advanced settings](media/config-v6.jpg?raw=true)
|
||||
|
||||
# System Settings
|
||||
The system settings are reachable via the cogwheel symbol on the top right. It can be used to configure whether all generated images should
|
||||
saved be automically, or to tune the Stable Diffusion image generation.
|
||||
|
||||
![Screenshot of advanced settings](media/system-settings-v2.jpg?raw=true)
|
||||
|
||||
# Image Modifiers
|
||||
|
@ -9,6 +9,11 @@ Additionally, a common reason for this error is that you're using an initial ima
|
||||
|
||||
Also try generating smaller sized images.
|
||||
|
||||
## basicsr module not found
|
||||
For Windows: Please download and extract basicsr from [here](https://github.com/cmdr2/stable-diffusion-ui/releases/download/v2.16/basicsr-win64.zip), and place the `basicsr` folder inside the `stable-diffusion-ui\stable-diffusion\env\lib\site-packages` folder. Then run the `Start Stable Diffusion UI.cmd` file again.
|
||||
|
||||
For Linux: Please contact on the [discord server](https://discord.com/invite/u9yhsFmEkB).
|
||||
|
||||
## No ldm found, or antlr4 or any other missing module, or ClobberError: This transaction has incompatible packages due to a shared path
|
||||
On Windows, please ensure that you had placed the `stable-diffusion-ui` folder after unzipping to the root of C: or D: (or any drive). For e.g. `C:\stable-diffusion-ui`. **Note:** This has to be done **before** you start the installation process. If you have already installed (and are facing this error), please delete the installed folder, and start fresh by unzipping and placing the folder at the top of your drive.
|
||||
|
||||
@ -44,3 +49,27 @@ After this, you can access the server at `http://localhost:1337` (where 1337 is
|
||||
Please ensure that you have an NVIDIA GPU and the latest [NVIDIA driver](http://www.nvidia.com/Download/index.aspx), and that you've installed [nvidia-container-toolkit](https://stackoverflow.com/a/58432877).
|
||||
|
||||
Also, if you are using WSL (Windows), please ensure you have the latest WSL kernel by running `wsl --shutdown` and then `wsl --update`. (Thanks [AndrWeisR](https://github.com/AndrWeisR))
|
||||
|
||||
# For support queries
|
||||
## Entering a conda environment in an existing installation
|
||||
This will give you an activated conda environment in the terminal, so you can run commands and force-install any packages, if required.
|
||||
|
||||
Users don't need to have the Anaconda Prompt installed to do this anymore, since the installer bundles a portable version of conda inside it. Just follow these steps.
|
||||
|
||||
**Windows:**
|
||||
1. Open the terminal: Press Win+R, type "cmd", and press "Run"
|
||||
2. Type `cd C:\stable-diffusion-ui` and press enter (or wherever you've installed it)
|
||||
3. Type `installer\Scripts\activate.bat` and press enter
|
||||
4. Type `cd stable-diffusion` and press enter
|
||||
5. Type `conda activate .\env` and press enter
|
||||
6. Type `python --version` and press enter. You should see 3.8.5.
|
||||
|
||||
**Windows:**
|
||||
1. Open the terminal
|
||||
2. Type `cd /path/to/stable-diffusion-ui` and press enter
|
||||
3. Type `installer/bin/activate` and press enter
|
||||
4. Type `cd stable-diffusion` and press enter
|
||||
5. Type `conda activate ./env` and press enter
|
||||
6. Type `python --version` and press enter. You should see 3.8.5.
|
||||
|
||||
This will give you an activated conda environment. To confirm, type `python --version` and press enter. You should see 3.8.5.
|
||||
|
@ -8,6 +8,8 @@
|
||||
set /p answer=Are you a developer of this project (Y/N)?
|
||||
if /i "%answer:~,1%" NEQ "Y" exit /b
|
||||
|
||||
@set PYTHONNOUSERSITE=1
|
||||
|
||||
@mkdir dist\stable-diffusion-ui
|
||||
|
||||
@echo "Downloading components for the installer.."
|
||||
@ -15,11 +17,6 @@ if /i "%answer:~,1%" NEQ "Y" exit /b
|
||||
@call conda env create --prefix installer -f environment.yaml
|
||||
@call conda activate .\installer
|
||||
|
||||
@echo "Setting up startup scripts.."
|
||||
|
||||
@mkdir installer\etc\conda\activate.d
|
||||
@copy scripts\post_activate.bat installer\etc\conda\activate.d\
|
||||
|
||||
@echo "Creating a distributable package.."
|
||||
|
||||
@call conda install -c conda-forge -y conda-pack
|
||||
@ -37,6 +34,7 @@ if /i "%answer:~,1%" NEQ "Y" exit /b
|
||||
@copy ..\..\LICENSE .
|
||||
@copy "..\..\CreativeML Open RAIL-M License" .
|
||||
@copy "..\..\How to install and run.txt" .
|
||||
@echo. > scripts\install_status.txt
|
||||
|
||||
@echo "Build ready. Zip the 'dist\stable-diffusion-ui' folder."
|
||||
|
||||
|
3
build.sh
3
build.sh
@ -11,6 +11,8 @@ case $yn in
|
||||
* ) exit;;
|
||||
esac
|
||||
|
||||
export PYTHONNOUSERSITE=1
|
||||
|
||||
mkdir -p dist/stable-diffusion-ui
|
||||
|
||||
echo "Downloading components for the installer.."
|
||||
@ -38,6 +40,7 @@ cp ../../scripts/start.sh .
|
||||
cp ../../LICENSE .
|
||||
cp "../../CreativeML Open RAIL-M License" .
|
||||
cp "../../How to install and run.txt" .
|
||||
echo "" > scripts/install_status.txt
|
||||
|
||||
chmod u+x start.sh
|
||||
|
||||
|
@ -1 +1,19 @@
|
||||
installer\Scripts\activate.bat
|
||||
@echo off
|
||||
|
||||
@REM Delete the post-activate hook from the old installer
|
||||
if exist "installer\etc\conda\activate.d\post_activate.bat" (
|
||||
echo. > installer\etc\conda\activate.d\post_activate.bat
|
||||
)
|
||||
|
||||
@call installer\Scripts\activate.bat
|
||||
|
||||
@call conda-unpack
|
||||
|
||||
@call conda --version
|
||||
@call git --version
|
||||
|
||||
@cd installer
|
||||
|
||||
@call ..\scripts\on_env_start.bat
|
||||
|
||||
@pause
|
||||
|
@ -165,13 +165,13 @@ call WHERE uvicorn > .tmp
|
||||
|
||||
@if exist "sd-v1-4.ckpt" (
|
||||
for %%I in ("sd-v1-4.ckpt") do if "%%~zI" EQU "4265380512" (
|
||||
echo "Data files (weights) necessary for Stable Diffusion were already downloaded"
|
||||
echo "Data files (weights) necessary for Stable Diffusion were already downloaded. Using the HuggingFace 4 GB Model."
|
||||
) else (
|
||||
for %%J in ("sd-v1-4.ckpt") do if "%%~zJ" EQU "7703807346" (
|
||||
echo "Data files (weights) necessary for Stable Diffusion were already downloaded"
|
||||
echo "Data files (weights) necessary for Stable Diffusion were already downloaded. Using the HuggingFace 7 GB Model."
|
||||
) else (
|
||||
for %%K in ("sd-v1-4.ckpt") do if "%%~zK" EQU "7703810927" (
|
||||
echo "Data files (weights) necessary for Stable Diffusion were already downloaded"
|
||||
echo "Data files (weights) necessary for Stable Diffusion were already downloaded. Using the Waifu Model."
|
||||
) else (
|
||||
echo. & echo "The model file present at %cd%\sd-v1-4.ckpt is invalid. It is only %%~zK bytes in size. Re-downloading.." & echo.
|
||||
del "sd-v1-4.ckpt"
|
||||
|
@ -4,4 +4,7 @@ source installer/bin/activate
|
||||
|
||||
conda-unpack
|
||||
|
||||
conda --version
|
||||
git --version
|
||||
|
||||
scripts/on_env_start.sh
|
||||
|
@ -8,7 +8,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="icon" type="image/png" href="/media/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="icon" type="image/png" href="/media/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="stylesheet" href="/media/main.css?v=3">
|
||||
<link rel="stylesheet" href="/media/main.css?v=10">
|
||||
<link rel="stylesheet" href="/media/modifier-thumbnails.css?v=1">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css">
|
||||
<link rel="stylesheet" href="/media/drawingboard.min.css">
|
||||
@ -19,7 +19,7 @@
|
||||
<div id="container">
|
||||
<div id="top-nav">
|
||||
<div id="logo">
|
||||
<h1>Stable Diffusion UI <small>v2.17 <span id="updateBranchLabel"></span></small></h1>
|
||||
<h1>Stable Diffusion UI <small>v2.195 <span id="updateBranchLabel"></span></small></h1>
|
||||
</div>
|
||||
<ul id="top-nav-items">
|
||||
<li class="dropdown">
|
||||
@ -27,6 +27,7 @@
|
||||
<ul id="community-links" class="dropdown-content">
|
||||
<li><a href="https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md" target="_blank"><i class="fa-solid fa-circle-question fa-fw"></i> Usual problems and solutions</a></li>
|
||||
<li><a href="https://discord.com/invite/u9yhsFmEkB" target="_blank"><i class="fa-brands fa-discord fa-fw"></i> Discord user community</a></li>
|
||||
<li><a href="https://www.reddit.com/r/StableDiffusionUI/" target="_blank"><i class="fa-brands fa-reddit fa-fw"></i> Reddit community</a></li>
|
||||
<li><a href="https://github.com/cmdr2/stable-diffusion-ui" target="_blank"><i class="fa-brands fa-github fa-fw"></i> Source code on GitHub</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
@ -81,7 +82,7 @@
|
||||
</div>
|
||||
|
||||
<button id="makeImage">Make Image</button>
|
||||
<button id="stopImage">Stop</button>
|
||||
<button id="stopImage" class="secondaryButton">Stop All</button>
|
||||
</div>
|
||||
|
||||
<div class="line-separator"> </div>
|
||||
@ -125,7 +126,8 @@
|
||||
<option value="1536">1536</option>
|
||||
<option value="1792">1792</option>
|
||||
<option value="2048">2048</option>
|
||||
</select> <label for="width"><small>(width)</small></label>
|
||||
</select>
|
||||
<label for="width"><small>(width)</small></label>
|
||||
<select id="height" name="height" value="512">
|
||||
<option value="128">128 (*)</option>
|
||||
<option value="192">192</option>
|
||||
@ -155,8 +157,13 @@
|
||||
|
||||
<br/>
|
||||
|
||||
<li><b class="settings-subheader">Prompt Settings</b></li>
|
||||
<li class="pl-5"><label for="negative_prompt">Negative Prompt:</label> <input id="negative_prompt" name="negative_prompt" size="55"></li>
|
||||
|
||||
<br/>
|
||||
|
||||
<li><b class="settings-subheader">Render Settings</b></li>
|
||||
<li class="pl-5"><input id="stream_image_progress" name="stream_image_progress" type="checkbox"> <label for="stream_image_progress">Show a live preview of the image <small>(consumes more VRAM, slightly slower image generation)</small></label></li>
|
||||
<li class="pl-5"><input id="stream_image_progress" name="stream_image_progress" type="checkbox"> <label for="stream_image_progress">Show a live preview of the image <small>(uses more VRAM, slightly slower image creation)</small></label></li>
|
||||
<li class="pl-5"><input id="use_face_correction" name="use_face_correction" type="checkbox" checked> <label for="use_face_correction">Fix incorrect faces and eyes <small>(uses GFPGAN)</small></label></li>
|
||||
<li class="pl-5">
|
||||
<input id="use_upscale" name="use_upscale" type="checkbox"> <label for="use_upscale">Upscale the image to 4x resolution using </label>
|
||||
@ -174,7 +181,7 @@
|
||||
<div id="editor-modifiers" class="panel-box">
|
||||
<h4 class="collapsible">Image Modifiers (art styles, tags etc)</h4>
|
||||
<div id="editor-modifiers-entries" class="collapsible-content">
|
||||
<label for="preview-image">Image Style:</label>
|
||||
<label for="preview-image">Image Style:</label>
|
||||
<select id="preview-image" name="preview-image" value="portrait">
|
||||
<option value="portrait" selected="">Face</option>
|
||||
<option value="landscape">Landscape</option>
|
||||
@ -187,15 +194,11 @@
|
||||
</div>
|
||||
|
||||
<div id="preview" class="col-free">
|
||||
<div id="preview-prompt">
|
||||
<div id="initial-text">
|
||||
Type a prompt and press the "Make Image" button.<br/><br/>You can set an "Initial Image" if you want to guide the AI.<br/><br/>You can also add modifiers like "Realistic", "Pencil Sketch", "ArtStation" etc by browsing through the "Image Modifiers" section and selecting the desired modifiers.<br/><br/>Click "Advanced Settings" for additional settings like seed, image size, number of images to generate etc.<br/><br/>Enjoy! :)
|
||||
</div>
|
||||
<div id="initial-text">
|
||||
Type a prompt and press the "Make Image" button.<br/><br/>You can set an "Initial Image" if you want to guide the AI.<br/><br/>You can also add modifiers like "Realistic", "Pencil Sketch", "ArtStation" etc by browsing through the "Image Modifiers" section and selecting the desired modifiers.<br/><br/>Click "Advanced Settings" for additional settings like seed, image size, number of images to generate etc.<br/><br/>Enjoy! :)
|
||||
</div>
|
||||
|
||||
<div id="outputMsg"></div>
|
||||
<div id="progressBar"></div>
|
||||
<div id="current-images" class="img-preview">
|
||||
<div id="preview-tools">
|
||||
<button id="clear-all-previews" class="secondaryButton"><i class="fa-solid fa-trash-can"></i> Clear All</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -214,7 +217,7 @@
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<script src="media/main.js?v=4"></script>
|
||||
<script src="media/main.js?v=14"></script>
|
||||
<script>
|
||||
async function init() {
|
||||
await loadModifiers()
|
||||
|
@ -54,8 +54,9 @@ label {
|
||||
.editor-slider {
|
||||
vertical-align: middle;
|
||||
}
|
||||
#outputMsg {
|
||||
.outputMsg {
|
||||
font-size: small;
|
||||
padding-bottom: 3pt;
|
||||
}
|
||||
#progressBar {
|
||||
font-size: small;
|
||||
@ -164,7 +165,7 @@ label {
|
||||
display: none;
|
||||
}
|
||||
#stopImage:hover {
|
||||
background: rgb(214, 32, 0);
|
||||
background: rgb(177, 27, 0);
|
||||
}
|
||||
.flex-container {
|
||||
display: flex;
|
||||
@ -173,7 +174,7 @@ label {
|
||||
flex: 50%;
|
||||
}
|
||||
.col-fixed-10 {
|
||||
flex: 0 0 400pt;
|
||||
flex: 0 0 380pt;
|
||||
}
|
||||
.col-free {
|
||||
flex: 1;
|
||||
@ -211,7 +212,7 @@ label {
|
||||
padding-bottom: 10pt;
|
||||
}
|
||||
#preview {
|
||||
margin-left: 20pt;
|
||||
margin-left: 10pt;
|
||||
}
|
||||
img {
|
||||
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.15), 0 6px 20px 0 rgba(0, 0, 0, 0.15);
|
||||
@ -245,7 +246,7 @@ img {
|
||||
padding-left: 2pt;
|
||||
font-size: 10pt;
|
||||
}
|
||||
#preview-prompt {
|
||||
.preview-prompt {
|
||||
font-size: 16pt;
|
||||
margin-bottom: 10pt;
|
||||
}
|
||||
@ -364,4 +365,48 @@ img {
|
||||
}
|
||||
.dropdown:hover .dropdown-content {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.imageTaskContainer {
|
||||
border: 1px solid #333;
|
||||
margin-bottom: 10pt;
|
||||
padding: 5pt;
|
||||
border-radius: 5pt;
|
||||
box-shadow: 0 20px 28px 0 rgba(0, 0, 0, 0.15), 0 6px 20px 0 rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
.taskStatusLabel {
|
||||
float: left;
|
||||
font-size: 8pt;
|
||||
background:rgb(44, 45, 48);
|
||||
border: 1px solid rgb(61, 62, 66);
|
||||
padding: 2pt 4pt;
|
||||
border-radius: 2pt;
|
||||
margin-right: 5pt;
|
||||
}
|
||||
.activeTaskLabel {
|
||||
background:rgb(0, 90, 30);
|
||||
border: 1px solid rgb(0, 75, 19);
|
||||
color:rgb(204, 255, 217)
|
||||
}
|
||||
.secondaryButton {
|
||||
background: rgb(132, 8, 0);
|
||||
border: 1px solid rgb(122, 29, 0);
|
||||
color: rgb(255, 221, 255);
|
||||
padding: 3pt 6pt;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.secondaryButton:hover {
|
||||
background: rgb(177, 27, 0);
|
||||
}
|
||||
.stopTask {
|
||||
float: right;
|
||||
}
|
||||
#preview-tools {
|
||||
display: none;
|
||||
padding: 4pt;
|
||||
}
|
||||
.taskConfig {
|
||||
font-size: 10pt;
|
||||
color: #aaa;
|
||||
margin-bottom: 5pt;
|
||||
}
|
323
ui/media/main.js
323
ui/media/main.js
@ -18,6 +18,7 @@ const IMAGE_REGEX = new RegExp('data:image/[A-Za-z]+;base64')
|
||||
let sessionId = new Date().getTime()
|
||||
|
||||
let promptField = document.querySelector('#prompt')
|
||||
let negativePromptField = document.querySelector('#negative_prompt')
|
||||
let numOutputsTotalField = document.querySelector('#num_outputs_total')
|
||||
let numOutputsParallelField = document.querySelector('#num_outputs_parallel')
|
||||
let numInferenceStepsField = document.querySelector('#num_inference_steps')
|
||||
@ -57,6 +58,10 @@ let initImagePreviewContainer = document.querySelector('#init_image_preview_cont
|
||||
let initImageClearBtn = document.querySelector('.init_image_clear')
|
||||
let promptStrengthContainer = document.querySelector('#prompt_strength_container')
|
||||
|
||||
let initialText = document.querySelector("#initial-text")
|
||||
let previewTools = document.querySelector("#preview-tools")
|
||||
let clearAllPreviewsBtn = document.querySelector("#clear-all-previews")
|
||||
|
||||
// let maskSetting = document.querySelector('#editor-inputs-mask_setting')
|
||||
// let maskImagePreviewContainer = document.querySelector('#mask_preview_container')
|
||||
// let maskImageClearBtn = document.querySelector('#mask_clear')
|
||||
@ -66,18 +71,19 @@ let editorModifierEntries = document.querySelector('#editor-modifiers-entries')
|
||||
let editorModifierTagsList = document.querySelector('#editor-inputs-tags-list')
|
||||
let editorTagsContainer = document.querySelector('#editor-inputs-tags-container')
|
||||
|
||||
let imagePreview = document.querySelector("#preview")
|
||||
let previewImageField = document.querySelector('#preview-image')
|
||||
previewImageField.onchange = () => changePreviewImages(previewImageField.value);
|
||||
|
||||
let modifierCardSizeSlider = document.querySelector('#modifier-card-size-slider')
|
||||
modifierCardSizeSlider.onchange = () => resizeModifierCards(modifierCardSizeSlider.value);
|
||||
|
||||
let previewPrompt = document.querySelector('#preview-prompt')
|
||||
// let previewPrompt = document.querySelector('#preview-prompt')
|
||||
|
||||
let showConfigToggle = document.querySelector('#configToggleBtn')
|
||||
// let configBox = document.querySelector('#config')
|
||||
let outputMsg = document.querySelector('#outputMsg')
|
||||
let progressBar = document.querySelector("#progressBar")
|
||||
// let outputMsg = document.querySelector('#outputMsg')
|
||||
// let progressBar = document.querySelector("#progressBar")
|
||||
|
||||
let soundToggle = document.querySelector('#sound_toggle')
|
||||
|
||||
@ -108,8 +114,10 @@ let serverStatus = 'offline'
|
||||
let activeTags = []
|
||||
let modifiers = []
|
||||
let lastPromptUsed = ''
|
||||
let taskStopped = true
|
||||
let batchesDone = 0
|
||||
let bellPending = false
|
||||
|
||||
let taskQueue = []
|
||||
let currentTask = null
|
||||
|
||||
const modifierThumbnailPath = 'media/modifier-thumbnails';
|
||||
const activeCardClass = 'modifier-card-active';
|
||||
@ -211,7 +219,7 @@ function setStatus(statusType, msg, msgType) {
|
||||
}
|
||||
}
|
||||
|
||||
function logMsg(msg, level) {
|
||||
function logMsg(msg, level, outputMsg) {
|
||||
if (level === 'error') {
|
||||
outputMsg.innerHTML = '<span style="color: red">Error: ' + msg + '</span>'
|
||||
} else if (level === 'warn') {
|
||||
@ -223,8 +231,8 @@ function logMsg(msg, level) {
|
||||
console.log(level, msg)
|
||||
}
|
||||
|
||||
function logError(msg, res) {
|
||||
logMsg(msg, 'error')
|
||||
function logError(msg, res, outputMsg) {
|
||||
logMsg(msg, 'error', outputMsg)
|
||||
|
||||
console.log('request error', res)
|
||||
setStatus('request', 'error', 'error')
|
||||
@ -251,7 +259,7 @@ async function healthCheck() {
|
||||
}
|
||||
}
|
||||
|
||||
function makeImageElement(width, height) {
|
||||
function makeImageElement(width, height, outputContainer) {
|
||||
let imgItem = document.createElement('div')
|
||||
imgItem.className = 'imgItem'
|
||||
|
||||
@ -260,17 +268,25 @@ function makeImageElement(width, height) {
|
||||
img.height = parseInt(height)
|
||||
|
||||
imgItem.appendChild(img)
|
||||
imagesContainer.appendChild(imgItem)
|
||||
outputContainer.insertBefore(imgItem, outputContainer.firstChild)
|
||||
|
||||
return imgItem
|
||||
}
|
||||
|
||||
// makes a single image. don't call this directly, use makeImage() instead
|
||||
async function doMakeImage(reqBody, batchCount) {
|
||||
if (taskStopped) {
|
||||
async function doMakeImage(task) {
|
||||
if (task.stopped) {
|
||||
return
|
||||
}
|
||||
|
||||
const reqBody = task.reqBody
|
||||
const batchCount = task.batchCount
|
||||
const outputContainer = task.outputContainer
|
||||
|
||||
const outputMsg = task['outputMsg']
|
||||
const previewPrompt = task['previewPrompt']
|
||||
const progressBar = task['progressBar']
|
||||
|
||||
let res = ''
|
||||
let seed = reqBody['seed']
|
||||
let numOutputs = parseInt(reqBody['num_outputs'])
|
||||
@ -279,7 +295,7 @@ async function doMakeImage(reqBody, batchCount) {
|
||||
|
||||
function makeImageContainers(numImages) {
|
||||
for (let i = images.length; i < numImages; i++) {
|
||||
images.push(makeImageElement(reqBody.width, reqBody.height))
|
||||
images.push(makeImageElement(reqBody.width, reqBody.height, outputContainer))
|
||||
}
|
||||
}
|
||||
|
||||
@ -316,7 +332,7 @@ async function doMakeImage(reqBody, batchCount) {
|
||||
finalJSON += jsonStr
|
||||
} else {
|
||||
let batchSize = stepUpdate.total_steps
|
||||
let overallStepCount = stepUpdate.step + batchesDone * batchSize
|
||||
let overallStepCount = stepUpdate.step + task.batchesDone * batchSize
|
||||
let totalSteps = batchCount * batchSize
|
||||
let percent = 100 * (overallStepCount / totalSteps)
|
||||
percent = (percent > 100 ? 100 : percent)
|
||||
@ -326,13 +342,13 @@ async function doMakeImage(reqBody, batchCount) {
|
||||
stepsRemaining = (stepsRemaining < 0 ? 0 : stepsRemaining)
|
||||
timeRemaining = (timeTaken === -1 ? '' : stepsRemaining * timeTaken) // ms
|
||||
|
||||
outputMsg.innerHTML = `Batch ${batchesDone+1} of ${batchCount}`
|
||||
progressBar.innerHTML = `Generating image(s): ${percent}%`
|
||||
outputMsg.innerHTML = `Batch ${task.batchesDone+1} of ${batchCount}`
|
||||
outputMsg.innerHTML += `. Generating image(s): ${percent}%`
|
||||
|
||||
if (timeTaken !== -1) {
|
||||
progressBar.innerHTML += `<br>Time remaining (approx): ${millisecondsToStr(timeRemaining)}`
|
||||
}
|
||||
progressBar.style.display = 'block'
|
||||
timeRemaining = (timeTaken !== -1 ? millisecondsToStr(timeRemaining) : '')
|
||||
|
||||
outputMsg.innerHTML += `. Time remaining (approx): ${timeRemaining}`
|
||||
outputMsg.style.display = 'block'
|
||||
|
||||
if (stepUpdate.output !== undefined) {
|
||||
makeImageContainers(numOutputs)
|
||||
@ -351,7 +367,7 @@ async function doMakeImage(reqBody, batchCount) {
|
||||
|
||||
prevTime = t
|
||||
} catch (e) {
|
||||
logError('Stable Diffusion had an error. Please check the logs in the command-line window.', res)
|
||||
logError('Stable Diffusion had an error. Please check the logs in the command-line window.', res, outputMsg)
|
||||
res = undefined
|
||||
throw e
|
||||
}
|
||||
@ -359,9 +375,9 @@ async function doMakeImage(reqBody, batchCount) {
|
||||
|
||||
if (res.status != 200) {
|
||||
if (serverStatus === 'online') {
|
||||
logError('Stable Diffusion had an error: ' + await res.text(), res)
|
||||
logError('Stable Diffusion had an error: ' + await res.text(), res, outputMsg)
|
||||
} else {
|
||||
logError("Stable Diffusion is still starting up, please wait. If this goes on beyond a few minutes, Stable Diffusion has probably crashed. Please check the error message in the command-line window.", res)
|
||||
logError("Stable Diffusion is still starting up, please wait. If this goes on beyond a few minutes, Stable Diffusion has probably crashed. Please check the error message in the command-line window.", res, outputMsg)
|
||||
}
|
||||
res = undefined
|
||||
progressBar.style.display = 'none'
|
||||
@ -381,7 +397,6 @@ async function doMakeImage(reqBody, batchCount) {
|
||||
}
|
||||
|
||||
res = JSON.parse(finalJSON)
|
||||
progressBar.style.display = 'none'
|
||||
|
||||
if (res.status !== 'succeeded') {
|
||||
let msg = ''
|
||||
@ -399,13 +414,13 @@ async function doMakeImage(reqBody, batchCount) {
|
||||
} else {
|
||||
msg = res
|
||||
}
|
||||
logError(msg, res)
|
||||
logError(msg, res, outputMsg)
|
||||
res = undefined
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('request error', e)
|
||||
logError('Stable Diffusion had an error. Please check the logs in the command-line window. <br/><br/>' + e + '<br/><pre>' + e.stack + '</pre>', res)
|
||||
logError('Stable Diffusion had an error. Please check the logs in the command-line window. <br/><br/>' + e + '<br/><pre>' + e.stack + '</pre>', res, outputMsg)
|
||||
setStatus('request', 'error', 'error')
|
||||
progressBar.style.display = 'none'
|
||||
res = undefined
|
||||
@ -440,6 +455,7 @@ async function doMakeImage(reqBody, batchCount) {
|
||||
|
||||
let imgItemInfo = document.createElement('span')
|
||||
imgItemInfo.className = 'imgItemInfo'
|
||||
imgItemInfo.style.opacity = 0
|
||||
|
||||
let imgSeedLabel = document.createElement('span')
|
||||
imgSeedLabel.className = 'imgSeedLabel'
|
||||
@ -486,55 +502,103 @@ async function doMakeImage(reqBody, batchCount) {
|
||||
})
|
||||
|
||||
imgItem.addEventListener('mouseleave', function() {
|
||||
imgItemInfo.style.opacity = 0.5
|
||||
imgItemInfo.style.opacity = 0
|
||||
})
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
function validateInput() {
|
||||
let width = parseInt(widthField.value)
|
||||
let height = parseInt(heightField.value)
|
||||
async function checkTasks() {
|
||||
if (taskQueue.length === 0) {
|
||||
setStatus('request', 'done', 'success')
|
||||
setTimeout(checkTasks, 500)
|
||||
stopImageBtn.style.display = 'none'
|
||||
makeImageBtn.innerHTML = 'Make Image'
|
||||
|
||||
if (IMAGE_REGEX.test(initImagePreview.src)) {
|
||||
if (initImagePreview.naturalWidth > MAX_INIT_IMAGE_DIMENSION || initImagePreview.naturalHeight > MAX_INIT_IMAGE_DIMENSION) {
|
||||
return {'isValid': false, 'warning': `The dimensions of your initial image are very large, and can cause 'Out of Memory' errors! Please ensure that its dimensions are equal (or smaller) than the desired output image.
|
||||
<br/><br/>
|
||||
Your initial image size is ${initImagePreview.naturalWidth}x${initImagePreview.naturalHeight} pixels. Please try to keep it smaller than ${MAX_INIT_IMAGE_DIMENSION}x${MAX_INIT_IMAGE_DIMENSION}.`}
|
||||
currentTask = null
|
||||
|
||||
if (bellPending) {
|
||||
if (isSoundEnabled()) {
|
||||
playSound()
|
||||
}
|
||||
bellPending = false
|
||||
}
|
||||
}
|
||||
|
||||
return {'isValid': true}
|
||||
}
|
||||
|
||||
async function makeImage() {
|
||||
if (serverStatus !== 'online') {
|
||||
logError('The server is still starting up..')
|
||||
return
|
||||
}
|
||||
|
||||
let validation = validateInput()
|
||||
if (validation['isValid']) {
|
||||
outputMsg.innerHTML = 'Starting..'
|
||||
} else {
|
||||
if (validation['error']) {
|
||||
logError(validation['error'])
|
||||
return
|
||||
} else if (validation['warning']) {
|
||||
logMsg(validation['warning'], 'warn')
|
||||
}
|
||||
}
|
||||
|
||||
setStatus('request', 'fetching..')
|
||||
|
||||
makeImageBtn.innerHTML = 'Processing..'
|
||||
makeImageBtn.disabled = true
|
||||
makeImageBtn.style.display = 'none'
|
||||
stopImageBtn.style.display = 'block'
|
||||
makeImageBtn.innerHTML = 'Enqueue Next Image'
|
||||
bellPending = true
|
||||
|
||||
taskStopped = false
|
||||
batchesDone = 0
|
||||
previewTools.style.display = 'block'
|
||||
|
||||
let task = taskQueue.pop()
|
||||
currentTask = task
|
||||
|
||||
let time = new Date().getTime()
|
||||
|
||||
let successCount = 0
|
||||
|
||||
task.isProcessing = true
|
||||
task['stopTask'].innerHTML = '<i class="fa-solid fa-circle-stop"></i> Stop'
|
||||
task['taskStatusLabel'].innerText = "Processing"
|
||||
task['taskStatusLabel'].className += " activeTaskLabel"
|
||||
console.log(task['taskStatusLabel'].className)
|
||||
|
||||
for (let i = 0; i < task.batchCount; i++) {
|
||||
task.reqBody['seed'] = task.seed + (i * task.reqBody['num_outputs'])
|
||||
|
||||
let success = await doMakeImage(task)
|
||||
task.batchesDone++
|
||||
|
||||
if (!task.isProcessing) {
|
||||
break
|
||||
}
|
||||
|
||||
if (success) {
|
||||
successCount++
|
||||
}
|
||||
}
|
||||
|
||||
task.isProcessing = false
|
||||
task['stopTask'].innerHTML = '<i class="fa-solid fa-trash-can"></i> Remove'
|
||||
task['taskStatusLabel'].style.display = 'none'
|
||||
|
||||
time = new Date().getTime() - time
|
||||
time /= 1000
|
||||
|
||||
if (successCount === task.batchCount) {
|
||||
task.outputMsg.innerText = 'Processed ' + task.numOutputsTotal + ' images in ' + time + ' seconds'
|
||||
|
||||
// setStatus('request', 'done', 'success')
|
||||
} else {
|
||||
task.outputMsg.innerText = 'Task ended after ' + time + ' seconds'
|
||||
}
|
||||
|
||||
if (randomSeedField.checked) {
|
||||
seedField.value = task.seed
|
||||
}
|
||||
|
||||
currentTask = null
|
||||
|
||||
setTimeout(checkTasks, 10)
|
||||
}
|
||||
setTimeout(checkTasks, 0)
|
||||
|
||||
async function makeImage() {
|
||||
if (serverStatus !== 'online') {
|
||||
alert('The server is still starting up..')
|
||||
return
|
||||
}
|
||||
|
||||
let task = {
|
||||
stopped: false,
|
||||
batchesDone: 0
|
||||
}
|
||||
|
||||
let seed = (randomSeedField.checked ? Math.floor(Math.random() * 10000000) : parseInt(seedField.value))
|
||||
let numOutputsTotal = parseInt(numOutputsTotalField.value)
|
||||
@ -550,11 +614,10 @@ async function makeImage() {
|
||||
prompt += ", " + promptTags;
|
||||
}
|
||||
|
||||
previewPrompt.innerText = prompt
|
||||
|
||||
let reqBody = {
|
||||
session_id: sessionId,
|
||||
prompt: prompt,
|
||||
negative_prompt: negativePromptField.value.trim(),
|
||||
num_outputs: batchSize,
|
||||
num_inference_steps: numInferenceStepsField.value,
|
||||
guidance_scale: guidanceScaleField.value,
|
||||
@ -597,44 +660,76 @@ async function makeImage() {
|
||||
reqBody['use_upscale'] = upscaleModelField.value
|
||||
}
|
||||
|
||||
let time = new Date().getTime()
|
||||
imagesContainer.innerHTML = ''
|
||||
let taskConfig = `Seed: ${seed}, Sampler: ${reqBody['sampler']}, Inference Steps: ${numInferenceStepsField.value}, Guidance Scale: ${guidanceScaleField.value}`
|
||||
|
||||
let successCount = 0
|
||||
if (negativePromptField.value.trim() !== '') {
|
||||
taskConfig += `, Negative Prompt: ${negativePromptField.value.trim()}`
|
||||
}
|
||||
|
||||
for (let i = 0; i < batchCount; i++) {
|
||||
reqBody['seed'] = seed + (i * batchSize)
|
||||
if (reqBody['init_image'] !== undefined) {
|
||||
taskConfig += `, Prompt Strength: ${promptStrengthField.value}`
|
||||
}
|
||||
|
||||
let success = await doMakeImage(reqBody, batchCount)
|
||||
batchesDone++
|
||||
if (useFaceCorrectionField.checked) {
|
||||
taskConfig += `, Fix Faces: ${reqBody['use_face_correction']}`
|
||||
}
|
||||
|
||||
if (success) {
|
||||
outputMsg.innerText = 'Processed batch ' + (i+1) + '/' + batchCount
|
||||
successCount++
|
||||
if (useUpscalingField.checked) {
|
||||
taskConfig += `, Upscale: ${reqBody['use_upscale']}`
|
||||
}
|
||||
|
||||
task['reqBody'] = reqBody
|
||||
task['seed'] = seed
|
||||
task['batchCount'] = batchCount
|
||||
task['isProcessing'] = false
|
||||
|
||||
let taskEntry = document.createElement('div')
|
||||
taskEntry.className = 'imageTaskContainer'
|
||||
taskEntry.innerHTML = ` <div class="taskStatusLabel">Enqueued</div>
|
||||
<button class="secondaryButton stopTask"><i class="fa-solid fa-trash-can"></i> Remove</button>
|
||||
<div class="preview-prompt collapsible active"></div>
|
||||
<div class="taskConfig">${taskConfig}</div>
|
||||
<div class="collapsible-content" style="display: block">
|
||||
<div class="outputMsg"></div>
|
||||
<div class="progressBar"></div>
|
||||
<div class="img-preview">
|
||||
</div>`
|
||||
|
||||
createCollapsibles(taskEntry)
|
||||
|
||||
task['numOutputsTotal'] = numOutputsTotal
|
||||
task['taskStatusLabel'] = taskEntry.querySelector('.taskStatusLabel')
|
||||
task['outputContainer'] = taskEntry.querySelector('.img-preview')
|
||||
task['outputMsg'] = taskEntry.querySelector('.outputMsg')
|
||||
task['previewPrompt'] = taskEntry.querySelector('.preview-prompt')
|
||||
task['progressBar'] = taskEntry.querySelector('.progressBar')
|
||||
task['stopTask'] = taskEntry.querySelector('.stopTask')
|
||||
|
||||
task['stopTask'].addEventListener('click', async function() {
|
||||
if (task['isProcessing']) {
|
||||
task.isProcessing = false
|
||||
try {
|
||||
let res = await fetch('/image/stop')
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
} else {
|
||||
let idx = taskQueue.indexOf(task)
|
||||
if (idx >= 0) {
|
||||
taskQueue.splice(idx, 1)
|
||||
}
|
||||
|
||||
taskEntry.remove()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
makeImageBtn.innerText = 'Make Image'
|
||||
makeImageBtn.disabled = false
|
||||
makeImageBtn.style.display = 'block'
|
||||
stopImageBtn.style.display = 'none'
|
||||
imagePreview.insertBefore(taskEntry, previewTools.nextSibling)
|
||||
|
||||
if (isSoundEnabled()) {
|
||||
playSound()
|
||||
}
|
||||
task['previewPrompt'].innerText = prompt
|
||||
|
||||
time = new Date().getTime() - time
|
||||
time /= 1000
|
||||
taskQueue.unshift(task)
|
||||
|
||||
if (successCount === batchCount) {
|
||||
outputMsg.innerText = 'Processed ' + numOutputsTotal + ' images in ' + time + ' seconds'
|
||||
|
||||
setStatus('request', 'done', 'success')
|
||||
}
|
||||
|
||||
if (randomSeedField.checked) {
|
||||
seedField.value = seed
|
||||
}
|
||||
initialText.style.display = 'none'
|
||||
}
|
||||
|
||||
// create a file name with embedded prompt and metadata
|
||||
@ -673,17 +768,37 @@ function createFileName() {
|
||||
return fileName
|
||||
}
|
||||
|
||||
stopImageBtn.addEventListener('click', async function() {
|
||||
async function stopAllTasks() {
|
||||
taskQueue.forEach(task => {
|
||||
task.isProcessing = false
|
||||
})
|
||||
taskQueue = []
|
||||
|
||||
if (currentTask !== null) {
|
||||
currentTask.isProcessing = false
|
||||
}
|
||||
|
||||
try {
|
||||
let res = await fetch('/image/stop')
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
}
|
||||
|
||||
stopImageBtn.style.display = 'none'
|
||||
makeImageBtn.style.display = 'block'
|
||||
clearAllPreviewsBtn.addEventListener('click', async function() {
|
||||
await stopAllTasks()
|
||||
|
||||
taskStopped = true
|
||||
let taskEntries = document.querySelectorAll('.imageTaskContainer')
|
||||
taskEntries.forEach(task => {
|
||||
task.remove()
|
||||
})
|
||||
|
||||
previewTools.style.display = 'none'
|
||||
initialText.style.display = 'block'
|
||||
})
|
||||
|
||||
stopImageBtn.addEventListener('click', async function() {
|
||||
await stopAllTasks()
|
||||
})
|
||||
|
||||
soundToggle.addEventListener('click', handleBoolSettingChange(SOUND_ENABLED_KEY))
|
||||
@ -780,7 +895,7 @@ updatePromptStrength()
|
||||
|
||||
useBetaChannelField.addEventListener('click', async function(e) {
|
||||
if (serverStatus !== 'online') {
|
||||
logError('The server is still starting up..')
|
||||
// logError('The server is still starting up..')
|
||||
alert('The server is still starting up..')
|
||||
e.preventDefault()
|
||||
return false
|
||||
@ -941,6 +1056,22 @@ function millisecondsToStr(milliseconds) {
|
||||
return s;
|
||||
}
|
||||
|
||||
// https://gomakethings.com/finding-the-next-and-previous-sibling-elements-that-match-a-selector-with-vanilla-js/
|
||||
function getNextSibling(elem, selector) {
|
||||
// Get the next sibling element
|
||||
var sibling = elem.nextElementSibling
|
||||
|
||||
// If there's no selector, return the first sibling
|
||||
if (!selector) return sibling
|
||||
|
||||
// If the sibling matches our selector, use it
|
||||
// If not, jump to the next sibling and continue the loop
|
||||
while (sibling) {
|
||||
if (sibling.matches(selector)) return sibling
|
||||
sibling = sibling.nextElementSibling
|
||||
}
|
||||
}
|
||||
|
||||
function createCollapsibles(node) {
|
||||
if (!node) {
|
||||
node = document
|
||||
@ -960,7 +1091,7 @@ function createCollapsibles(node) {
|
||||
|
||||
c.addEventListener('click', function() {
|
||||
this.classList.toggle("active")
|
||||
let content = this.nextElementSibling
|
||||
let content = getNextSibling(this, '.collapsible-content')
|
||||
if (content.style.display === "block") {
|
||||
content.style.display = "none"
|
||||
handle.innerHTML = '➕' // plus
|
||||
|
@ -3,6 +3,7 @@ import json
|
||||
class Request:
|
||||
session_id: str = "session"
|
||||
prompt: str = ""
|
||||
negative_prompt: str = ""
|
||||
init_image: str = None # base64
|
||||
mask: str = None # base64
|
||||
num_outputs: int = 1
|
||||
@ -30,6 +31,7 @@ class Request:
|
||||
return {
|
||||
"session_id": self.session_id,
|
||||
"prompt": self.prompt,
|
||||
"negative_prompt": self.negative_prompt,
|
||||
"num_outputs": self.num_outputs,
|
||||
"num_inference_steps": self.num_inference_steps,
|
||||
"guidance_scale": self.guidance_scale,
|
||||
@ -46,6 +48,7 @@ class Request:
|
||||
return f'''
|
||||
session_id: {self.session_id}
|
||||
prompt: {self.prompt}
|
||||
negative_prompt: {self.negative_prompt}
|
||||
seed: {self.seed}
|
||||
num_inference_steps: {self.num_inference_steps}
|
||||
sampler: {self.sampler}
|
||||
|
@ -343,7 +343,7 @@ def do_mk_img(req: Request):
|
||||
modelCS.to(device)
|
||||
uc = None
|
||||
if opt_scale != 1.0:
|
||||
uc = modelCS.get_learned_conditioning(batch_size * [""])
|
||||
uc = modelCS.get_learned_conditioning(batch_size * [req.negative_prompt])
|
||||
if isinstance(prompts, tuple):
|
||||
prompts = list(prompts)
|
||||
|
||||
@ -450,7 +450,7 @@ def do_mk_img(req: Request):
|
||||
if return_orig_img:
|
||||
save_image(img, img_out_path)
|
||||
|
||||
save_metadata(meta_out_path, prompts, opt_seed, opt_W, opt_H, opt_ddim_steps, opt_scale, opt_strength, opt_use_face_correction, opt_use_upscale, opt_sampler_name)
|
||||
save_metadata(meta_out_path, prompts, opt_seed, opt_W, opt_H, opt_ddim_steps, opt_scale, opt_strength, opt_use_face_correction, opt_use_upscale, opt_sampler_name, req.negative_prompt)
|
||||
|
||||
if return_orig_img:
|
||||
img_data = img_to_base64_str(img)
|
||||
@ -511,8 +511,8 @@ def save_image(img, img_out_path):
|
||||
except:
|
||||
print('could not save the file', traceback.format_exc())
|
||||
|
||||
def save_metadata(meta_out_path, prompts, opt_seed, opt_W, opt_H, opt_ddim_steps, opt_scale, opt_prompt_strength, opt_correct_face, opt_upscale, sampler_name):
|
||||
metadata = f"{prompts[0]}\nWidth: {opt_W}\nHeight: {opt_H}\nSeed: {opt_seed}\nSteps: {opt_ddim_steps}\nGuidance Scale: {opt_scale}\nPrompt Strength: {opt_prompt_strength}\nUse Face Correction: {opt_correct_face}\nUse Upscaling: {opt_upscale}\nSampler: {sampler_name}"
|
||||
def save_metadata(meta_out_path, prompts, opt_seed, opt_W, opt_H, opt_ddim_steps, opt_scale, opt_prompt_strength, opt_correct_face, opt_upscale, sampler_name, negative_prompt):
|
||||
metadata = f"{prompts[0]}\nWidth: {opt_W}\nHeight: {opt_H}\nSeed: {opt_seed}\nSteps: {opt_ddim_steps}\nGuidance Scale: {opt_scale}\nPrompt Strength: {opt_prompt_strength}\nUse Face Correction: {opt_correct_face}\nUse Upscaling: {opt_upscale}\nSampler: {sampler_name}\nNegative Prompt: {negative_prompt}"
|
||||
|
||||
try:
|
||||
with open(meta_out_path, 'w') as f:
|
||||
|
@ -55,6 +55,7 @@ app.mount('/media', StaticFiles(directory=os.path.join(SD_UI_DIR, 'frontend/asse
|
||||
class ImageRequest(BaseModel):
|
||||
session_id: str = "session"
|
||||
prompt: str = ""
|
||||
negative_prompt: str = ""
|
||||
init_image: str = None # base64
|
||||
mask: str = None # base64
|
||||
num_outputs: int = 1
|
||||
@ -110,7 +111,10 @@ async def ping():
|
||||
model_is_loading = True
|
||||
|
||||
from sd_internal import runtime
|
||||
runtime.load_model_ckpt(ckpt_to_use="sd-v1-4")
|
||||
|
||||
custom_weight_path = os.path.join(SCRIPT_DIR, 'custom-model.ckpt')
|
||||
ckpt_to_use = "sd-v1-4" if not os.path.exists(custom_weight_path) else "custom-model"
|
||||
runtime.load_model_ckpt(ckpt_to_use=ckpt_to_use)
|
||||
|
||||
model_loaded = True
|
||||
model_is_loading = False
|
||||
@ -127,6 +131,7 @@ def image(req : ImageRequest):
|
||||
r = Request()
|
||||
r.session_id = req.session_id
|
||||
r.prompt = req.prompt
|
||||
r.negative_prompt = req.negative_prompt
|
||||
r.init_image = req.init_image
|
||||
r.mask = req.mask
|
||||
r.num_outputs = req.num_outputs
|
||||
|
Loading…
Reference in New Issue
Block a user