Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: parlance-zz/g-diffuser-bot
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: aio-release
Choose a base ref
...
head repository: parlance-zz/g-diffuser-bot
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: aio
Choose a head ref
  • 14 commits
  • 5 files changed
  • 1 contributor

Commits on Nov 24, 2022

  1. updated readme for aio

    parlance-zz committed Nov 24, 2022
    Copy the full SHA
    81e132a View commit details
  2. updated readme

    parlance-zz committed Nov 24, 2022
    Copy the full SHA
    e7a8e05 View commit details
  3. updated readme

    parlance-zz committed Nov 24, 2022
    Copy the full SHA
    2d03df6 View commit details
  4. Copy the full SHA
    d4c0597 View commit details
  5. Copy the full SHA
    6f51709 View commit details

Commits on Nov 25, 2022

  1. updated readme

    parlance-zz committed Nov 25, 2022
    Copy the full SHA
    f8e2d6c View commit details
  2. updated readme

    parlance-zz committed Nov 25, 2022
    Copy the full SHA
    c71f1ff View commit details
  3. Copy the full SHA
    dd910af View commit details
  4. Copy the full SHA
    c745cff View commit details
  5. Copy the full SHA
    403fcb4 View commit details
  6. improved zoom defaults

    parlance-zz committed Nov 25, 2022
    Copy the full SHA
    eba0559 View commit details
  7. Copy the full SHA
    eb36e32 View commit details

Commits on Nov 26, 2022

  1. Copy the full SHA
    4045db5 View commit details
  2. Copy the full SHA
    0d3a239 View commit details
Showing with 148 additions and 132 deletions.
  1. +27 −49 README.md
  2. +15 −15 g_diffuser_defaults.py
  3. +71 −56 inputs/scripts/zoom_composite.py
  4. +34 −11 inputs/scripts/zoom_maker.py
  5. +1 −1 modules/g_diffuser_lib.py
76 changes: 27 additions & 49 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
![https://www.stablecabal.org](https://www.g-diffuser.com/stablecabal.png) https://www.stablecabal.org

## [g-diffuser-bot](https://www.g-diffuser.com) - Discord bot and interface for Stable Diffusion
## [g-diffuser-bot](https://www.g-diffuser.com) - Discord bot and interface for Stable Diffusion
- [G-Diffuser / Stable Cabal Discord](https://discord.gg/stFy2UPppg)

Nov 20-2022 Update: The infinite zoom scripts have been updated with some improvements, notably a new compositer script that is hundreds of times faster than before. The environment / requirements have changed, so if you want to use the new zoom compositer be sure to run a "conda env update -f environment.yaml"
Nov 23-2022 Update: The first release of the all-in-one installer version of G-Diffuser is here. This release no longer requires the installation of WSL or Docker, and has a systray icon to keep track of and launch G-Diffuser components. The download link is available under this project's [releases](https://github.com/parlance-zz/g-diffuser-bot/releases/tag/aio-release).

Nov 20-2022 Update: The infinite zoom scripts have been updated with some improvements, notably a new compositer script that is hundreds of times faster than before.

Nov 19-2022 Update: There are some new g-diffuser CLI scripts that can be used to make infinite zoom videos. Check out [/inputs/scripts/](https://github.com/parlance-zz/g-diffuser-bot/tree/dev/inputs/scripts) and have a look at [zoom_maker](https://github.com/parlance-zz/g-diffuser-bot/blob/dev/inputs/scripts/zoom_maker.py) and [zoom_composite](https://github.com/parlance-zz/g-diffuser-bot/blob/dev/inputs/scripts/zoom_composite.py)

@@ -13,50 +15,26 @@ Nov 08-2022 Update: In/out-painting and img2img (aka "riffing") has (finally) be

Nov 07-2022 Update: This update adds support for **clip guided models** and new parameters to control them. For now clip guidance has a heavy performance penalty, but this will improve with optimization. This update also adds **negative prompt support** to both the CLI and discord bot, and changes the default loaded models to include SD1.5 and SD1.5 with (small) clip. This update also adds several **new samplers (dpmspp_1, dpmspp_2, dpmspp_3)**.

Nov 02-2022 Update: In/out-painting bugs are now fixed, and the interactive CLI now prints proper error messages.

Oct 22-2022 Update: Most of the annoying bugs in the Discord bot have now been fixed. The gRPC server now uses a Docker image which includes xformers support (large speed boost) as well as support for **stable-diffusion-v1-5 (which is the new default)**. The install instructions have changed accordingly, please find the changes below:

## Vision for the g-diffuser-bot project:
- Nov 01-2022: There are now many mature and rapidly evolving easy-to-use frontends and discord bots for Stable Diffusion. As a lone developer I do not necessarily have the time or resources to keep pace with these developments, but I will do my best to continue to maintain the project and may occasionally add new features.

## Installation:
- System Requirements: Windows 10 (1903+), Windows 11, or Linux (Ubuntu 20+), nvidia GPU with at least 8GB VRAM, ~10GB free space for model downloads
- If you are running Windows 10/11 you may need to turn on "developer mode" before beginning the install instructions. Look for "developer settings" in the start menu.

1) git clone this repository to a folder of your choice (or click the green "code" button up top and click "download zip")
2) download / install miniconda (https://docs.conda.io/en/latest/miniconda.html)
3) open a conda prompt (click on the start menu and look for "anaconda prompt"), then navigate to the folder where you cloned or downloaded this repository.
4) run "conda env create -f environment.yaml"
5) Install Docker Desktop:<br/>
- On Windows: https://docs.docker.com/desktop/install/windows-install/ <br/>
- On Linux: sudo apt install docker-desktop
6) Sign up for an account at https://huggingface.co/
```
- Accept the terms of use for the models you wish to use:
(https://huggingface.co/runwayml/stable-diffusion-v1-5, https://huggingface.co/hakurei/waifu-diffusion-v1-4)
- Go to https://huggingface.co/settings/tokens and create a new access token.
- Open g_diffuser_config.py, find GRPC_SERVER_SETTINGS.hf_token = "YOUR_HUGGINGFACE_ACCESS_TOKEN_HERE"
Replace the placeholder text with the access token you generated above and save the file.
- If you're using the Discord bot this is also where you enter your Discord bot token and guild id.
(https://discordapp.com/developers/applications/, https://www.writebots.com/discord-bot-token/)
```
Optional: edit g_diffuser_config.py and g_diffuser_defaults.py to change any other default settings of interest

## Running:
1) Run the discord bot by using "start_discord_bot.bat"
2) Run the interactive CLI by using "start_interactive_cli.bat"
3) You can (optionally) start the sdgrpcserver with "start_server.bat" to see the server console in it's own separate window

## Updating:
- Simply git pull or download and replace your files with those from this repository. You probably won't need to replace your g_diffuser_config.py or g_diffuser_defaults.py files, but you may need to merge changes.
- The conda environment is sometimes (rarely) updated to include new requirements. If you git pull and get an error running the software try updating the conda environment with any new dependencies by running "conda env update -f environment.yaml"

## Troubleshooting:
- Better install instructions are (always) coming
- Docker Desktop depends on WSL2 (Windows subsystem for Linux). For best results always make sure you're using the latest version of WSL by opening a command prompt as administrator and running "wsl --update"
- Docker Desktop has a helpful GUI that you can use to keep track of the gRPC server and it's Docker "container". You can view the server parameters it was launched with, restart it or shut it down, and view the console output to track down any errors from the grpc server side. In some rare cases (or when updating) you may need to delete the existing "image" from the docker images list.
- If you have questions or problems running g-diffuser-bot, please post as much detailed information as you can in (https://github.com/parlance-zz/g-diffuser-bot/discussions/categories/q-a), either myself or someone in the community may be able to help you. Thank you for your patience.
## System Requirements:
- Windows 10+ (1903+), nvidia GPU with at least 8GB VRAM, ~40GB free space for model downloads
- You may need to turn on "developer mode" before beginning the install instructions. Look for "developer settings" in the start menu.

## G-Diffuser all-in-one
The first release of the all-in-one installer is here. It notably features much easier "one-click" installation and updating, as well as a systray icon to keep track of g-diffuser programs and the server while it is running.

## Installation / Setup
- Download and extract [G-Diffuser AIO Installer (Windows 10+ 64-bit)](https://github.com/parlance-zz/g-diffuser-bot/releases/tag/aio-release) to a folder of your choice.
- Run install_or_update.cmd at least once (once to install, and again later if you wish update to the latest version)
- Edit the filed named "config" and make sure to add your hugging-face access token and save the file.
- If you don't have a huggingface token yet:
- Register for a HuggingFace account at https://huggingface.co/join
- Follow the instructions to access the repository at https://huggingface.co/CompVis/stable-diffusion-v1-4 (don't worry, this doesn't mean SD1.4 will be downloaded or used, it just grants you the necessary access to download stable diffusion models)
- Create a token at https://huggingface.co/settings/tokens (if required, choose the "read" role)

## Usage
- Run run.cmd to start the G-Diffuser system
- You should see a G-Diffuser icon in your systray / notification area. Click on the icon to open and interact with the G-Diffuser system. If the icon is missing be sure it isn't hidden by clicking the "up" arrow near the notification area.

![G-Diffuser Systray](https://www.g-diffuser.com/systray_screenshot.jpg)

GUI is coming soon(tm)
30 changes: 15 additions & 15 deletions g_diffuser_defaults.py
Original file line number Diff line number Diff line change
@@ -3,22 +3,22 @@
# ******************** SETTINGS BEGIN ************************

DEFAULT_SAMPLE_SETTINGS = argparse.Namespace()
DEFAULT_SAMPLE_SETTINGS.sampler = "k_dpm_2_ancestral" # default sampling mode (ddim, plms, k_euler, k_euler_ancestral, k_heun, k_dpm_2, k_dpm_2_ancestral, k_lms)
DEFAULT_SAMPLE_SETTINGS.n = 1 # number of samples to generate per sample command by default
DEFAULT_SAMPLE_SETTINGS.resolution = (640,640) # default resolution for img / video outputs
DEFAULT_SAMPLE_SETTINGS.max_resolution = (800,800) # if you run out of ram due to output resolution lower this to prevent exceeding your max memory
DEFAULT_SAMPLE_SETTINGS.resolution_granularity = 8 # required by stable-diffusion for now due to latent space subsampling
DEFAULT_SAMPLE_SETTINGS.noise_start = 0.65 # default strength for pure img2img or style transfer
DEFAULT_SAMPLE_SETTINGS.noise_end = 0.01 # can be used to influence in/out-painting quality
DEFAULT_SAMPLE_SETTINGS.noise_eta = 0.70 # can be used to influence in/out-painting quality
DEFAULT_SAMPLE_SETTINGS.scale = 10. # default cfg scale
DEFAULT_SAMPLE_SETTINGS.steps = 75 # default number of sampling steps, lower to reduce sampling time
DEFAULT_SAMPLE_SETTINGS.noise_q = 1. # fall-off of shaped noise distribution for in/out-painting
DEFAULT_SAMPLE_SETTINGS.auto_seed_range = (10000,99999) # automatic random seed range
DEFAULT_SAMPLE_SETTINGS.sampler = "dpmspp_2" # default sampling mode (ddim, plms, k_euler, k_euler_ancestral, k_heun, k_dpm_2, k_dpm_2_ancestral, k_lms)
DEFAULT_SAMPLE_SETTINGS.n = 1 # number of samples to generate per sample command by default
DEFAULT_SAMPLE_SETTINGS.resolution = (640,640) # default resolution for img / video outputs
DEFAULT_SAMPLE_SETTINGS.max_resolution = (960,960) # if you run out of ram due to output resolution lower this to prevent exceeding your max memory
DEFAULT_SAMPLE_SETTINGS.resolution_granularity = 8 # required by stable-diffusion for now due to latent space subsampling
DEFAULT_SAMPLE_SETTINGS.noise_start = 0.65 # default strength for pure img2img or style transfer
DEFAULT_SAMPLE_SETTINGS.noise_end = 0.01 # can be used to influence in/out-painting quality
DEFAULT_SAMPLE_SETTINGS.noise_eta = 0.70 # can be used to influence in/out-painting quality
DEFAULT_SAMPLE_SETTINGS.scale = 14. # default cfg scale
DEFAULT_SAMPLE_SETTINGS.steps = 12 # default number of sampling steps, lower to reduce sampling time
DEFAULT_SAMPLE_SETTINGS.noise_q = 1. # fall-off of shaped noise distribution for in/out-painting
DEFAULT_SAMPLE_SETTINGS.auto_seed_range = (10000,99999) # automatic random seed range
DEFAULT_SAMPLE_SETTINGS.model_name = "stable-diffusion-v1-5-clip-small" # default model id to use, see g_diffuser_config_models.yaml for the list of models to be loaded by grpc server
DEFAULT_SAMPLE_SETTINGS.guidance_strength = 0.25 # default guidance strength (only affects 'clip guided' models)
DEFAULT_SAMPLE_SETTINGS.negative_prompt = None # default negative prompt string or None
DEFAULT_SAMPLE_SETTINGS.min_outpaint_noise = 1.618 # 1 for pure shaped noise, values above 1. add some unshaped noise
DEFAULT_SAMPLE_SETTINGS.guidance_strength = 0.5 # default guidance strength (only affects 'clip guided' models)
DEFAULT_SAMPLE_SETTINGS.negative_prompt = None # default negative prompt string or None
DEFAULT_SAMPLE_SETTINGS.min_outpaint_noise = 1. # 1 for pure shaped noise, values above 1. add some unshaped noise

# ******************** SETTINGS END ************************

127 changes: 71 additions & 56 deletions inputs/scripts/zoom_composite.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
import cv2
import glob
import numpy as np
@@ -15,23 +16,28 @@

expand_softness = 100. # **the expand values here should match the values used to create the frames in zoom_maker**
expand_space = 1.
expand_top = 40
expand_bottom = 40
expand_left = 40
expand_right = 40

start_in_black_void = False # enabled to start zooming out from a black void instead of starting on the first frame
num_interpolated_frames = 50 # number of interpolated frames per keyframe
frame_rate = 24 # fps of the output video
output_file = "zoom.mp4" # name of output file (this will be saved in the folder with the key frames)
preview_output = False # if enabled this will show a preview of the video in a window as it renders
video_size = (1920*2, 1080*2) # 4k by default
expand_top = 30
expand_bottom = 30
expand_left = 30
expand_right = 30

start_in_black_void = False # enabled to start zooming out from a black void instead of starting on the first frame
num_interpolated_frames = 25 # number of interpolated frames per keyframe, controls zoom speed (and the expand ratio)
frame_rate = 30 # fps of the output video
output_file = "zoom.mp4" # name of output file (this will be saved in the folder with the key frames)
preview_output = False # if enabled this will show a preview of the video in a window as it renders
zoom_out = False # if enabled this will zoom out instead of zooming in
rotate_speed = 0. # change from 0. if you _really_ want to barf
acceleration_smoothing = 0. #1.8 # if > 0. this slows the start and stop, good values are 1 to 3
video_size = (1920*2, 1080*2) # video output resolution
encode_lossless = False # set to True to make an uncompressed video file (this will take a lot of disk space)

# *****************************************************************

# find keyframes and sort them
print("Loading keyframes from {0}...".format(DEFAULT_PATHS.outputs+"/"+frames_path))
frame_filenames = sorted(glob.glob(DEFAULT_PATHS.outputs+"/"+frames_path+"/*.png"), reverse=True)
#frame_filenames = frame_filenames[0:3] # limit to 20 frames for testing
num_keyframes = len(frame_filenames)

frame0_cv2_image = cv2.imread(frame_filenames[0])
@@ -65,57 +71,69 @@
glGenerateMipmap(GL_TEXTURE_2D)

# create video encoder
video_output_path = DEFAULT_PATHS.outputs+"/"+gdl.get_noclobber_checked_path(DEFAULT_PATHS.outputs, frames_path+"/"+output_file)
if encode_lossless == False:
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
else:
fourcc = cv2.VideoWriter_fourcc(*'HFYU')
output_file = os.path.splitext(output_file)[0]+".avi"

print("Creating video of size {0}x{1}...".format(video_size[0], video_size[1]))
result = cv2.VideoWriter(video_output_path, cv2.VideoWriter_fourcc(*'mp4v'), frame_rate, video_size)
video_output_path = DEFAULT_PATHS.outputs+"/"+gdl.get_noclobber_checked_path(DEFAULT_PATHS.outputs, frames_path+"/"+output_file)

result = cv2.VideoWriter(video_output_path, fourcc, frame_rate, video_size)
frame_pixels = (GLubyte * (3*video_size[0]*video_size[1]))(0)

if preview_output: # show video window if preview is enabled
pygame.display.set_mode(video_size, SHOWN|DOUBLEBUF|OPENGL, vsync=0)
if start_in_black_void: start_offset = 0 # start by zooming in from a black screen if enabled
else: start_offset = 4 # otherwise start very slightly pulled back from the first keyframe

# create a schedule of time values for each rendered video frame
if acceleration_smoothing > 0.:
t_schedule = np.tanh(np.linspace(-acceleration_smoothing, acceleration_smoothing, num_interpolated_frames * num_keyframes))
t_schedule = t_schedule - np.min(t_schedule)
t_schedule = t_schedule / np.max(t_schedule) * (num_keyframes-2.5) + start_offset
else:
t_schedule = np.linspace(start_offset, num_keyframes-2.5, num_interpolated_frames * num_keyframes)

if zoom_out:
t_schedule = t_schedule[::-1] # reverse the schedule if zooming out

try:
for f in range(start_offset, num_keyframes):
print("Rendering {0}/{1}...".format(f+1, num_keyframes))
for i in range(num_interpolated_frames):
glClear(GL_COLOR_BUFFER_BIT)

t = f + i/num_interpolated_frames
start_frame = int(np.clip(t+0.5-8., 0, num_keyframes-1))
end_frame = int(np.clip(t+0.5+8., 1, num_keyframes))
for f0 in range(start_frame, end_frame):
z = f0 - t
"""
num_oversamples = 8
radial_blur_amount = 1.
glColor4f(1., 1., 1., 1./num_oversamples)
for s in range(num_oversamples):
z = f0 - t + 1. + s / num_oversamples / 30. * radial_blur_amount
"""

glPushMatrix()
scaleX = ((expand_left + expand_right)/100. +1.) ** (-z)
scaleY = ((expand_top + expand_bottom)/100. +1.) ** (-z)
glScalef(scaleX * aspect_adjustmentX, scaleY * aspect_adjustmentY, 1.)

glBindTexture(GL_TEXTURE_2D, frame_textures[f0])
glBegin(GL_QUADS)
glTexCoord2f(0., 0.); glVertex2f(-1.,-1.)
glTexCoord2f(1., 0.); glVertex2f( 1.,-1.)
glTexCoord2f(1., 1.); glVertex2f( 1., 1.)
glTexCoord2f(0., 1.); glVertex2f(-1., 1.)
glEnd()
glPopMatrix()

glReadPixels(0, 0, video_size[0], video_size[1], GL_RGB, GL_UNSIGNED_BYTE, frame_pixels)
np_frame = np.array(frame_pixels).reshape(video_size[1], video_size[0], 3)
result.write(np_frame)

pygame.display.flip()
for e in pygame.event.get():
if e.type == pygame.QUIT:
raise Exception("Operation cancelled by user")
for f in range(len(t_schedule)):
if (f % frame_rate) == 0: # print progress every (video) second
print("Rendering {0:.2f}%...".format(f/len(t_schedule)*100.))
t = t_schedule[f]

glClear(GL_COLOR_BUFFER_BIT)
start_frame = int(np.clip(t+0.5-10., 0, num_keyframes-1))
end_frame = int(np.clip(t+0.5+10., 1, num_keyframes))
for f0 in range(start_frame, end_frame):
z = f0 - t

glPushMatrix()
scaleX = ((expand_left + expand_right)/100. +1.) ** (-z)
scaleY = ((expand_top + expand_bottom)/100. +1.) ** (-z)
glScalef(scaleX * aspect_adjustmentX, scaleY * aspect_adjustmentY, 1.)
glRotatef(t * rotate_speed, 0., 0., 1.)

glBindTexture(GL_TEXTURE_2D, frame_textures[f0])
glBegin(GL_QUADS)
glTexCoord2f(0., 0.); glVertex2f(-1.,-1.)
glTexCoord2f(1., 0.); glVertex2f( 1.,-1.)
glTexCoord2f(1., 1.); glVertex2f( 1., 1.)
glTexCoord2f(0., 1.); glVertex2f(-1., 1.)
glEnd()
glPopMatrix()

glReadPixels(0, 0, video_size[0], video_size[1], GL_RGB, GL_UNSIGNED_BYTE, frame_pixels)
np_frame = np.array(frame_pixels).reshape(video_size[1], video_size[0], 3)
result.write(np_frame)

pygame.display.flip()
for e in pygame.event.get():
if e.type == pygame.QUIT:
raise Exception("Operation cancelled by user")

except Exception as e:
print("Error: {0}".format(str(e)))
@@ -124,8 +142,5 @@

pygame.quit()

for i in range(frame_rate*3): # linger on the last frame for 3 seconds
result.write(np_frame)

result.release()
print("Saved {0}".format(video_output_path))
Loading