diff --git a/.gitignore b/.gitignore index 1b0eb546..cb81decb 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,7 @@ htmlcov tests/results.xml .coverage* serverlog.txt + +# Backup and broken files from debugging +scripts/deforum_helpers/*.bak +scripts/deforum_helpers/*_broken.py diff --git a/INSTALL.txt b/INSTALL.txt new file mode 100644 index 00000000..91c9e9cf --- /dev/null +++ b/INSTALL.txt @@ -0,0 +1,105 @@ +MICROCOSM DEFORUM - HOW TO INSTALL +================================== + +You do not need GitHub, git, a terminal, or any developer tools. +This is a folder you copy into place. Five minutes, start to finish. + + +WHAT THIS IS +------------ +A modified version of the Deforum extension for AUTOMATIC1111 Stable Diffusion. +It is the normal Deforum you already know, plus a handful of additions: + + - Preset dropdown. Drag any number of settings files onto the preset box + and pick them from a list, instead of typing file paths. + - Drag and drop settings import, which also relinks the init image for you. + - Folder pickers for init images, video input and ControlNet, so you can + browse to a folder instead of typing the path. + - A Settings Editor tab for editing values without leaving the page. + - Tooltips on the parameters that never had any. + - Save As with a real Windows save dialog, and a prompts-only loader. + - Better error messages when ControlNet is misconfigured. + - An "Open the render viewer" button that opens the viewer in a browser tab. + +Nothing that already worked was removed. Your existing settings files still load. + + +BEFORE YOU START +---------------- +Close Stable Diffusion completely if it is running. + + +INSTALLING +---------- +1. Find your Stable Diffusion folder. It is the one containing "webui-user.bat". + Open the "extensions" folder inside it. The path looks like: + + ...\stable-diffusion-webui\extensions\ + +2. If there is already a folder called "deforum" in there, rename it to + "deforum-OLD". Do not delete it. That is your way back if you want it. + +3. Unzip the file you downloaded. You will get a folder called "deforum". + Drag that folder into the "extensions" folder from step 1. + + When you are done it must look exactly like this: + + ...\stable-diffusion-webui\extensions\deforum\scripts\ + ...\stable-diffusion-webui\extensions\deforum\INSTALL.txt + + If you instead see "extensions\deforum\deforum\scripts\", you have one + folder too many. Move the inner "deforum" up a level. + +4. Start Stable Diffusion the way you normally do. + +5. Click the Deforum tab. Under the Init tab you should now see a Preset + dropdown. That means it worked. + + +NOTHING TO INSTALL +------------------ +No pip installs, no downloads, no requirements. It uses only what +AUTOMATIC1111 already ships with. + + +LOADING THE INCLUDED SETTINGS +----------------------------- +"microcosm\BEST_DEFAULT_settings.txt" is the full Microcosm recipe: real +prompts, the whole LoRA stack, nothing stripped out. It is also pre-loaded: +after install it shows up in the Preset dropdown as "00 - Microcosm BEST". + + - Pick "00 - Microcosm BEST" from the Preset dropdown, or drop the settings + file onto the preset box yourself. + - The init image it wants, "microcosm-init.png", is in the same folder. + Drop it into the Init image box. + - It is set to 15,000 frames, which is about a 20 hour render. Turn + max_frames down to a few thousand for a first go. + - It expects the MOHAWK_v20 checkpoint. Any good SDXL model works, just + pick a different one in the usual checkpoint dropdown at the top left. + +Missing a LoRA is not fatal. Stable Diffusion prints a "couldn't find Lora" +line and carries on without it. The render still works, it just looks +different. + + +THE VIEWER +---------- +"microcosm\Microcosm.html" needs none of the above. Double-click it and it +opens in your browser. Or, inside Stable Diffusion, click the "Open the render +viewer" button on the Deforum tab: same file, either way. Drag a finished +render and its _settings.txt onto it and the panel under the video shows the +prompt, the LoRAs, the FOV and every camera value at the exact frame you are +watching. It works with your wifi off and nothing you open in it leaves your +machine. + + +IF SOMETHING GOES WRONG +----------------------- +The Deforum tab is missing, or Stable Diffusion will not start: + Close it. Rename "deforum" to "deforum-BROKEN" and rename your + "deforum-OLD" back to "deforum". You are exactly where you started. + Then tell Brian what the console window said. + +The Deforum tab is there but looks unchanged: + You probably have two copies. Check that there is no leftover + "deforum" folder somewhere else under "extensions". diff --git a/README.md b/README.md index a514500c..ff409f50 100644 --- a/README.md +++ b/README.md @@ -1,74 +1,290 @@ -# Deforum Stable Diffusion — official extension for AUTOMATIC1111's webui +# Deforum Stable Diffusion -- m1llipede fork -

- Last Commit - GitHub issues - GitHub stars - GitHub forks - -

+> **Fork of [deforum-art/sd-webui-deforum](https://github.com/deforum-art/sd-webui-deforum)** with UI improvements, workflow tools, and practical documentation focused on usability during long render sessions. -## Need help? See our [FAQ](https://github.com/deforum-art/sd-webui-deforum/wiki/FAQ-&-Troubleshooting) +This fork doesn't change the render engine. It only changes the UI and adds tools around it. Everything renders the same as upstream -- you just spend less time fighting the interface and more time iterating. -## Getting Started +--- -1. Install [AUTOMATIC1111's webui](https://github.com/AUTOMATIC1111/stable-diffusion-webui/). +## Start here, Microcosm ([`microcosm/`](microcosm/)) -2. Now two ways: either clone the repo into the `extensions` directory via git commandline launched within in the `stable-diffusion-webui` folder +**The render viewer, my best settings, and the notes behind them.** The viewer needs nothing installed, download one HTML file, double-click it, drag a render in, and watch the prompt / LoRAs / FOV / camera update **at the frame you're looking at**. Tick two renders to compare every parameter side by side with the differences highlighted. + +- **[`microcosm/Microcosm.html`](microcosm/Microcosm.html)**, the viewer (no install, works offline) +- **[`microcosm/BEST_DEFAULT_settings.txt`](microcosm/BEST_DEFAULT_settings.txt)**, the real Microcosm recipe: prompts, full LoRA stack, init image +- **[`microcosm/BEST_PRACTICES.txt`](microcosm/BEST_PRACTICES.txt)**, what causes streaking, the smoothness recipes, camera rules + +Once the extension is installed, the Deforum tab has an **Open the render viewer** button that opens this same `Microcosm.html` in a browser tab, one viewer, whether Stable Diffusion is open or closed. + +**[Full guide in `microcosm/README.md`](microcosm/README.md)** + +--- + +## Panel additions in this fork + +- **Preset dropdown**, pick a saved recipe, it loads into every field. Presets are ordinary complete settings `.txt` files in a `presets/` folder next to the WebUI. +- **Drag-and-drop preset import**, drop any number of settings files to add them as presets. Each is validated, has its `init_image` repaired if the file moved (or `use_init` turned off if it's genuinely gone, this silently breaks loads otherwise), and stale resume-timestrings cleared. +- **Folders accordion**, init-images and video/ControlNet input folders with a native folder picker. Models folder shown read-only, with a note that it's fixed at launch via `--ckpt-dir`. +- **SUGGESTED values and info text** on parameters and ControlNet toggles that shipped with none. + +--- + +## Best settings ever, Spore Mandala + +The single best result to date. A 15,000-frame, 1024x1024, 30fps two-cycle journey: +geometric node-mandalas into a fractalized biological universe (mushroom caves, hidden +faces, eyes, owls and wolves, fractal butterflies and caterpillars), then vast empty space, +a wormhole, a biological singularity, then repeats. Hidden faces and creatures emerge +"out of nowhere" throughout. Negatives live in the negative-prompt field, not inline. + +**[`examples/Spore_Mandala_BEST_EVER_settings.txt`](examples/Spore_Mandala_BEST_EVER_settings.txt)** + +The numbers that matter for this one: + +| Setting | Value | Why | +|---|---|---| +| Sampler / scheduler | DPM++ 2M SDE / Karras | smooth, detail-preserving | +| Steps | 35 | clean frames, fast enough for 15k | +| `strength_schedule` | `0:(0.7)` | strong scene persistence with init | +| `cfg_scale_schedule` | `0: (8)` | punchy guidance for dense psychedelia | +| `noise_schedule` | `0: (0.01)` | low per-frame noise, stable scene | +| `diffusion_cadence` | `8` | high consistency over thousands of frames | +| `color_coherence` | LAB | locks the palette across the journey | +| `midas_weight` | `-0.3` | inverted depth = the signature inside-out psychedelic warp | +| `translation_z` | `0: (2.25)` | steady forward travel through the worlds | +| Keyframes | 43 @ 350-frame spacing | dense schedule, two full cycles | +| `add-detail-xl` LoRA | `0.8` | maximum fine detail without crunch | + +--- + +## Recommended starting settings + +The single best long-form recipe to date is included as a ready-to-load preset: + +**[`examples/Microcosm_Best_settings.txt`](examples/Microcosm_Best_settings.txt)** + +Load it via the Deforum tab's "Load all settings" button, then swap in your own +prompts. It is a 15,000-frame, 1024x1024, 30fps organic micro-world walk-through +tuned for long-run coherence. The numbers that matter: + +| Setting | Value | Why | +|---|---|---| +| Sampler / scheduler | DPM++ 2M SDE / Karras | smooth, detail-preserving | +| Steps | 40 | enough for clean frames without crawl | +| `strength_schedule` | `0: (0.6)` | frame-to-frame persistence without smearing | +| `cfg_scale_schedule` | `0: (6)` | guidance without over-baking | +| `noise_schedule` | `0: (0.01)` | low per-frame noise = stable scene | +| `noise_multiplier_schedule` | `0: (1.0)`, scheduling **off** | avoids the compounding-noise blowup that destroys coherence over thousands of frames | +| `diffusion_cadence` | `5` | strong consistency; in-between frames are warped, not re-rolled | +| `optical_flow_cadence` | DIS Fine | smooth motion across cadence skips | +| `color_coherence` | LAB | locks the palette so colors don't drift | +| `translation_z` | `0: (2.5)` | slow forward drift; the camera explores one evolving world | +| Keyframes | 50 @ 300-frame spacing | dense prompt schedule for constant visual change | + +Prompts in the preset are organic/photoreal micro-organism scenes; replace them +with your own while keeping the motion and noise/cadence values. + +--- + +## Quick Start ```sh -git clone https://github.com/deforum-art/sd-webui-deforum extensions/deforum +# Replace the stock Deforum extension with this fork +cd stable-diffusion-webui/extensions +rm -rf deforum +git clone https://github.com/m1llipede/sd-webui-deforum deforum ``` -Or download this repository, locate the `extensions` folder within your WebUI installation, create a folder named `deforum` and put the contents of the downloaded directory inside of it. Then restart WebUI. +Restart the WebUI. The Deforum tab will appear with all changes active. + +--- + +## What's Different (vs upstream Deforum) + +Every change below is something that was missing, broken, or annoying in the stock extension. Each one is a direct response to real problems encountered during hundreds of hours of render sessions. + +### 1. Keyframes Tab -- Two-Column Layout + +The Keyframes tab now shows Strength schedules (Strength / CFG / Seed / SubSeed / Step / Sampler / Checkpoint) and Motion tabs (Motion / Noise / Coherence / Anti-Blur / Depth) **side by side** instead of stacked. You can see both without scrolling. + +![Keyframes tab with two-column layout](screenshots/deforum-keyframes.png) + +### 2. Settings File Workflow -- Save As, Drag & Drop, Live Editor + +Stock Deforum makes it hard to manage settings files. This fork adds: + +- **Drag & drop upload** -- drop any `.txt` or `.json` settings file onto the Upload area +- **Upload auto-updates the path** -- so Save writes back to the correct file +- **Save As... button** -- save settings to any filename/path via popup dialog +- **Live JSON settings editor** -- full JSON editor built into the left panel + +![Run tab with Save As and Upload](screenshots/deforum-run-tab.png) + +![Settings Editor tab](screenshots/deforum-settings-editor.png) + +### 3. Init Image Auto-Enable + +Dropping an image into the Init image box now automatically ticks the "Use init" checkbox. In stock Deforum, renders silently ignore the init image if you forget to manually tick the checkbox. + +![Init tab](screenshots/deforum-init-tab.png) + +### 4. MiDaS/Zoe Weight Always Visible + +The MiDaS weight field is now always shown in Depth Warping & FOV. Stock Deforum hides it unless you select a legacy depth algorithm from the dropdown -- but you almost always want to adjust it. + +### 5. Improved Tooltips + +Stock Deforum has minimal or empty tooltips on critical fields. This fork adds plain-English descriptions for: + +| Field | What the tooltip explains | +|---|---| +| `noise_schedule` | What higher/lower values do to per-frame variation | +| `diffusion_cadence` | Speed/quality tradeoff (1 = every frame, 2-4 = good balance) | +| `optical_flow_cadence` | RAFT vs DIS Fine vs DIS Medium vs Farneback tradeoffs | +| `color_coherence` | LAB vs HSV vs RGB vs None and when to use each | +| `seed_behavior` | iter / fixed / random / schedule in plain English | +| `midas_weight` | Range guidance and default recommendation | +| `perspective_flip_*` | Which axis each parameter controls (were blank) | +| `enable_perspective_flip` | The 2D-simulates-3D use case | + +### 6. Bug Fixes + +- **Save crash** -- fixed a NoneType crash when saving settings with no model loaded +- **Tab disappearance** -- Quick Tools accordion referenced non-existent component keys, causing KeyError on startup; restored working UI + +### 7. Larger Output Gallery + +The gallery fills ~75% of the viewport instead of the cramped default. You can actually see what you're rendering. + +--- + +## Deforum Compare -- Render Comparison Tool + +A standalone HTML tool for reviewing and comparing renders side by side. Lives in `tools/Deforum_Compare_Portable/`. + +**The problem it solves:** After 20+ test renders with different settings, you need to figure out which combination of strength, CFG, noise, cadence, optical flow, and model produced the best results. Deforum's auto-saved settings files contain 200+ parameters each -- manually diffing them is impossible. + +![Compare tool landing page](screenshots/compare-landing.png) + +### What it does + +1. **Open any folder** of Deforum outputs -- it recursively scans all subfolders +2. **Matches videos to settings files** automatically (by timestamp and folder name) +3. **Displays everything in a sortable table** with inline video playback +4. **Select renders to compare** -- check the boxes and click "Compare Selected" +5. **Shows a full settings diff** with render-critical parameters (strength, CFG, noise, cadence, FOV, optical flow, depth) sorted to the top, camera motion in its own section, and all remaining parameters below +6. **"Only show differences" toggle** hides identical parameters so you see only what changed + +### Features + +- Star rating and notes per render (persisted in browser localStorage) +- Drag-reorder rows to group interesting renders together +- Color-coded columns showing which settings vary between renders +- Full-size video viewer with left/right arrow key navigation +- Whole-page zoom control (100% / 150% / 200%) +- Export notes to CSV for sharing +- No install needed -- works on any machine with Chrome + Python + +### How to use it + +1. Double-click `tools/Deforum_Compare_Portable/Launch Deforum Compare.bat` +2. Click "Open Folder" and select your `outputs/img2img-images` directory +3. Browse, rate, and compare your renders + +The .bat starts a tiny Python web server (needed for the folder picker API) and opens Chrome. Keep the command window open while using the tool. + +--- + +## Best Practices -- Notes from Long Render Sessions + +Practical lessons from hundreds of hours of Deforum renders. Not from docs -- from actual experience with what works and what doesn't. -Or launch A1111, navigate to the Extensions tab, choose Available, find deforum in the list of available extensions and install it. Restart A1111 once the extension has been installed. -3. Open the webui, find the Deforum tab at the top of the page. +### Sampler & Quality -4. Enter the animation settings. Refer to [this general guide](https://docs.google.com/document/d/1pEobUknMFMkn8F5TMsv8qRzamXX_75BShMMXV8IFslI/edit) and [this guide to math keyframing functions in Deforum](https://docs.google.com/document/d/1pfW1PwbDIuW0cv-dnuyYj1UzPqe23BlSLTJsqazffXM/edit?usp=sharing). However, **in this version prompt weights less than zero don't just like in original Deforum!** Split the positive and the negative prompt in the json section using --neg argument like this "apple:\`where(cos(t)>=0, cos(t), 0)\`, snow --neg strawberry:\`where(cos(t)<0, -cos(t), 0)\`" +- **DPM++ 2M SDE + Karras at 40 steps** is the most reliable baseline. Smooth frame-to-frame, fast enough for 8000+ frame runs. +- **Resolution: 1024x1024** for SDXL. Higher rarely improves animation at playback speed. -5. To view animation frames as they're being made, without waiting for the completion of an animation, go to the 'Settings' tab and set the value of this toolbar **above zero**. Warning: it may slow down the generation process. +### Coherence & Motion -![adsdasunknown](https://user-images.githubusercontent.com/14872007/196064311-1b79866a-e55b-438a-84a7-004ff30829ad.png) +- **Diffusion cadence 2-4** is the sweet spot. Cadence 1 burns time and over-cooks artifacts. Cadence 2-4 lets optical flow do the work between frames. +- **Strength 0.80-0.85** is the working range for 3D mode. Below 0.78 the model loses grip; above 0.88 you get flicker. +- **Seed behavior: schedule** gives controlled organic variation without the frozen look of fixed seed or the chaos of random. +### Prompt Keyframing -6. Run the script and see if you got it working or even got something. **In 3D mode a large delay is expected at first** as the script loads the depth models. In the end, using the default settings the whole thing should consume 6.4 GBs of VRAM at 3D mode peaks and no more than 3.8 GB VRAM in 3D mode if you launch the webui with the '--lowvram' command line argument. +- **Keyframe every 600-800 frames** for smooth transitions. Tighter feels rushed; looser feels aimless. +- **Write prompts as active camera moves** -- "Flying into", "Penetrating a", "Soaring through" -- reinforces motion vectors. +- **Keep negative prompts consistent** across all keyframes. Changing them mid-render causes tonal lurches. -7. After the generation process is completed, click the button with the self-describing name to show the video or gif result right in the GUI! +### LoRA Stacking -8. Join our Discord where you can post generated stuff, ask questions and more: https://discord.gg/deforum.
-* There's also the 'Issues' tab in the repo, for well... reporting issues ;) +These LoRAs are reliable for psychedelic/visionary/abstract animation work: -9. Profit! +| LoRA | Role | Weight | +|---|---|---| +| `Unfazed_Psychedelic-000009` | Core psychedelic style | 0.70-0.85 | +| `3D_Fractals_wDoF` | Depth-of-field fractal | 0.40-0.50 | +| `ral-mndlbrt-sdxl` | Mandelbrot/sacred geometry | 0.45-0.65 | +| `ral-colorswirl-sdxl` | Vivid color motion | 0.40-0.50 | +| `ral-hlgrphc-sdxl` | Holographic overlay | 0.35-0.45 | +| `ral-polygon-sdxl` | Hard geometric structure | 0.45-0.55 | +| `ral-3dcubes-sdxl` | Isometric cube lattices | 0.40-0.50 | +| `ral-iricnt-sdxl` | Iridescent shimmer | 0.40-0.50 | +| `add-detail-xl` | Global detail enhancement | 0.40-0.60 | +| `HR_Giger_SDXL` | Biomechanical texture | 0.40-0.55 | +| `fractalex` | Fractal field extension | 0.40-0.50 | -## Known issues +**Keep total LoRA weight under ~2.0.** 3-4 LoRAs at 0.35-0.55 each is more stable than 2 at high weights. -* This port is not fully backward-compatible with the notebook and the local version both due to the changes in how AUTOMATIC1111's webui handles Stable Diffusion models and the changes in this script to get it to work in the new environment. *Expect* that you may not get exactly the same result or that the thing may break down because of the older settings. +### Checkpoint Models (SDXL) -## Screenshots +| Model | Best for | +|---|---| +| `juggernautXL_v8Rundiffusion` | Photorealistic base, holds detail across long runs | +| `dynavisionXLAllInOneStylized` | Stylized renders, great LoRA compatibility | +| `dreamshaperXL_lightningDPMSDE` | Fast, good for motion-heavy sequences | +| `nightvisionxl_V900` | Dark atmospheric, Giger-adjacent | +| `RealVisXL_V5.0` | High-realism, clean geometry | +| `epicrealismXL_pureFix` | Grounded surrealism, strong structure | +| `CyberRealisticXL_V9.0` | Sci-fi and tech aesthetics | +| `MOHAWK_v20` | Stylized character/organic work | -Amazing raw Deforum animation by [Pxl.Pshr](https://www.instagram.com/pxl.pshr): -* Turn Audio ON! +For abstract/psychedelic: `dynavisionXL` + heavy LoRA stack. For structure-forward renders: `RealVisXL` or `epicrealismXL`. -(Audio credits: SKRILLEX, FRED AGAIN & FLOWDAN - RUMBLE (PHACE'S DNB FLIP)) +### Settings File Workflow Tips -https://user-images.githubusercontent.com/121192995/224450647-39529b28-be04-4871-bb7a-faf7afda2ef2.mp4 +- **Name your settings files immediately** after a good render. The auto-save timestamps are impossible to remember. +- **Use Save As** to write named presets. Load them back with "Load All Settings." +- The included `smooth_master_settings.txt` is a working baseline from a successful 8000-frame run. -Setting file of that video: [here](https://github.com/deforum-art/sd-webui-deforum/files/11353167/PxlPshrWinningAnimationSettings.txt). +### 3D Mode Tips -
+- **Large delay on first frame is normal** -- depth models load at render start. +- **MiDaS weight 0.3-0.5** is a good range. Too high = depth warping dominates; too low = 3D parallax disappears. +- Depth artifacts mid-run usually mean the depth model ran out of VRAM. Lower resolution or add `--lowvram`. -Main extension tab: +--- -![image](https://user-images.githubusercontent.com/121192995/226101131-43bf594a-3152-45dd-a5d1-2538d0bc221d.png) +## Files Changed vs Upstream -Keyframes tab: +| File | What changed | +|---|---| +| `scripts/deforum_helpers/ui_right.py` | Settings editor, save-as, drag-drop upload, larger gallery | +| `scripts/deforum_helpers/ui_left.py` | Two-column keyframes layout | +| `scripts/deforum_helpers/ui_elements.py` | Improved tooltips, MiDaS weight visibility | +| `scripts/deforum_helpers/args.py` | Settings editor component registration | +| `scripts/deforum_helpers/settings.py` | Save-as support, upload path auto-update | +| `scripts/deforum_helpers/gradio_funcs.py` | JSON editor sync functions (new file) | +| `scripts/deforum_helpers/render.py` | Init image auto-enable | +| `scripts/default_settings.txt` | Updated defaults from working render baseline | +| `style.css` | Gallery height override | +| `tools/Deforum_Compare_Portable/` | Standalone render comparison tool (new) | -![image](https://user-images.githubusercontent.com/121192995/226101140-bfe6cce7-9b78-4a1d-be9a-43e1fc78239e.png) +--- ## License This program is distributed under the terms of the GNU Affero Public License v3.0, copyright (c) 2023 Deforum LLC. -Some of its sublicensed integrated 3rd party components may have other licenses, see LICENSE for usage terms. +Fork modifications by [m1llipede](https://github.com/m1llipede). diff --git a/examples/Microcosm_Best_settings.txt b/examples/Microcosm_Best_settings.txt new file mode 100644 index 00000000..b239e1e3 --- /dev/null +++ b/examples/Microcosm_Best_settings.txt @@ -0,0 +1,306 @@ +{ + "W": 1024, + "H": 1024, + "show_info_on_ui": false, + "tiling": false, + "restore_faces": false, + "seed_resize_from_w": 0, + "seed_resize_from_h": 0, + "seed": 31415, + "sampler": "DPM++ 2M SDE", + "scheduler": "Karras", + "steps": 40, + "batch_name": "Microcosm_Best", + "seed_behavior": "iter", + "seed_iter_N": 12345, + "use_init": false, + "strength": 0.83, + "strength_0_no_init": false, + "init_image": "", + "use_mask": false, + "use_alpha_as_mask": false, + "mask_file": "https://deforum.github.io/a1/M1.jpg", + "invert_mask": false, + "mask_contrast_adjust": 1.0, + "mask_brightness_adjust": 1.0, + "overlay_mask": true, + "mask_overlay_blur": 4, + "fill": 1, + "full_res_mask": true, + "full_res_mask_padding": 4, + "reroll_blank_frames": "ignore", + "reroll_patience": 10.0, + "motion_preview_mode": false, + "prompts": { + "0": " Extreme close-up electron micrograph aesthetic, bacteriophage T4 virus particle suspended in vitreous ice. The icosahedral capsid head shows perfect hexagonal protein subunit lattice with crystalline shading, individual capsomeres visible as raised tessellated bumps. The contractile tail sheath descends in striated rings of darker pigment, terminating in a baseplate with six splayed tail fibers articulated like spider legs, each fiber kinked at characteristic joints. Subtle false-color tinting: bruised plum on the capsid, cool slate on the sheath, pale parchment background. Surface micro-detail at every pixel, cryo-EM negative-stain aesthetic, depth of field razor-thin. Photorealistic scientific micrography, hyper-detailed, no artistic interpretation. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "300": " The same bacteriophage now drifting closer to a curved Escherichia coli bacterial membrane surface. The bacterial wall pebbled with lipopolysaccharide texture: thousands of branching sugar chains catching scattered backlight in golden-amber pinpricks. Outer membrane porins visible as faint annular depressions. The phage tail fibers reach toward the surface, one fiber making first molecular contact with an LPS terminal sugar, the contact point ringed with a faint refractive halo of cytoplasmic water displacement. Wet glistening membrane surface, low-key transmission electron microscopy palette of olive, ochre, deep umber. Photorealistic, scientifically literate, hyper-detailed surface texture. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "600": " Bacteriophage anchored to the E. coli surface, tail sheath in mid-contraction. The sheath rings have compressed into thicker pleated stacks while the inner tail tube punches downward through the outer membrane in a microscopic injection. Cytoplasmic leakage forms a tiny droplet at the entry point catching specular highlight. Cross-sectioned membrane reveals lipid bilayer headgroups in characteristic dark-light-dark banding. The empty capsid head has lost some density, walls slightly translucent from genome ejection. False-color TEM aesthetic, mauve and slate palette, motion frozen mid-event. Hyperrealistic scientific imagery, intricate ultrastructural detail. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "900": " Interior view inside the bacterial cytoplasm shortly after viral genome injection. Densely packed ribosomes coat every available surface as small dark granular dots, free DNA strands curl through the open space as fine filamentous threads, the freshly injected viral genome unwinding as a noticeably thicker, brighter strand among them. Polyribosome chains beading along messenger RNA. A few enzymes visible as larger globular shapes. Crowded molecular environment, slate-blue false-color cytoplasm. Photorealistic cryo-ET tomographic aesthetic, every nanometer earned. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "1200": " Procapsid assembly in progress. Half-formed bacteriophage head shells under construction, scaffolding proteins still visible inside the developing capsid lattices, the hexagonal protein subunits being added one by one at growing edges in characteristic prolate geometry. Multiple procapsids at varied stages clustered together. Surrounding cytoplasm filled with free coat protein monomers as smaller particles. Bone-grey false-color shading, dramatic depth of field with one capsid in sharp focus and others trailing into bokeh. Photorealistic structural biology micrograph, scientifically meticulous. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "1500": " Fully formed virions accumulating in the bacterial cytoplasm. Hundreds of completed bacteriophage particles packed in chaotic crystalline arrays, tail fibers tangled together, residual host cytoplasmic structures crowded out to the periphery. The bacterial inner membrane just visible at the bottom edge of frame, beginning to bulge inward from osmotic stress. False-color TEM in cool teal and warm sepia. Dense crowded composition, depth of field shallow, hyper-detailed particle counts. Photorealistic, no stylization. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "1800": " The bacterial cell wall begins to rupture in lysis. A cleft has opened in the outer membrane and inner membrane, peptidoglycan layer visibly torn, cell contents under pressure beginning to evacuate. The first liberated bacteriophages tumble outward through the breach trailed by released cytoplasmic proteins and ribosomes drifting in escaping liquid. Suggestion of explosive osmotic release frozen at the instant of breach. Dramatic chiaroscuro lighting from refracted scattered electrons, palette of bone-white phage against deep-violet cytoplasm and dusty rose membrane fragments. Photorealistic, hyper-detailed, scientifically accurate. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "2100": " Free virions dispersing into the extracellular fluid after lysis. Dozens of bacteriophage particles drifting away from the burst bacterial remnant, suspended in their own Brownian motion against a softer out-of-focus tissue-fluid background. Each phage is rendered with full anatomical clarity: capsid head, sheath, baseplate, fibers — but at varied depths of field, some sharp, some soft. Suggestion of vast distance to navigate before finding the next host. Cool blue-grey palette, hint of dust-particle ambient backscatter. Photorealistic micrography, contemplative composition. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "2400": " Coronavirus virion at extreme resolution. A spherical lipid envelope of approximately 100 nanometers, surface studded with the characteristic corona of club-shaped spike glycoproteins, each spike a trimer of S protein with visible receptor-binding domain at the distal head and stalk geometry beneath. Between spikes the M protein and small E protein punctate the membrane as smaller bumps. Faint suggestion of the helical nucleocapsid coil inside the translucent envelope. False-color rendering: bruised burgundy spikes, pale parchment membrane, deep umber background. Cryo-electron microscopy aesthetic with negative-stain ring of phosphotungstate around the particle. Photorealistic, scientifically rigorous, every detail earned. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "2700": " Field of mixed bacterial morphologies under high-magnification Gram stain brightfield microscopy. Rod-shaped Bacillus chains in characteristic streptobacillus arrangements stained deep violet, coccal Staphylococcus aureus clusters in grape-like aggregates, spiral Spirillum twisting between them, all swimming in extracellular polymeric matrix. Pleomorphic forms suggesting active division mid-binary-fission. Crystalline iodine staining shadows in the larger Gram-positive cells, faint pink Gram-negative counterstain in others. Phase contrast halo effects around each cell edge. Photorealistic clinical microbiology slide, oil-immersion 1000x feel, hyper-detailed. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "3000": " Dense bacterial biofilm at scanning electron microscopy magnification. Multiple species embedded within a glistening extracellular polymeric substance matrix that stretches between cells in viscous threads and sheets, drying into intricate fractal crackle patterns at the margins. Some bacteria stand erect on the substrate, others lie flat with surface pili anchoring them to the matrix. Water channels carve through the biofilm in rivers and lagoons creating three-dimensional architecture. SEM characteristic monochromatic grayscale with subtle warm false-color tinting. Photorealistic, hyper-detailed surface micrography. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "3300": " Single E. coli bacterium swimming in fluid with flagellar bundle visible at the rear, six to eight helical flagella rotating in counterclockwise bundle for forward run motion, each flagellum a long whip-like proteinaceous filament. Bacterial pole shows hook structure attaching flagella to the motor. Body of the bacterium nearly translucent under dark-field illumination, revealing nucleoid as a denser central region. Surrounding fluid carries drifting molecular debris suggesting chemotactic gradient. Cool teal monochrome with bright specular highlights on flagellar bundle. Photorealistic, motion implied through bundle position, hyperrealistic. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "3600": " Bacterial conjugation event captured mid-transfer. Two E. coli cells connected by a long thin protein pilus bridging the gap between them, single-stranded DNA visible as a fine thread passing through the conjugation tube from donor to recipient. The pilus structure shows characteristic helical assembly of pilin protein subunits, the membrane junction at each end reinforced by a complex protein collar. Surrounding extracellular matrix sparsely populated with smaller debris. False-color TEM aesthetic in muted ochre and slate, with the DNA thread highlighted in faint cyan. Photorealistic, scientifically meticulous, intimate bacterial moment. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "3900": " Endospore formation in a sporulating Bacillus subtilis cell. The mother cell wall remains visible as the outer boundary, but inside, the forespore has begun condensing into a compact ovoid form at one pole, surrounded by characteristic spore coat layers in concentric translucent shells. Calcium dipicolinate crystals already begun deposition in the spore core as glittering inclusions. The mother cell cytoplasm thinning as resources transfer into the spore. Cross-sectional TEM aesthetic, false-color in pale parchment and ochre with the spore core slightly luminous. Photorealistic, hyper-detailed structural biology imagery. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "4200": " Encapsulated bacterial cell viewed at extreme magnification. Streptococcus pneumoniae surrounded by a thick polysaccharide capsule visible as a soft semi-translucent halo extending well beyond the cell wall, the capsule edge feathering into the surrounding fluid in delicate filamentous fronds. Capsule catches and scatters illumination in opalescent shimmer. The cell beneath shows characteristic diplococcus pairing geometry. India ink negative staining technique evident in the surrounding dark background revealing the clear capsule territory. Photorealistic, hyper-detailed clinical pathology aesthetic. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "4500": " Mat of filamentous Oscillatoria cyanobacteria in mid-rotation gliding motion. Long unbranched chains of cylindrical cells laid edge to edge in slightly curving rows, each cell containing photosynthetic membranes visible as fine parallel internal stacks. The mat surface gleams with biofilm extracellular matrix, oxygen bubbles trapped between filaments rising slowly. Subtle blue-green pigmentation from phycocyanin and chlorophyll a colors. Dark mineral grains of calcium carbonate inclusion catching specular highlight. Hyperrealistic photomicrography, wet glistening surface, scientifically accurate. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "4800": " Magnetotactic bacterium with intracellular magnetosome chain. The cell, an elongated coccoid, contains a perfectly aligned linear array of cuboctahedral magnetite crystals each about fifty nanometers, each crystal enveloped in a thin lipid membrane vesicle. The chain runs along the cell axis like a microscopic compass needle. Around the cell, fine grain mineral substrate texture and traces of dissolved ferric ions in the surrounding fluid as faint refractive haze. False-color TEM in cool slate and warm umber palette. Photorealistic, scientifically rigorous, ultrastructural imagery. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "5100": " Bacterial colony viewed from above at low magnification. A circular Bacillus colony showing characteristic concentric ring growth pattern, surface texture wrinkled and matte at the older central zone, becoming smoother and glossier at the outer expansion front. Edge of the colony fingering into the agar surface in delicate branching swarm patterns. Agar surface around the colony shows hint of secondary metabolite diffusion zone. Macrophotography microbiology aesthetic, side-lit to emphasize three-dimensional surface texture, palette of clinical cream and tan. Photorealistic, hyper-detailed colony micrography. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "5400": " Living Paramecium caudatum gliding through a pond water field at phase-contrast magnification. The slipper-shaped body completely covered in beating cilia frozen mid-stroke in characteristic metachronal wave pattern, the oral groove on the ventral side visibly funneling water and food particles inward. Two contractile vacuoles at opposite ends positioned for osmotic regulation, the larger one visibly distended with collected water. Macronucleus and smaller micronucleus faintly visible within the cytoplasm. Phase-contrast halo aura around the cell silhouette. Slate olive and bone palette, drifting algae cells out of focus in background. Hyperrealistic optical microscopy, intricate detail. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "5700": " Amoeba proteus extending pseudopodia in active movement. Multiple finger-like cytoplasmic projections branch outward from the main cell body, each one a current of streaming endoplasm flowing forward inside a thin ectoplasmic sheath. The nucleus visible as a contrasting dense oval in the body's interior, surrounded by food vacuoles containing partially digested smaller organisms in various stages of breakdown. Surface granular with internal organelles. Brightfield microscopy aesthetic with subtle differential interference contrast shadowing. Pale tan body against soft cool grey background, scientifically meticulous, hyperrealistic. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "6000": " Euglena gracilis swimming with characteristic spiral motion. The spindle-shaped cell body shows internal chloroplasts arranged radially in green stars, the prominent red eyespot near the anterior end clearly visible, the long whip-like flagellum trailing forward and undulating in graceful sinusoidal waves. Pellicle texture striated with longitudinal grooves catching subtle iridescent reflection. Suggestion of the fluid being displaced behind the cell as it advances. Darkfield microscopy palette with the cell glowing against deep black background, internal chlorophyll fluorescence enhanced. Photorealistic, hyperrealistic micrography. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "6300": " Cluster of foraminifera tests, calcium carbonate shells of single-celled protists at scanning electron microscopy magnification. Each test a perfectly chambered spiraled construction, chambers added in logarithmic growth, surface pores allowing pseudopodia to extend. Various species showing distinct geometries: planispiral, trochospiral, milioline. Surface texture of fine carbonate crystals catching scattered electron beam in glassy gold-bone palette. Dramatic side-lighting reveals chamber wall thickness and pore architecture. Photorealistic SEM scientific micrograph, hyper-detailed crystalline structure. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "6600": " Radiolarian skeleton, an Ernst Haeckel masterpiece in actual three-dimensional silicate. Intricately latticed spherical cage of opaline silica, geometric perfection in pentagonal and hexagonal apertures, radial spines projecting outward in symmetrical arrays. Internal nested concentric shells faintly visible through the outer cage. Suggestion of cytoplasm and central capsule still embedded inside. Darkfield illumination casting the structure into glowing translucent jewel against deep void. Pale honey gold over inky black, fractal mathematical perfection. Photorealistic, hyperrealistic biological mineralogy. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "6900": " Armored dinoflagellate Ceratium with characteristic horn-shaped projections. The thecal plates fitted together like an alien helmet, surface engraved with fine reticulate patterns, three long horns extending in different directions giving the cell its strange asymmetric profile. Two flagella visible: the transverse cingular flagellum wrapped around the equator, the longitudinal sulcal flagellum trailing posterior. Chloroplasts dappled inside through translucent thecal armor. Photorealistic darkfield with subtle bioluminescent glow tint, ocean blue-green palette. Hyperrealistic microbiology. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "7200": " Pennate diatom in darkfield, frustule of two frustule halves overlapping like a pillbox. The silica frustule walls etched with thousands of nano-scale punctae arranged in precise rows and chevrons, the central raphe running longitudinally as a sealed slit. Through the translucent walls, golden-brown chloroplasts visible inside the protoplast. Edge highlights of the frustule scattered into prismatic refraction. Pure jewel-like clarity, cool cyan and ivory palette against absolute black background. Photorealistic, hyper-detailed silica micro-architecture. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "7500": " Colony of choanoflagellates with collared cells in characteristic arrangement. Each cell flask-shaped, bearing a single anterior flagellum surrounded by a collar of fine microvilli that filter bacteria from the surrounding water. The flagellum beats in slow corkscrew motion drawing water current through the collar. Multiple cells share a common gelatinous matrix connecting them into a small colony. Suggestion of captured bacteria trapped against the collar. Phase-contrast aesthetic with halo, soft pearl-grey and translucent silver palette. Photorealistic, hyperrealistic protistology. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "7800": " Acanthamoeba in trophozoite stage with characteristic spike-like pseudopodia called acanthopodia. The cell surface bristles with fine sharp projections in radial array, the body itself flattened against the substrate, internal nucleus prominent with dense nucleolus visible. Surrounding fluid carries fine grain debris and bacterial prey. Differential interference contrast microscopy aesthetic giving relief and depth to surface architecture. Slate blue and silver palette, hyperrealistic optical micrography, scientifically rigorous. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "8100": " Living tardigrade water bear at extreme phase-contrast microscopy magnification. Eight stubby clawed legs gripping a strand of wet sphagnum moss, each leg ending in four to eight curved claws articulated like grappling hooks. Translucent cuticle reveals internal organs in faint chiaroscuro: ventral nerve cord, muscular pharynx with crystalline stylets retracted, glistening gut tube. Two black eyespots in dorsal head. Slow deliberate posture. Honey-amber and pale teal palette, surrounding water droplet creating prismatic halo. Hyperrealistic optical microscopy, every cuticular bristle rendered. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "8400": " Tardigrade in tun state, dehydrated cryptobiosis form. The animal has retracted its legs and head into a compact barrel shape, cuticle dramatically wrinkled and accordioned, body water content reduced to near zero. Surface texture leathery, glassy reflections from preserved trehalose sugars protecting internal structures. Surrounding substrate dry and crackled. Backlit slightly to reveal the still-organized internal architecture frozen in suspended life. Dusty amber and parchment palette. Photorealistic micro-photography, scientifically literate. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "8700": " Rotifer Brachionus crown of beating cilia in vortex feeding motion. The transparent body shows internal mastax with prominent grinding trophi jaws, a long gut and corona of cilia creating visible water currents drawing in particles. Foot at the posterior with toes for substrate attachment. Carapace lorica armor faintly visible as outer shell. Surrounded by algal cells caught in the feeding vortex. Phase contrast aesthetic with strong halo effect, pale ivory and translucent green palette. Photorealistic, hyper-detailed micro-zoology. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "9000": " Copepod Cyclops mid-swim under darkfield illumination. Streamlined body with prominent single nauplius eye in characteristic crimson coloration, long branched antennae splayed forward for prey detection, abdomen tapering to forked caudal rami. Egg sacs visible at the rear in pearl-translucent clusters carrying developing nauplii. Body bristles set with sensory hairs. Glowing against deep black darkfield background, body translucent enough to reveal internal gut and musculature. Hyperrealistic photomicrography, scientifically accurate. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "9300": " Water mite Hydracarina close-up. Spherical orange-red body covered in fine setae, eight legs splayed in walking posture, each leg jointed and bristled. Mouthparts in the form of a chelate gnathosoma at the front. Surface texture pebbled like miniature alligator hide. Through translucent integument, hint of internal gut diverticula visible. Brightfield microscopy with crisp focus, warm orange and brown palette against pale aqua aquatic background. Photorealistic, hyperrealistic acarology micrography. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "9600": " Planarian flatworm Dugesia in dorsal view. The triangular head bears two simple eyespots like dark teardrops and lateral auricles for chemosensing. The body laterally flattened, dorsal surface mottled with dark and light pigment patches in characteristic species pattern. Pharynx visible as a denser tube along the ventral midline ready to evert for feeding. Surface ciliated for gliding motion. Moist glistening sheen. Photographic clinical micrography, pale tan and chocolate palette against off-white substrate. Photorealistic, hyper-detailed. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "9900": " Free-living nematode Caenorhabditis elegans in dorsoventral view. The slender cylindrical body about one millimeter long, cuticle smooth and translucent, internal anatomy visible through the body wall: pharynx with grinder, gonad arms, intestine, eggs in late development within hermaphrodite. Body in a characteristic sinusoidal posture mid-undulation. Differential interference contrast microscopy aesthetic giving organelle-level detail. Pale champagne and cream palette, scientifically meticulous, hyperrealistic developmental biology imagery. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "10200": " Mosquito larva Culex hanging upside down at the water surface. Siphon tube broken through surface tension for atmospheric breathing, body suspended beneath in characteristic angled posture. Segmented abdomen, thorax with bristles, head with mouth brushes filtering particles from the water column. Internal gut filled with detritus visible through translucent integument. Surface tension film visible as faint refractive ring around the siphon. Brightfield aquatic micrography palette of olive and chestnut against pale aqua. Photorealistic, hyperrealistic micro-zoology. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "10500": " Daphnia magna water flea in lateral view. Translucent carapace shell shows everything inside in extraordinary clarity: single black compound eye, beating heart visible as a faint rhythmic pulsation in the upper body, brood pouch carrying developing parthenogenetic embryos at various stages, intricate branched antennae extending forward used for swimming, hopping locomotion. Gut filled with algal detritus. Phase contrast halo aesthetic with subtle false-color in cool green and warm amber. Photorealistic, hyperrealistic micrography. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "10800": " Mitochondrion in cross-section at electron microscopy resolution. The double membrane envelope clearly resolved as two parallel dark lines separated by intermembrane space, the inner membrane deeply infolded into characteristic accordion cristae jutting into the matrix interior. Cristae studded with tiny stalked F1-F0 ATP synthase complexes visible as raised bumps along the inner membrane surface. Matrix dense with proteins and circular mitochondrial DNA visible as a faint coiled thread. False-color TEM in muted slate and warm sepia. Hyperrealistic ultrastructural biology, scientifically meticulous. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "11100": " Golgi apparatus in cross-section. Stacked flattened cisternae form the characteristic cis-medial-trans architecture, each cisterna a slim disk of membrane, peripheral edges curling and budding off transport vesicles in active vesicular trafficking. Free vesicles surround the stack in profusion, some en route to plasma membrane delivery. Nuclear envelope visible at the corner of the frame for context. Cytoplasm dense with ribosomes and cytoskeletal filaments. False-color TEM aesthetic in dusty rose, ochre, and slate. Photorealistic, hyper-detailed cellular ultrastructure. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "11400": " Cell nucleus interior at chromatin level. Dense heterochromatin clumps near the nuclear envelope inner surface, looser euchromatin spread through the central nucleoplasm, prominent nucleolus visible as a darker spherical region of active rRNA synthesis. Nuclear pores in the envelope appear as ring-shaped openings. Suggestion of individual chromatin fibers as nucleosome bead-on-string strands. False-color TEM rendering in warm rose and bone tones. Hyperrealistic ultrastructural imagery, scientifically rigorous. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "11700": " Cytoskeleton at high magnification cryo-electron tomography aesthetic. Actin filaments visible as fine twin-strand helices forming branched networks, microtubules as wider hollow cylinders running across the field, intermediate filaments as ropes of woven protein strands. Crosslinking proteins visible at junctions. Plasma membrane lipid bilayer at one edge of the field. Cool grey-blue monochromatic palette with subtle warmth. Photorealistic cryo-ET aesthetic, hyperrealistic structural cell biology. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "12000": " Membrane vesicle fusion event captured at the moment of bilayer merger. A small transport vesicle has docked against the larger target membrane, SNARE protein complexes from both membranes intertwined in tight four-helix bundle pulling the bilayers together, the lipid bilayers in mid-fusion as a transient stalk-and-hemifusion intermediate. Surrounding cytoplasm dense with proteins. False-color TEM in cool slate and warm parchment, scientifically meticulous. Hyperrealistic membrane biology, hyper-detailed nanoscale moment. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "12300": " Red blood cells flowing through a capillary lumen at high magnification. Biconcave disc erythrocytes deformed by the narrow passage, single file, jostling against each other and against the endothelial cell wall. The endothelium is a thin glistening layer with prominent cell nuclei bulging into the lumen. Following the erythrocytes, a single leukocyte rolls along the wall surface ruffled with microvilli, preparing for diapedesis. Plasma in between visible as a faintly opalescent fluid carrying drifting platelets. Crimson and salmon palette under transmitted light, hyperrealistic photomicrography. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "12600": " Synaptic junction between two neurons at electron microscopy resolution. Presynaptic terminal swollen with synaptic vesicles clustered against the active zone, several vesicles docked and primed for release. Synaptic cleft as a narrow space about twenty nanometers wide. Postsynaptic density appearing as a thicker electron-dense band on the receiving neuron membrane. Mitochondria in the presynaptic terminal providing energy. False-color TEM aesthetic in cool slate and warm sepia. Hyper-detailed neurobiology, scientifically meticulous. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "12900": " Macrophage in active phagocytosis engulfing a bacterium. The white blood cell has extended pseudopodia around the prey, the cell membrane folding in characteristic phagocytic cup geometry, the bacterium already partially engulfed with the membrane closing over it. Surface of macrophage ruffled with active cytoskeletal protrusions. Internal lysosomes prepared near the forming phagosome ready for fusion. Surrounding plasma with antibody molecules in solution. False-color TEM aesthetic: warm pink macrophage, pale tan bacterium, neutral plasma. Hyperrealistic immunology micrography. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "13200": " Alveolus in lung tissue at scanning electron microscopy. The thin-walled air sac coated with surfactant film, capillaries pressed against the outside surface visible as bumpy vessels carrying erythrocytes within. Type I pneumocytes form the gas exchange surface as flat thin cells, type II pneumocytes appearing as cuboidal cells with surfactant droplet content. Alveolar macrophage patrolling the interior surface. Wet glistening texture. SEM monochromatic grayscale with subtle warm false-color, photorealistic, hyper-detailed. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "13500": " Cross-section of intestinal villus brush border at electron microscopy. The epithelial cell apical surface bristling with thousands of densely packed microvilli forming a uniform brush border, each microvillus a fingerlike membrane protrusion supported by an actin filament core. Above the brush border, the glycocalyx coating as fine fuzzy mat. Below, junctional complexes seal cells together. Mitochondria abundant in the apical cytoplasm. False-color TEM in muted pink and slate, scientifically meticulous, hyperrealistic ultrastructure. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "13800": " Pulling back to medium magnification: a single droplet of pond water on a microscope slide revealed teeming with microscopic life. Inside the curved spherical boundary of the droplet, simultaneously visible: a tardigrade, two paramecia, a rotifer, several diatoms, drifting bacterial chains, a single phage-like particle, foraminiferan tests, mineral grains. All sharing the same suspended liquid universe in dense diorama composition. Droplet surface refracts light into prismatic halos. Cool blue-green palette, photorealistic micrography, contemplative awe. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "14100": " Soil clump at high magnification revealing a hidden teeming ecosystem. Mineral grains, organic detritus, fungal hyphae weaving through, nematodes browsing, mites stalking among the particles, bacterial biofilms coating every surface, springtails and tardigrades in moist crevices. The matrix of life packed into a few cubic millimeters of soil. Warm earth-tone palette of umber, ochre, and chestnut. Photorealistic environmental micrography, hyper-detailed diorama. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "14400": " Air at high magnification: atmospheric microbiome and particulates. Bacteria attached to dust grains drift through frame, pollen grains tumble in slow rotation, fungal spores released from invisible substrate, single virus particles riding on droplet nuclei. Sunlight beams through the air at oblique angles revealing the suspended drifting world normally invisible. Pale gold and silver against translucent blue background. Photorealistic, hyperrealistic aerobiology imagery. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "14700": " Final transcendent micro-macro reveal. The pond drop, the soil clump, the air sample all converge into a single composite vision: the visible universe at every nanometer scale full of life, structure, and pattern. Bacteriophages, bacteria, protists, micrometazoans, subcellular architecture, all overlaid in a multi-scale composition rendered with photographic clarity at each register. Light is patient and uninterested in being looked at. Quiet awe. Photorealistic transcendent finale, painterly micrography bloom, scientifically rigorous beauty. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude" + }, + "positive_prompts": "", + "negative_prompts": "nsfw, nude", + "animation_mode": "3D", + "max_frames": 15000, + "border": "wrap", + "angle": "0: (0)", + "zoom": "0: (1.0006+0.0004*sin(0.5*3.14*t/30))", + "translation_x": "0: (0.35*sin(0.5*3.14*t/200))", + "translation_y": "0: (0.5*sin(0.5*3.14*t/240))", + "translation_z": "0: (2.5)", + "transform_center_x": "0: (0.5)", + "transform_center_y": "0: (0.5)", + "rotation_3d_x": "0: (0.06*sin(0.5*3.14*t/180))", + "rotation_3d_y": "0: (0.05*sin(0.5*3.14*t/220))", + "rotation_3d_z": "0: (0.03*sin(0.5*3.14*t/260))", + "enable_perspective_flip": false, + "perspective_flip_theta": "0: (0)", + "perspective_flip_phi": "0: (0)", + "perspective_flip_gamma": "0: (0)", + "perspective_flip_fv": "0: (53)", + "noise_schedule": "0: (0.01)", + "strength_schedule": "0: (0.6)", + "contrast_schedule": "0: (1.0)", + "cfg_scale_schedule": "0: (6)", + "enable_steps_scheduling": false, + "steps_schedule": "0: (25)", + "fov_schedule": "0: (80)", + "aspect_ratio_schedule": "0: (1)", + "aspect_ratio_use_old_formula": false, + "near_schedule": "0: (50)", + "far_schedule": "0: (20000)", + "seed_schedule": "0:(s), 1:(-1), \"max_f-2\":(-1), \"max_f-1\":(s)", + "pix2pix_img_cfg_scale_schedule": "0:(1.5)", + "enable_subseed_scheduling": false, + "subseed_schedule": "0: (1)", + "subseed_strength_schedule": "0: (0)", + "enable_sampler_scheduling": false, + "sampler_schedule": "0: (\"Euler a\")", + "use_noise_mask": false, + "mask_schedule": "0: (\"{video_mask}\")", + "noise_mask_schedule": "0: (\"{video_mask}\")", + "enable_checkpoint_scheduling": false, + "checkpoint_schedule": "0: (\"model1.ckpt\"), 100: (\"model2.safetensors\")", + "enable_clipskip_scheduling": false, + "clipskip_schedule": "0: (2)", + "enable_noise_multiplier_scheduling": false, + "noise_multiplier_schedule": "0: (1.0)", + "resume_from_timestring": false, + "resume_timestring": "", + "enable_ddim_eta_scheduling": false, + "ddim_eta_schedule": "0: (0)", + "enable_ancestral_eta_scheduling": false, + "ancestral_eta_schedule": "0: (1)", + "amount_schedule": "0: (1.0)", + "kernel_schedule": "0: (5)", + "sigma_schedule": "0: (1)", + "threshold_schedule": "0: (0)", + "color_coherence": "LAB", + "color_coherence_image_path": "", + "color_coherence_video_every_N_frames": 1, + "color_force_grayscale": false, + "legacy_colormatch": false, + "diffusion_cadence": 5, + "optical_flow_cadence": "DIS Fine", + "cadence_flow_factor_schedule": "0: (1)", + "optical_flow_redo_generation": "DIS Fine", + "redo_flow_factor_schedule": "0: (1)", + "diffusion_redo": "0", + "noise_type": "perlin", + "perlin_octaves": 4, + "perlin_persistence": 0.5, + "use_depth_warping": false, + "depth_algorithm": "Midas-3-Hybrid", + "midas_weight": 0.5, + "padding_mode": "border", + "sampling_mode": "bicubic", + "save_depth_maps": false, + "video_init_path": "https://deforum.github.io/a1/V1.mp4", + "extract_nth_frame": 1, + "extract_from_frame": 0, + "extract_to_frame": -1, + "overwrite_extracted_frames": false, + "use_mask_video": false, + "video_mask_path": "https://deforum.github.io/a1/VM1.mp4", + "hybrid_comp_alpha_schedule": "0:(0.5)", + "hybrid_comp_mask_blend_alpha_schedule": "0:(0.5)", + "hybrid_comp_mask_contrast_schedule": "0:(1)", + "hybrid_comp_mask_auto_contrast_cutoff_high_schedule": "0:(100)", + "hybrid_comp_mask_auto_contrast_cutoff_low_schedule": "0:(0)", + "hybrid_flow_factor_schedule": "0:(1)", + "hybrid_generate_inputframes": false, + "hybrid_generate_human_masks": "None", + "hybrid_use_first_frame_as_init_image": true, + "hybrid_motion": "None", + "hybrid_motion_use_prev_img": false, + "hybrid_flow_consistency": false, + "hybrid_consistency_blur": 2, + "hybrid_flow_method": "RAFT", + "hybrid_composite": "None", + "hybrid_use_init_image": false, + "hybrid_comp_mask_type": "None", + "hybrid_comp_mask_inverse": false, + "hybrid_comp_mask_equalize": "None", + "hybrid_comp_mask_auto_contrast": false, + "hybrid_comp_save_extra_frames": false, + "parseq_manifest": "", + "parseq_use_deltas": true, + "parseq_non_schedule_overrides": true, + "use_looper": false, + "init_images": "{\n \"0\": \"https://deforum.github.io/a1/Gi1.png\"\n}", + "image_strength_schedule": "0:(0.6)", + "blendFactorMax": "0:(0.35)", + "blendFactorSlope": "0:(0.25)", + "tweening_frames_schedule": "0:(20)", + "color_correction_factor": "0:(0.075)", + "cn_1_overwrite_frames": true, + "cn_1_vid_path": "", + "cn_1_mask_vid_path": "", + "cn_1_enabled": true, + "cn_1_low_vram": false, + "cn_1_pixel_perfect": false, + "cn_1_module": "depth_anything_v2", + "cn_1_model": "diffusion_pytorch_model_promax [9460e4db]", + "cn_1_weight": "0:(0.45)", + "cn_1_guidance_start": "0:(0.0)", + "cn_1_guidance_end": "0:(0.8)", + "cn_1_processor_res": 512, + "cn_1_threshold_a": 64, + "cn_1_threshold_b": 64, + "cn_1_resize_mode": "Inner Fit (Scale to Fit)", + "cn_1_control_mode": "Balanced", + "cn_1_loopback_mode": true, + "cn_2_overwrite_frames": true, + "cn_2_vid_path": "", + "cn_2_mask_vid_path": "", + "cn_2_enabled": false, + "cn_2_low_vram": false, + "cn_2_pixel_perfect": false, + "cn_2_module": "none", + "cn_2_model": "None", + "cn_2_weight": "0:(1)", + "cn_2_guidance_start": "0:(0.0)", + "cn_2_guidance_end": "0:(1.0)", + "cn_2_processor_res": 64, + "cn_2_threshold_a": 64, + "cn_2_threshold_b": 64, + "cn_2_resize_mode": "Inner Fit (Scale to Fit)", + "cn_2_control_mode": "Balanced", + "cn_2_loopback_mode": false, + "cn_3_overwrite_frames": true, + "cn_3_vid_path": "", + "cn_3_mask_vid_path": "", + "cn_3_enabled": false, + "cn_3_low_vram": false, + "cn_3_pixel_perfect": false, + "cn_3_module": "none", + "cn_3_model": "None", + "cn_3_weight": "0:(1)", + "cn_3_guidance_start": "0:(0.0)", + "cn_3_guidance_end": "0:(1.0)", + "cn_3_processor_res": 64, + "cn_3_threshold_a": 64, + "cn_3_threshold_b": 64, + "cn_3_resize_mode": "Inner Fit (Scale to Fit)", + "cn_3_control_mode": "Balanced", + "cn_3_loopback_mode": false, + "cn_4_overwrite_frames": true, + "cn_4_vid_path": "", + "cn_4_mask_vid_path": "", + "cn_4_enabled": false, + "cn_4_low_vram": false, + "cn_4_pixel_perfect": false, + "cn_4_module": "none", + "cn_4_model": "None", + "cn_4_weight": "0:(1)", + "cn_4_guidance_start": "0:(0.0)", + "cn_4_guidance_end": "0:(1.0)", + "cn_4_processor_res": 64, + "cn_4_threshold_a": 64, + "cn_4_threshold_b": 64, + "cn_4_resize_mode": "Inner Fit (Scale to Fit)", + "cn_4_control_mode": "Balanced", + "cn_4_loopback_mode": false, + "cn_5_overwrite_frames": true, + "cn_5_vid_path": "", + "cn_5_mask_vid_path": "", + "cn_5_enabled": false, + "cn_5_low_vram": false, + "cn_5_pixel_perfect": false, + "cn_5_module": "none", + "cn_5_model": "None", + "cn_5_weight": "0:(1)", + "cn_5_guidance_start": "0:(0.0)", + "cn_5_guidance_end": "0:(1.0)", + "cn_5_processor_res": 64, + "cn_5_threshold_a": 64, + "cn_5_threshold_b": 64, + "cn_5_resize_mode": "Inner Fit (Scale to Fit)", + "cn_5_control_mode": "Balanced", + "cn_5_loopback_mode": false, + "skip_video_creation": false, + "fps": 30, + "make_gif": false, + "delete_imgs": false, + "delete_input_frames": false, + "add_soundtrack": "None", + "soundtrack_path": "https://deforum.github.io/a1/A1.mp3", + "r_upscale_video": false, + "r_upscale_factor": "x2", + "r_upscale_model": "realesr-animevideov3", + "r_upscale_keep_imgs": true, + "store_frames_in_ram": false, + "frame_interpolation_engine": "None", + "frame_interpolation_x_amount": 2, + "frame_interpolation_slow_mo_enabled": false, + "frame_interpolation_slow_mo_amount": 2, + "frame_interpolation_keep_imgs": true, + "frame_interpolation_use_upscaled": false, + "sd_model_name": "MOHAWK_v20.safetensors", + "deforum_git_commit_id": "a94ba3c7" +} \ No newline at end of file diff --git a/examples/Spore_Mandala_BEST_EVER_settings.txt b/examples/Spore_Mandala_BEST_EVER_settings.txt new file mode 100644 index 00000000..00fcc498 --- /dev/null +++ b/examples/Spore_Mandala_BEST_EVER_settings.txt @@ -0,0 +1,300 @@ +{ + "W": 1024, + "H": 1024, + "show_info_on_ui": true, + "tiling": false, + "restore_faces": false, + "seed_resize_from_w": 0, + "seed_resize_from_h": 0, + "seed": 88421, + "sampler": "DPM++ 2M SDE", + "scheduler": "Karras", + "steps": 35, + "batch_name": "Spore_Mandala_BEST_EVER", + "seed_behavior": "iter", + "seed_iter_N": 12345, + "use_init": true, + "strength": 0.8, + "strength_0_no_init": false, + "init_image": "F:\\stable-diffusion-webui\\outputs\\deforum_init_images\\init_8a8a8336.png", + "use_mask": false, + "use_alpha_as_mask": false, + "mask_file": "https://deforum.github.io/a1/M1.jpg", + "invert_mask": false, + "mask_contrast_adjust": 1.0, + "mask_brightness_adjust": 1.0, + "overlay_mask": false, + "mask_overlay_blur": 4, + "fill": 1, + "full_res_mask": false, + "full_res_mask_padding": 4, + "reroll_blank_frames": "ignore", + "reroll_patience": 10.0, + "motion_preview_mode": false, + "prompts": { + "0": "Data halo mandala of glowing nodes: concentric rings of luminous interconnected nodes, perfect symmetry, a vast neural network of light, molten color dripping down the rings. Blue center through green yellow orange to magenta edges. Warm LED nodes dense intricate optical pattern. Emissive. Pure geometric. Deep glowing dark. ", + "350": "Node network blooming into fine threads: glowing nodes linked by colored lines radiating outward, wet luminous drips trailing. Warm reds oranges yellows above, cool magentas pinks purples below. Threads glow fiber-optic between pulsing nodes. Luminous starburst. Pure geometric, faint hidden eyes beginning to peek from the lattice. ", + "700": "Kirell Benzi radial node-web: thousands of glowing nodes radiating from center, precision wedges in cyan magenta gold violet hot pink, glistening wet color dripping off delicate tendrils. A first DMT face half-forming in the symmetry then gone. Balanced dynamic luminous. Glowing dark depth. ", + "1050": "Color wheel mandala of nodes: luminous dots in concentric rings, spectral hues cycling, molten droplets beading between glowing nodes. Unified gradient LED spheres glistening wet. Threads fading transparent. Hypnotic. Deep glow, pairs of eyes blinking open in the pattern then vanishing. ", + "1400": "Dense node-mandala, radial chart of light: rings of glowing dots and arcs, pure hues grading outward, liquid color dripping along the wedges. Among the nodes, hidden faces emerge from nowhere, owl-eyes and a serene elf visage forming from the lattice then dissolving. Complex balanced. Luminous dark. ", + "1750": "The geometry breathes alive: small luminous mushroom caps appearing at mandala edges, glowing magenta cyan gold, dripping bioluminescent dew. A biological universe manifesting. Fractal butterflies unfolding from the rings, tiny eyes everywhere. Two aesthetics distinct. Emissive. Hybrid beginning. ", + "2100": "Biological universe blooming: mushroom caps prominent, gills like fractal galaxies, glistening liquid light oozing down stalks. Fractal caterpillars crawling glowing branches, fractalized butterflies drifting. Owl and wolf faces materializing from the cave foliage, eyes opening in the dark. Precision distorting into living organic. Dripping spore-light. ", + "2450": "Nested living mandalas: dense glowing grove, fractal creatures everywhere, overlapping caps dripping luminous gel. Hidden faces in the canopy, dozens of eyes watching from the jungle dark, a great DMT elf face presiding. Colors mix in overlaps, magenta plus cyan equals violet. Mandala of living mandalas. ", + "2800": "Deep biological cave with geometric ghost-overlay: dense glowing mushroom forest, fractal butterflies and caterpillars luminous, semi-transparent node-circles overlaying. See faces and eyes through the bright threads, owls and wolves emerging from nowhere. Bioluminescent liquid dripping everywhere. Both visible, wet, alive. ", + "3150": "Living forest so dense it blurs abstract, dripping wet with running light, fractal creatures crawling and fluttering. Eyes everywhere, faces forming and unforming in the foliage. Node-circles cutting through organic chaos, tension. Mandala center warping, molten, a wolf face dissolving into pattern. ", + "3500": "The living cave thinning: mushrooms fading translucent, fractal butterflies drifting away, faces receding. Node-bursts visible, threads glowing, biology dissolving into drips. Transitioning toward emptiness. Soft glow in background, melting away. Space opening up. ", + "3850": "Vast empty space: forms nearly gone, immense breathing emptiness, only a few distant glowing nodes floating, a single faraway face barely visible. Deep luminous dark, sparse and quiet. Negative space dominates. Slow drips falling through the glowing emptiness. Clean psychedelic stillness. ", + "4200": "Sparse luminous expanse: a handful of distant mandalas and node-wheels rotating slowly in vast emptiness, molten color dripping off their edges into the dark. Mostly empty space, breathing room, a pair of eyes opening in the far distance. Mesmerizing, minimal, hypnotic. ", + "4550": "Whispers in the emptiness: tiny fractal creatures and faint nodes appearing at the edges, small distant colored dots, beads of glowing dew. A face flickers and is gone. The empty space beginning to curve and pull inward. Asymmetry developing, wet glow. ", + "4900": "Entering the wormhole: nodes and creatures spiraling inward toward a vanishing point, the empty space folding into a tunnel of light, walls rushing past, eyes lining the wormhole, liquid light streaming down the throat of the vortex. Spectrum cycling. Worlds collapsing into the tunnel. ", + "5250": "Racing through the wormhole: tunnel walls of light streaming inward toward a bright center, fractal faces and eyes flashing past on the wormhole walls, densely packed, accelerating, molten color pouring inward. Blinding white core. Luminous implosion, dripping streams pulled forward. ", + "5600": "Bursting out the far end of the wormhole: forms exploding radially into a new space, fractal butterflies and eyes flung outward trailing wet light, saturated electric magenta cyan gold violet energy expanding. Faces blooming from the burst. Climax, running luminous paint. ", + "5950": "Settling into a new realm: the explosion slowing, fractal creatures drifting into place, a fresh biological cosmos coalescing, faces and eyes scattered through the glow. Both worlds disorganized, overlapping, dripping trails. Beautiful disorienting, wet, alive. ", + "6300": "Deep in the biological universe: glowing mushroom forms dominant, dripping thick bioluminescent liquid, fractal butterflies and caterpillars everywhere. Owl, wolf, and elf faces materializing from living tissue, countless eyes in the jungle dark. Geometric faintly visible over solid wet biology. Bioluminescence primary. ", + "6650": "Biological cosmos haunted: surrounded by glowing caps and fractal creatures, geometric phantoms barely visible, ghostly mandala overlay. Faces drifting in spore mist, eyes opening and closing everywhere, a wolf made of fractal foliage. Living memory like a dream over the wet cave. ", + "7000": "Equilibrium of worlds: geometric nodes and biological creatures floating in balance, fractal butterflies among the rings, hidden faces integrated into the pattern, eyes watching, equal presence. Forms rotating in rhythm, colors mixing, emissive light play, gentle drips falling. ", + "7350": "Dissolution: the living structure dissolving, fractal creatures fading, faces and eyes blurring away, boundaries softening, forms melting into drips. The biological cosmos thinning back toward emptiness, glowing dark predominant. Colors muted, slow runs of light. ", + "7700": "Fading into vast empty space: forms mostly gone, only suggestions remaining, diffuse glow, immense quiet emptiness, a last faint face dissolving. Sparse, breathing, glowing dark. Dissolution, last drips of light falling. Comedown. ", + "8050": "Pure ethereal emptiness: no forms, soft colored light without source, emissive bioluminescence, cool hints of magenta cyan gold violet suspended in vast empty space. Almost nothing, faint drips floating. Peaceful transcendence, a single distant eye. ", + "8400": "The emptiness dimming: glow fading, colors disappearing into glowing dark, light cooler, nearly gone, vast and deep with faint hints of color, one last slow drip. Returning to quiet, a face barely there. Silence. ", + "8750": "Near-empty stillness: light almost gone, a few faint nodes and a single dim eye in the dark, returning to the beginning, the cycle completing in vast empty space. ", + "9100": "Rebirth of the node-network: a faint new mandala of glowing nodes manifesting in the empty dark, tiny interconnected lights appearing, drips coalescing upward into rings. A new cycle, nodes blooming again, light returning. ", + "9450": "Second cycle, node-mandala fully manifest: rings of glowing interconnected nodes, colors cycling cool center hot edges, warm LED optical lattice dense and intricate, molten color dripping. A face surfacing briefly in the symmetry. Pure geometric restart, glowing dark. ", + "9800": "Node-lattice dissolving into threads: glowing nodes linked by bundled strands, warm upper cool lower, spiraling far, fiber-optic starburst, wet light running down each strand. Faint owl-eyes in the weave. Geometric, glowing dark, second cycle progressing. ", + "10150": "Benzi radial node-web, second pass: precise glowing nodes, wedges cyan magenta gold violet hot pink, delicate tendrils dripping glistening color. DMT faces forming and dissolving in the radial symmetry, eyes blinking. Balanced dynamic, pure geometric, clean organized. ", + "10500": "Color wheel of nodes again: luminous dots in concentric rings, spectral cycling gradient, threads fading transparent, mandala of glowing nodes dominant, LED spheres glistening wet. Hidden faces and eyes surfacing from the pattern. Glowing dark, second cycle color phase. ", + "10850": "Dense node-mandala with radial chart, second pass: glowing dots and arcs, pure hue grades, fine threads with wet nodes dripping. Fractal butterflies beginning to unfold from the rings, first eyes opening, a face emerging from nowhere. Second cycle rings layering. ", + "11200": "Geometry breathing alive again: small mushroom caps at the edges glowing magenta cyan gold, dripping bioluminescent dew, fractal caterpillars appearing on glowing branches. The biological universe returning, eyes opening, node-circles precise within. Emissive hybrid, cycle two. ", + "11550": "Living mandala deepening: prominent caps and gills like fractal galaxies, fractal butterflies drifting, owl and wolf faces materializing from the cave foliage, eyes everywhere. Liquid light oozing down stalks, dripping mist. Precision distorting into organic. Second cycle biology. ", + "11900": "Nested living mandalas, second pass: dense glowing grove, fractal creatures and faces throughout, caps forming their own mandalas, molten drips running. A great DMT elf face presiding over countless watching eyes. Colors mixing in overlaps, emissive mist, complexity peak. ", + "12250": "Biological cave with node-overlay, second pass: dense glowing forest, fractal butterflies and caterpillars, semi-transparent node-circles overlaying. Faces and eyes seen through bright threads, owls emerging from nowhere. Bioluminescent liquid dripping, both visible, blended, wet and alive. ", + "12600": "Living forest blurring abstract, fractal creatures crawling and fluttering, eyes and faces forming and unforming. Node-circles prominent, tension of forces, mandala center warping, molten color running, a wolf face dissolving into the pattern. Second cycle organic peak. ", + "12950": "The living cave thinning again: mushrooms fading, fractal butterflies drifting away, faces receding, node-bursts dominant, threads glowing, biology dissolving into drips. Transitioning back toward emptiness, soft background, space opening, luminous trails running. ", + "13300": "Vast empty space, second pass: forms nearly gone, immense breathing emptiness, a few distant node-wheels orbiting, a single faraway face. Deep luminous dark, sparse and quiet, slow drips falling. Clean psychedelic stillness, hybrid becoming pure, dark-glow. ", + "13650": "Sparse luminous finale: a handful of distant mandalas and node-wheels rotating in vast emptiness, dripping color off their edges into the dark, a last pair of eyes opening far away. Mostly empty space, mesmerizing, minimal, second cycle peak. ", + "14000": "Final whispers in the emptiness: tiny fractal creatures and faint nodes at the edges, a face flickering and gone, the empty space curving and pulling inward again. Asymmetry, last bioluminescent drips, the wormhole beginning to form. ", + "14350": "The final wormhole: nodes and fractal creatures spiraling inward, empty space folding into a tunnel of light, walls rushing past lined with eyes and faces, liquid light streaming down the vortex. Worlds collapsing into the tunnel of light. ", + "14700": "Final implosion into a biological singularity: convergence at a bright white core, both worlds merging, fractal faces and eyes pulled inward, molten glow pouring into the center, the wormhole birthing a new living universe. Dripping streams to the core. " + }, + "positive_prompts": "", + "negative_prompts": "nsfw, nude", + "animation_mode": "3D", + "max_frames": 15000, + "border": "wrap", + "angle": "0: (0)", + "zoom": "0: (1.0)", + "translation_x": "0: (0.25*sin(0.5*3.14*t/1000))", + "translation_y": "0: (0.25*cos(0.5*3.14*t/700))", + "translation_z": "0: (2.25)", + "transform_center_x": "0: (0.5)", + "transform_center_y": "0: (0.5)", + "rotation_3d_x": "0: (0.05*sin(0.5*3.14*t/800))", + "rotation_3d_y": "0: (0.025*sin(0.5*3.14*t/900))", + "rotation_3d_z": "0: (0.15)", + "enable_perspective_flip": false, + "perspective_flip_theta": "0: (0)", + "perspective_flip_phi": "0: (0)", + "perspective_flip_gamma": "0: (0)", + "perspective_flip_fv": "0: (53)", + "noise_schedule": "0: (0.01)", + "strength_schedule": "0:(0.7)", + "contrast_schedule": "0: (1.01)", + "cfg_scale_schedule": "0: (8)", + "enable_steps_scheduling": false, + "steps_schedule": "0: (25)", + "fov_schedule": "0: (80)", + "aspect_ratio_schedule": "0: (1)", + "aspect_ratio_use_old_formula": true, + "near_schedule": "0: (100)", + "far_schedule": "0: (20000)", + "seed_schedule": "0:(s), 1:(-1), \"max_f-2\":(-1), \"max_f-1\":(s)", + "pix2pix_img_cfg_scale_schedule": "0:(1.5)", + "enable_subseed_scheduling": false, + "subseed_schedule": "0: (1)", + "subseed_strength_schedule": "0: (0)", + "enable_sampler_scheduling": false, + "sampler_schedule": "0: (\"Euler a\")", + "use_noise_mask": false, + "mask_schedule": "0: (\"{video_mask}\")", + "noise_mask_schedule": "0: (\"{video_mask}\")", + "enable_checkpoint_scheduling": false, + "checkpoint_schedule": "0: (\"model1.ckpt\"), 100: (\"model2.safetensors\")", + "enable_clipskip_scheduling": false, + "clipskip_schedule": "0: (2)", + "enable_noise_multiplier_scheduling": false, + "noise_multiplier_schedule": "0: (1.0)", + "resume_from_timestring": false, + "resume_timestring": "20260622132250", + "enable_ddim_eta_scheduling": false, + "ddim_eta_schedule": "0: (0)", + "enable_ancestral_eta_scheduling": false, + "ancestral_eta_schedule": "0: (1)", + "amount_schedule": "0: (1.0)", + "kernel_schedule": "0: (5)", + "sigma_schedule": "0: (1)", + "threshold_schedule": "0: (0)", + "color_coherence": "LAB", + "color_coherence_image_path": "", + "color_coherence_video_every_N_frames": 1, + "color_force_grayscale": false, + "legacy_colormatch": false, + "diffusion_cadence": 8, + "optical_flow_cadence": "None", + "cadence_flow_factor_schedule": "0: (1)", + "optical_flow_redo_generation": "None", + "redo_flow_factor_schedule": "0: (1)", + "diffusion_redo": "0", + "noise_type": "uniform", + "perlin_octaves": 4, + "perlin_persistence": 0.5, + "use_depth_warping": true, + "depth_algorithm": "Midas-3-Hybrid", + "midas_weight": -0.3, + "padding_mode": "border", + "sampling_mode": "bicubic", + "save_depth_maps": false, + "video_init_path": "https://deforum.github.io/a1/V1.mp4", + "extract_nth_frame": 1, + "extract_from_frame": 0, + "extract_to_frame": -1, + "overwrite_extracted_frames": false, + "use_mask_video": false, + "video_mask_path": "https://deforum.github.io/a1/VM1.mp4", + "hybrid_comp_alpha_schedule": "0:(0.5)", + "hybrid_comp_mask_blend_alpha_schedule": "0:(0.5)", + "hybrid_comp_mask_contrast_schedule": "0:(1)", + "hybrid_comp_mask_auto_contrast_cutoff_high_schedule": "0:(100)", + "hybrid_comp_mask_auto_contrast_cutoff_low_schedule": "0:(0)", + "hybrid_flow_factor_schedule": "0:(1)", + "hybrid_generate_inputframes": false, + "hybrid_generate_human_masks": "None", + "hybrid_use_first_frame_as_init_image": true, + "hybrid_motion": "None", + "hybrid_motion_use_prev_img": false, + "hybrid_flow_consistency": false, + "hybrid_consistency_blur": 2, + "hybrid_flow_method": "RAFT", + "hybrid_composite": "None", + "hybrid_use_init_image": false, + "hybrid_comp_mask_type": "None", + "hybrid_comp_mask_inverse": false, + "hybrid_comp_mask_equalize": "None", + "hybrid_comp_mask_auto_contrast": false, + "hybrid_comp_save_extra_frames": false, + "parseq_manifest": "", + "parseq_use_deltas": true, + "parseq_non_schedule_overrides": true, + "use_looper": false, + "init_images": "{\n \"0\": \"https://deforum.github.io/a1/Gi1.png\"\n}", + "image_strength_schedule": "0:(0.6)", + "blendFactorMax": "0:(0.35)", + "blendFactorSlope": "0:(0.25)", + "tweening_frames_schedule": "0:(20)", + "color_correction_factor": "0:(0.075)", + "cn_1_overwrite_frames": true, + "cn_1_vid_path": "", + "cn_1_mask_vid_path": "", + "cn_1_enabled": false, + "cn_1_low_vram": false, + "cn_1_pixel_perfect": false, + "cn_1_module": "depth_anything_v2", + "cn_1_model": "diffusers_xl_depth_mid [39c49e13]", + "cn_1_weight": "0:(0.0), 1750:(0.0), 2100:(0.35), 6300:(0.40), 7350:(0.2), 8750:(0.0), 11200:(0.35), 12600:(0.2), 14700:(0.0)", + "cn_1_guidance_start": "0:(0.0)", + "cn_1_guidance_end": "0:(0.8)", + "cn_1_processor_res": 512, + "cn_1_threshold_a": 64, + "cn_1_threshold_b": 64, + "cn_1_resize_mode": "Inner Fit (Scale to Fit)", + "cn_1_control_mode": "Balanced", + "cn_1_loopback_mode": true, + "cn_2_overwrite_frames": true, + "cn_2_vid_path": "", + "cn_2_mask_vid_path": "", + "cn_2_enabled": false, + "cn_2_low_vram": false, + "cn_2_pixel_perfect": false, + "cn_2_module": "none", + "cn_2_model": "None", + "cn_2_weight": "0:(1)", + "cn_2_guidance_start": "0:(0.0)", + "cn_2_guidance_end": "0:(1.0)", + "cn_2_processor_res": 64, + "cn_2_threshold_a": 64, + "cn_2_threshold_b": 64, + "cn_2_resize_mode": "Inner Fit (Scale to Fit)", + "cn_2_control_mode": "Balanced", + "cn_2_loopback_mode": false, + "cn_3_overwrite_frames": true, + "cn_3_vid_path": "", + "cn_3_mask_vid_path": "", + "cn_3_enabled": false, + "cn_3_low_vram": false, + "cn_3_pixel_perfect": false, + "cn_3_module": "none", + "cn_3_model": "None", + "cn_3_weight": "0:(1)", + "cn_3_guidance_start": "0:(0.0)", + "cn_3_guidance_end": "0:(1.0)", + "cn_3_processor_res": 64, + "cn_3_threshold_a": 64, + "cn_3_threshold_b": 64, + "cn_3_resize_mode": "Inner Fit (Scale to Fit)", + "cn_3_control_mode": "Balanced", + "cn_3_loopback_mode": false, + "cn_4_overwrite_frames": true, + "cn_4_vid_path": "", + "cn_4_mask_vid_path": "", + "cn_4_enabled": false, + "cn_4_low_vram": false, + "cn_4_pixel_perfect": false, + "cn_4_module": "none", + "cn_4_model": "None", + "cn_4_weight": "0:(1)", + "cn_4_guidance_start": "0:(0.0)", + "cn_4_guidance_end": "0:(1.0)", + "cn_4_processor_res": 64, + "cn_4_threshold_a": 64, + "cn_4_threshold_b": 64, + "cn_4_resize_mode": "Inner Fit (Scale to Fit)", + "cn_4_control_mode": "Balanced", + "cn_4_loopback_mode": false, + "cn_5_overwrite_frames": true, + "cn_5_vid_path": "", + "cn_5_mask_vid_path": "", + "cn_5_enabled": false, + "cn_5_low_vram": false, + "cn_5_pixel_perfect": false, + "cn_5_module": "none", + "cn_5_model": "None", + "cn_5_weight": "0:(1)", + "cn_5_guidance_start": "0:(0.0)", + "cn_5_guidance_end": "0:(1.0)", + "cn_5_processor_res": 64, + "cn_5_threshold_a": 64, + "cn_5_threshold_b": 64, + "cn_5_resize_mode": "Inner Fit (Scale to Fit)", + "cn_5_control_mode": "Balanced", + "cn_5_loopback_mode": false, + "skip_video_creation": false, + "fps": 30, + "make_gif": false, + "delete_imgs": false, + "delete_input_frames": false, + "add_soundtrack": "None", + "soundtrack_path": "https://deforum.github.io/a1/A1.mp3", + "r_upscale_video": false, + "r_upscale_factor": "x2", + "r_upscale_model": "realesr-animevideov3", + "r_upscale_keep_imgs": true, + "store_frames_in_ram": false, + "frame_interpolation_engine": "None", + "frame_interpolation_x_amount": 2, + "frame_interpolation_slow_mo_enabled": false, + "frame_interpolation_slow_mo_amount": 2, + "frame_interpolation_keep_imgs": true, + "frame_interpolation_use_upscaled": false, + "sd_model_name": "RealVisXL_V5.0_fp16.safetensors", + "sd_model_hash": "ebafbfea", + "deforum_git_commit_id": "400a998b" +} \ No newline at end of file diff --git a/examples/Spore_Mandala_settings.txt b/examples/Spore_Mandala_settings.txt new file mode 100644 index 00000000..97a9d7cc --- /dev/null +++ b/examples/Spore_Mandala_settings.txt @@ -0,0 +1,173 @@ +{ + "W": 1024, + "H": 1024, + "show_info_on_ui": true, + "tiling": false, + "restore_faces": false, + "seed_resize_from_w": 0, + "seed_resize_from_h": 0, + "seed": 88421, + "sampler": "DPM++ 2M SDE", + "scheduler": "Karras", + "steps": 35, + "batch_name": "Spore_Mandala_v1", + "seed_behavior": "iter", + "seed_iter_N": 1, + "use_init": true, + "strength": 0.55, + "strength_0_no_init": false, + "use_mask": false, + "use_alpha_as_mask": false, + "invert_mask": false, + "mask_contrast_adjust": 1.0, + "mask_brightness_adjust": 1.0, + "overlay_mask": false, + "mask_overlay_blur": 4, + "fill": 1, + "full_res_mask": false, + "full_res_mask_padding": 4, + "reroll_blank_frames": "ignore", + "reroll_patience": 10.0, + "motion_preview_mode": false, + "prompts": { + "0": "Data halo mandala: concentric rings glowing perfect symmetry. Blue center through green yellow orange to magenta edges. LED warm dense intricate optical pattern. Emissive rings. Pure geometric. ", + "350": "Data halo rings becoming fine threads: rings dissolving into colored lines radiating outward. Warm reds oranges yellows above, cool magentas pinks purples below. Threads glow fiber-optic LED. Luminous form. Still pure geometric glowing. ", + "700": "Kirell Benzi radial threads: thousands radiating center precision wedges cyan magenta gold violet hot pink colors. Tendrils delicate curves. Balanced dynamic luminous. LED glow. No mushrooms. ", + "1050": "Color wheel mandala: dots concentric rings within threads spectral hues cycling. Unified gradient dots LED spheres. Threads fading transparent. Mandala dominates. Balanced hypnotic. Glowing. ", + "1400": "Color wheel with radial chart: rings both dots and arcs pure hues grading center outward. Wedge segments subtle variations. Connecting threads fine nodes. Complex balanced. Emissive glow. ", + "1750": "Circles meeting mushrooms: small luminous caps appearing mandala edges glowing magenta cyan gold. Circles precise mushrooms float within. Two aesthetics distinct same space. Cave space manifesting. Emissive both. Hybrid beginning. ", + "2100": "Mushrooms and circles merging: caps prominent gills visible circular mandala. Geometric abstract layers within mushroom forms. Dark cave both glows. Precision distorting organic. Mist chaos structured. ", + "2450": "Nested mandalas: multiple patterns dense grove wheel center threads radiating halos mid-ground overlapping caps. Mushrooms own mandala. Colors mix overlaps magenta plus cyan equals violet. Mandala mandalas. ", + "2800": "Cave with geometric overlay: dense mushroom forest semi-transparent circles overlaying radial threads see mushrooms through bright threads still glow. Geometry adds structure chaos without obscuring. Both visible blended. ", + "3150": "Geometric emerging: forest so dense caps blur abstract. Circles prominent precision cutting organic chaos. Geometry imposing order or mushrooms distorting precision tension. Mandala center warping. ", + "3500": "Pure geometry reasserts: mushrooms fading translucent circles dominant Benzi burst visible threads glowing bright cave dissolving. Transitioning pure geometric. Mushroom glow soft background. LED dominant. ", + "3850": "Floating forms space: mushrooms nearly gone faint background halo center wheels at scales bursts orbiting warm LED glowing. Deep glowing space. Negative space dominates. Forms slowly rotating clean psychedelic. ", + "4200": "Maximum complexity: overlapping mandalas scales rotations halo center wheels rotating bursts arcing ring charts dividing. Complex form symphony circles all luminous emissive dark space mesmerizing hypnotic. ", + "4550": "Mushroom whispers: tiny caps appearing edges orbiting geometric structures small distant colored dots threads. Geometric dominant mushrooms reasserting. Hybrid beginning. Asymmetry developing. ", + "4900": "Spiral descent: circles mushrooms spiraling inward vanishing point outer large geometric inner small mushroom aesthetic shifting spectrum colors cycling emissive glow motion vortex worlds collapsing. ", + "5250": "Central convergence: forms bright center point smaller densely packed outer rings visible rotating collapsing blindingly bright white light acceleration focus aesthetics merging implosion. ", + "5600": "Explosion outward: center explodes forms burst radial circles mushrooms flying trailing light saturated electric magenta cyan gold violet energy expanding space filling climax. ", + "5950": "Settling chaos: explosion slowing chaotic arrangement overlapped rotated angles precision disrupted cave partially visible both worlds disorganized glow shadows overlaps beautiful disorienting. ", + "6300": "Mushroom returns: geometric fading forest dominance caps glowing magenta cyan gold dark cave illuminated geometric faintly visible transparent solid mushrooms hybrid shifting organic mist bioluminescence primary. ", + "6650": "Deep cave ghosts: surrounded glowing caps geometric barely visible phantoms overlaying color wheel mandala ghostly cluster radial threads hints spore mist geometric memory dream real cave different intensities. ", + "7000": "Balance equilibrium: two worlds balance geometric circles cave mushrooms floating geometric hybrid aesthetic integrated equal presence forms rotating shifting rhythm colors mixing overlaps emissive light play. ", + "7350": "Dissolution phase: hybrid structure dissolving elements less distinct boundaries blurring glow softening diffuse forms visible losing definition cave fading space predominant ending colors less saturated chaos settling. ", + "7700": "Fading light: forms mostly gone suggestions remaining diffuse glow soft scene glowing faint cave invisible space absolute colors muted dissolution returning light aesthetics merged undefined comedown. ", + "8050": "Pure ethereal glow: no forms visible soft colored light emissive bioluminescence without source cool ethereal hints magenta cyan gold violet space almost empty glow peaceful transcendence. ", + "8400": "Dimming return: glow fading colors disappearing space light darker cooler emissive nearly gone frame dark hints color scene returning space ending quiet silence. ", + "8750": "Space return: light almost gone few hints nearly black returning beginning cycle completing. ", + "9100": "Rebirth halo: faint new data halo manifesting darkness tiny rings glowing appearing new cycle beginning light returning. ", + "9450": "Second cycle begins: data halo rings fully manifest colors cycling cool center hot edges glowing LED warm optical dense intricate emissive pure geometric restart cycle two. ", + "9800": "Halo to threads: rings dissolving threads colors bundled families warm upper cool lower spiraling far fiber optic starburst geometric glowing second cycle progressing. ", + "10150": "Benzi radial second: threads precise wedges cyan magenta gold violet hot pink luminous transmitting tendrils delicate balanced dynamic emissive pure geometric circles clean organized cycle two established. ", + "10500": "Wheel manifesting again: dots concentric rings threads spectral cycling gradient unified threads fading transparent mandala dominates LED spheres glowing second cycle color wheel phase. ", + "10850": "Wheel with chart again: dots arcs both bands pure hue grade outward divisions wedges complex balanced chart mandala fine threads nodes second cycle rings layering. ", + "11200": "Mushrooms entering twice: small caps edges glowing magenta cyan gold circles precise float within distinct same space cave beginning emissive hybrid starting cycle two. ", + "11550": "Caps circles merging again: prominent gills circular arrangement mandala geometric abstract within dark cave both glows precision distorting organic mist chaos second cycle hybrid deepening. ", + "11900": "Nested again: multiple patterns dense grove center wheel threads mid halos caps mushroom mandala colors mixing overlaps mandala mandalas emissive mist second cycle complexity peak. ", + "12250": "Cave with overlay twice: forest dense semi transparent circles overlaying see mushrooms threads glow bright both visible blended light play second cycle full integration. ", + "12600": "Geometric emerging twice: forest blurs circles prominent tension forces mandala center warping second cycle geometric return. ", + "12950": "Pure geometry twice: mushrooms fading Benzi burst dominant threads glowing cave dissolving transitioning back soft background LED dominant second cycle pure state. ", + "13300": "Final floating space: forms nearly gone halo center wheels orbit bursts radiate deep glowing space negative space rotating slowly clean psychedelic hybrid becoming pure second cycle space ending. ", + "13650": "Maximum complexity finale: overlapping mandalas scales rotations all luminous dark space mesmerizing hypnotic second cycle peak complexity final. ", + "14000": "Final dissolution: caps whispers orbiting edges geometric dominant mushrooms reassert asymmetry hybrid beginning present second cycle ending setup. ", + "14350": "Final space begin: circle spirals descending vortex forming worlds collapse. ", + "14700": "Final light implosion: convergence center bright white light both worlds merging. " + }, + "positive_prompts": "", + "negative_prompts": "", + "animation_mode": "3D", + "max_frames": 15000, + "border": "replicate", + "angle": "0: (0)", + "zoom": "0: (1.0)", + "translation_x": "0: (0.25*sin(0.5*3.14*t/1000))", + "translation_y": "0: (0.25*cos(0.5*3.14*t/700))", + "translation_z": "0: (0), 100:(0.5), 300:(1.5), 500:(2.25)", + "transform_center_x": "0: (0.5)", + "transform_center_y": "0: (0.5)", + "rotation_3d_x": "0: (0.05*sin(0.5*3.14*t/800))", + "rotation_3d_y": "0: (0.025*sin(0.5*3.14*t/900))", + "rotation_3d_z": "0: (0.15)", + "enable_perspective_flip": false, + "perspective_flip_theta": "0: (0)", + "perspective_flip_phi": "0: (0)", + "perspective_flip_gamma": "0: (0)", + "perspective_flip_fv": "0: (53)", + "noise_schedule": "0: (0.003)", + "strength_schedule": "0:(0.55)", + "contrast_schedule": "0: (1.0)", + "cfg_scale_schedule": "0: (7)", + "enable_steps_scheduling": false, + "steps_schedule": "0: (35)", + "fov_schedule": "0: (70)", + "aspect_ratio_schedule": "0: (1)", + "aspect_ratio_use_old_formula": false, + "near_schedule": "0: (200)", + "far_schedule": "0: (10000)", + "seed_schedule": "0:(s), 1:(-1), \"max_f-2\":(-1), \"max_f-1\":(s)", + "pix2pix_img_cfg_scale_schedule": "0:(1.5)", + "enable_subseed_scheduling": false, + "subseed_schedule": "0: (1)", + "subseed_strength_schedule": "0: (0)", + "enable_sampler_scheduling": false, + "sampler_schedule": "0: (\"Euler a\")", + "use_noise_mask": false, + "mask_schedule": "0: (\"{video_mask}\")", + "noise_mask_schedule": "0: (\"{video_mask}\")", + "enable_checkpoint_scheduling": false, + "checkpoint_schedule": "0: (\"model1.ckpt\"), 100: (\"model2.safetensors\")", + "enable_clipskip_scheduling": false, + "clipskip_schedule": "0: (2)", + "enable_noise_multiplier_scheduling": true, + "noise_multiplier_schedule": "0: (1.05)", + "resume_from_timestring": false, + "resume_timestring": "", + "enable_ddim_eta_scheduling": false, + "ddim_eta_schedule": "0: (0)", + "enable_ancestral_eta_scheduling": false, + "ancestral_eta_schedule": "0: (1)", + "amount_schedule": "0: (1.0)", + "kernel_schedule": "0: (5)", + "sigma_schedule": "0: (1)", + "threshold_schedule": "0: (0)", + "color_coherence": "LAB", + "color_coherence_image_path": "", + "color_coherence_video_every_N_frames": 1, + "color_force_grayscale": false, + "legacy_colormatch": false, + "diffusion_cadence": 6, + "optical_flow_cadence": "DIS Fine", + "cadence_flow_factor_schedule": "0: (1.0)", + "optical_flow_redo_generation": "DIS Fine", + "redo_flow_factor_schedule": "0: (1.0)", + "diffusion_redo": "0", + "noise_type": "uniform", + "perlin_octaves": 4, + "perlin_persistence": 0.5, + "use_depth_warping": true, + "depth_algorithm": "Midas-3-Hybrid", + "midas_weight": 0.4, + "padding_mode": "border", + "sampling_mode": "bicubic", + "save_depth_maps": false, + "cn_1_enabled": false, + "skip_video_creation": false, + "fps": 30, + "make_gif": false, + "delete_imgs": false, + "delete_input_frames": false, + "add_soundtrack": "None", + "r_upscale_video": false, + "r_upscale_factor": "x2", + "r_upscale_model": "realesr-animevideov3", + "r_upscale_keep_imgs": true, + "store_frames_in_ram": false, + "frame_interpolation_engine": "None", + "frame_interpolation_x_amount": 2, + "frame_interpolation_slow_mo_enabled": false, + "frame_interpolation_slow_mo_amount": 2, + "frame_interpolation_keep_imgs": true, + "frame_interpolation_use_upscaled": false, + "sd_model_name": "juggernautXL_v8Rundiffusion.safetensors" +} diff --git a/microcosm/BEST_DEFAULT_settings.txt b/microcosm/BEST_DEFAULT_settings.txt new file mode 100644 index 00000000..5b4bdaf3 --- /dev/null +++ b/microcosm/BEST_DEFAULT_settings.txt @@ -0,0 +1,308 @@ +{ + "W": 1024, + "H": 1024, + "show_info_on_ui": false, + "tiling": false, + "restore_faces": false, + "seed_resize_from_w": 0, + "seed_resize_from_h": 0, + "seed": 31415, + "sampler": "DPM++ 2M SDE", + "scheduler": "Karras", + "steps": 40, + "batch_name": "Microcosm_{timestring}", + "seed_behavior": "iter", + "seed_iter_N": 12345, + "use_init": true, + "strength": 0.83, + "strength_0_no_init": false, + "init_image": "microcosm-init.png", + "use_mask": false, + "use_alpha_as_mask": false, + "mask_file": "https://deforum.github.io/a1/M1.jpg", + "invert_mask": false, + "mask_contrast_adjust": 1.0, + "mask_brightness_adjust": 1.0, + "overlay_mask": true, + "mask_overlay_blur": 4, + "fill": 1, + "full_res_mask": true, + "full_res_mask_padding": 4, + "reroll_blank_frames": "ignore", + "reroll_patience": 10.0, + "motion_preview_mode": false, + "prompts": { + "0": " Extreme close-up electron micrograph aesthetic, bacteriophage T4 virus particle suspended in vitreous ice. The icosahedral capsid head shows perfect hexagonal protein subunit lattice with crystalline shading, individual capsomeres visible as raised tessellated bumps. The contractile tail sheath descends in striated rings of darker pigment, terminating in a baseplate with six splayed tail fibers articulated like spider legs, each fiber kinked at characteristic joints. Subtle false-color tinting: bruised plum on the capsid, cool slate on the sheath, pale parchment background. Surface micro-detail at every pixel, cryo-EM negative-stain aesthetic, depth of field razor-thin. Photorealistic scientific micrography, hyper-detailed, no artistic interpretation. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "300": " The same bacteriophage now drifting closer to a curved Escherichia coli bacterial membrane surface. The bacterial wall pebbled with lipopolysaccharide texture: thousands of branching sugar chains catching scattered backlight in golden-amber pinpricks. Outer membrane porins visible as faint annular depressions. The phage tail fibers reach toward the surface, one fiber making first molecular contact with an LPS terminal sugar, the contact point ringed with a faint refractive halo of cytoplasmic water displacement. Wet glistening membrane surface, low-key transmission electron microscopy palette of olive, ochre, deep umber. Photorealistic, scientifically literate, hyper-detailed surface texture. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "600": " Bacteriophage anchored to the E. coli surface, tail sheath in mid-contraction. The sheath rings have compressed into thicker pleated stacks while the inner tail tube punches downward through the outer membrane in a microscopic injection. Cytoplasmic leakage forms a tiny droplet at the entry point catching specular highlight. Cross-sectioned membrane reveals lipid bilayer headgroups in characteristic dark-light-dark banding. The empty capsid head has lost some density, walls slightly translucent from genome ejection. False-color TEM aesthetic, mauve and slate palette, motion frozen mid-event. Hyperrealistic scientific imagery, intricate ultrastructural detail. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "900": " Interior view inside the bacterial cytoplasm shortly after viral genome injection. Densely packed ribosomes coat every available surface as small dark granular dots, free DNA strands curl through the open space as fine filamentous threads, the freshly injected viral genome unwinding as a noticeably thicker, brighter strand among them. Polyribosome chains beading along messenger RNA. A few enzymes visible as larger globular shapes. Crowded molecular environment, slate-blue false-color cytoplasm. Photorealistic cryo-ET tomographic aesthetic, every nanometer earned. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "1200": " Procapsid assembly in progress. Half-formed bacteriophage head shells under construction, scaffolding proteins still visible inside the developing capsid lattices, the hexagonal protein subunits being added one by one at growing edges in characteristic prolate geometry. Multiple procapsids at varied stages clustered together. Surrounding cytoplasm filled with free coat protein monomers as smaller particles. Bone-grey false-color shading, dramatic depth of field with one capsid in sharp focus and others trailing into bokeh. Photorealistic structural biology micrograph, scientifically meticulous. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "1500": " Fully formed virions accumulating in the bacterial cytoplasm. Hundreds of completed bacteriophage particles packed in chaotic crystalline arrays, tail fibers tangled together, residual host cytoplasmic structures crowded out to the periphery. The bacterial inner membrane just visible at the bottom edge of frame, beginning to bulge inward from osmotic stress. False-color TEM in cool teal and warm sepia. Dense crowded composition, depth of field shallow, hyper-detailed particle counts. Photorealistic, no stylization. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "1800": " The bacterial cell wall begins to rupture in lysis. A cleft has opened in the outer membrane and inner membrane, peptidoglycan layer visibly torn, cell contents under pressure beginning to evacuate. The first liberated bacteriophages tumble outward through the breach trailed by released cytoplasmic proteins and ribosomes drifting in escaping liquid. Suggestion of explosive osmotic release frozen at the instant of breach. Dramatic chiaroscuro lighting from refracted scattered electrons, palette of bone-white phage against deep-violet cytoplasm and dusty rose membrane fragments. Photorealistic, hyper-detailed, scientifically accurate. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "2100": " Free virions dispersing into the extracellular fluid after lysis. Dozens of bacteriophage particles drifting away from the burst bacterial remnant, suspended in their own Brownian motion against a softer out-of-focus tissue-fluid background. Each phage is rendered with full anatomical clarity: capsid head, sheath, baseplate, fibers \u2014 but at varied depths of field, some sharp, some soft. Suggestion of vast distance to navigate before finding the next host. Cool blue-grey palette, hint of dust-particle ambient backscatter. Photorealistic micrography, contemplative composition. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "2400": " Coronavirus virion at extreme resolution. A spherical lipid envelope of approximately 100 nanometers, surface studded with the characteristic corona of club-shaped spike glycoproteins, each spike a trimer of S protein with visible receptor-binding domain at the distal head and stalk geometry beneath. Between spikes the M protein and small E protein punctate the membrane as smaller bumps. Faint suggestion of the helical nucleocapsid coil inside the translucent envelope. False-color rendering: bruised burgundy spikes, pale parchment membrane, deep umber background. Cryo-electron microscopy aesthetic with negative-stain ring of phosphotungstate around the particle. Photorealistic, scientifically rigorous, every detail earned. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "2700": " Field of mixed bacterial morphologies under high-magnification Gram stain brightfield microscopy. Rod-shaped Bacillus chains in characteristic streptobacillus arrangements stained deep violet, coccal Staphylococcus aureus clusters in grape-like aggregates, spiral Spirillum twisting between them, all swimming in extracellular polymeric matrix. Pleomorphic forms suggesting active division mid-binary-fission. Crystalline iodine staining shadows in the larger Gram-positive cells, faint pink Gram-negative counterstain in others. Phase contrast halo effects around each cell edge. Photorealistic clinical microbiology slide, oil-immersion 1000x feel, hyper-detailed. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "3000": " Dense bacterial biofilm at scanning electron microscopy magnification. Multiple species embedded within a glistening extracellular polymeric substance matrix that stretches between cells in viscous threads and sheets, drying into intricate fractal crackle patterns at the margins. Some bacteria stand erect on the substrate, others lie flat with surface pili anchoring them to the matrix. Water channels carve through the biofilm in rivers and lagoons creating three-dimensional architecture. SEM characteristic monochromatic grayscale with subtle warm false-color tinting. Photorealistic, hyper-detailed surface micrography. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "3300": " Single E. coli bacterium swimming in fluid with flagellar bundle visible at the rear, six to eight helical flagella rotating in counterclockwise bundle for forward run motion, each flagellum a long whip-like proteinaceous filament. Bacterial pole shows hook structure attaching flagella to the motor. Body of the bacterium nearly translucent under dark-field illumination, revealing nucleoid as a denser central region. Surrounding fluid carries drifting molecular debris suggesting chemotactic gradient. Cool teal monochrome with bright specular highlights on flagellar bundle. Photorealistic, motion implied through bundle position, hyperrealistic. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "3600": " Bacterial conjugation event captured mid-transfer. Two E. coli cells connected by a long thin protein pilus bridging the gap between them, single-stranded DNA visible as a fine thread passing through the conjugation tube from donor to recipient. The pilus structure shows characteristic helical assembly of pilin protein subunits, the membrane junction at each end reinforced by a complex protein collar. Surrounding extracellular matrix sparsely populated with smaller debris. False-color TEM aesthetic in muted ochre and slate, with the DNA thread highlighted in faint cyan. Photorealistic, scientifically meticulous, intimate bacterial moment. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "3900": " Endospore formation in a sporulating Bacillus subtilis cell. The mother cell wall remains visible as the outer boundary, but inside, the forespore has begun condensing into a compact ovoid form at one pole, surrounded by characteristic spore coat layers in concentric translucent shells. Calcium dipicolinate crystals already begun deposition in the spore core as glittering inclusions. The mother cell cytoplasm thinning as resources transfer into the spore. Cross-sectional TEM aesthetic, false-color in pale parchment and ochre with the spore core slightly luminous. Photorealistic, hyper-detailed structural biology imagery. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "4200": " Encapsulated bacterial cell viewed at extreme magnification. Streptococcus pneumoniae surrounded by a thick polysaccharide capsule visible as a soft semi-translucent halo extending well beyond the cell wall, the capsule edge feathering into the surrounding fluid in delicate filamentous fronds. Capsule catches and scatters illumination in opalescent shimmer. The cell beneath shows characteristic diplococcus pairing geometry. India ink negative staining technique evident in the surrounding dark background revealing the clear capsule territory. Photorealistic, hyper-detailed clinical pathology aesthetic. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "4500": " Mat of filamentous Oscillatoria cyanobacteria in mid-rotation gliding motion. Long unbranched chains of cylindrical cells laid edge to edge in slightly curving rows, each cell containing photosynthetic membranes visible as fine parallel internal stacks. The mat surface gleams with biofilm extracellular matrix, oxygen bubbles trapped between filaments rising slowly. Subtle blue-green pigmentation from phycocyanin and chlorophyll a colors. Dark mineral grains of calcium carbonate inclusion catching specular highlight. Hyperrealistic photomicrography, wet glistening surface, scientifically accurate. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "4800": " Magnetotactic bacterium with intracellular magnetosome chain. The cell, an elongated coccoid, contains a perfectly aligned linear array of cuboctahedral magnetite crystals each about fifty nanometers, each crystal enveloped in a thin lipid membrane vesicle. The chain runs along the cell axis like a microscopic compass needle. Around the cell, fine grain mineral substrate texture and traces of dissolved ferric ions in the surrounding fluid as faint refractive haze. False-color TEM in cool slate and warm umber palette. Photorealistic, scientifically rigorous, ultrastructural imagery. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "5100": " Bacterial colony viewed from above at low magnification. A circular Bacillus colony showing characteristic concentric ring growth pattern, surface texture wrinkled and matte at the older central zone, becoming smoother and glossier at the outer expansion front. Edge of the colony fingering into the agar surface in delicate branching swarm patterns. Agar surface around the colony shows hint of secondary metabolite diffusion zone. Macrophotography microbiology aesthetic, side-lit to emphasize three-dimensional surface texture, palette of clinical cream and tan. Photorealistic, hyper-detailed colony micrography. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "5400": " Living Paramecium caudatum gliding through a pond water field at phase-contrast magnification. The slipper-shaped body completely covered in beating cilia frozen mid-stroke in characteristic metachronal wave pattern, the oral groove on the ventral side visibly funneling water and food particles inward. Two contractile vacuoles at opposite ends positioned for osmotic regulation, the larger one visibly distended with collected water. Macronucleus and smaller micronucleus faintly visible within the cytoplasm. Phase-contrast halo aura around the cell silhouette. Slate olive and bone palette, drifting algae cells out of focus in background. Hyperrealistic optical microscopy, intricate detail. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "5700": " Amoeba proteus extending pseudopodia in active movement. Multiple finger-like cytoplasmic projections branch outward from the main cell body, each one a current of streaming endoplasm flowing forward inside a thin ectoplasmic sheath. The nucleus visible as a contrasting dense oval in the body's interior, surrounded by food vacuoles containing partially digested smaller organisms in various stages of breakdown. Surface granular with internal organelles. Brightfield microscopy aesthetic with subtle differential interference contrast shadowing. Pale tan body against soft cool grey background, scientifically meticulous, hyperrealistic. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "6000": " Euglena gracilis swimming with characteristic spiral motion. The spindle-shaped cell body shows internal chloroplasts arranged radially in green stars, the prominent red eyespot near the anterior end clearly visible, the long whip-like flagellum trailing forward and undulating in graceful sinusoidal waves. Pellicle texture striated with longitudinal grooves catching subtle iridescent reflection. Suggestion of the fluid being displaced behind the cell as it advances. Darkfield microscopy palette with the cell glowing against deep black background, internal chlorophyll fluorescence enhanced. Photorealistic, hyperrealistic micrography. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "6300": " Cluster of foraminifera tests, calcium carbonate shells of single-celled protists at scanning electron microscopy magnification. Each test a perfectly chambered spiraled construction, chambers added in logarithmic growth, surface pores allowing pseudopodia to extend. Various species showing distinct geometries: planispiral, trochospiral, milioline. Surface texture of fine carbonate crystals catching scattered electron beam in glassy gold-bone palette. Dramatic side-lighting reveals chamber wall thickness and pore architecture. Photorealistic SEM scientific micrograph, hyper-detailed crystalline structure. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "6600": " Radiolarian skeleton, an Ernst Haeckel masterpiece in actual three-dimensional silicate. Intricately latticed spherical cage of opaline silica, geometric perfection in pentagonal and hexagonal apertures, radial spines projecting outward in symmetrical arrays. Internal nested concentric shells faintly visible through the outer cage. Suggestion of cytoplasm and central capsule still embedded inside. Darkfield illumination casting the structure into glowing translucent jewel against deep void. Pale honey gold over inky black, fractal mathematical perfection. Photorealistic, hyperrealistic biological mineralogy. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "6900": " Armored dinoflagellate Ceratium with characteristic horn-shaped projections. The thecal plates fitted together like an alien helmet, surface engraved with fine reticulate patterns, three long horns extending in different directions giving the cell its strange asymmetric profile. Two flagella visible: the transverse cingular flagellum wrapped around the equator, the longitudinal sulcal flagellum trailing posterior. Chloroplasts dappled inside through translucent thecal armor. Photorealistic darkfield with subtle bioluminescent glow tint, ocean blue-green palette. Hyperrealistic microbiology. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "7200": " Pennate diatom in darkfield, frustule of two frustule halves overlapping like a pillbox. The silica frustule walls etched with thousands of nano-scale punctae arranged in precise rows and chevrons, the central raphe running longitudinally as a sealed slit. Through the translucent walls, golden-brown chloroplasts visible inside the protoplast. Edge highlights of the frustule scattered into prismatic refraction. Pure jewel-like clarity, cool cyan and ivory palette against absolute black background. Photorealistic, hyper-detailed silica micro-architecture. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "7500": " Colony of choanoflagellates with collared cells in characteristic arrangement. Each cell flask-shaped, bearing a single anterior flagellum surrounded by a collar of fine microvilli that filter bacteria from the surrounding water. The flagellum beats in slow corkscrew motion drawing water current through the collar. Multiple cells share a common gelatinous matrix connecting them into a small colony. Suggestion of captured bacteria trapped against the collar. Phase-contrast aesthetic with halo, soft pearl-grey and translucent silver palette. Photorealistic, hyperrealistic protistology. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "7800": " Acanthamoeba in trophozoite stage with characteristic spike-like pseudopodia called acanthopodia. The cell surface bristles with fine sharp projections in radial array, the body itself flattened against the substrate, internal nucleus prominent with dense nucleolus visible. Surrounding fluid carries fine grain debris and bacterial prey. Differential interference contrast microscopy aesthetic giving relief and depth to surface architecture. Slate blue and silver palette, hyperrealistic optical micrography, scientifically rigorous. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "8100": " Living tardigrade water bear at extreme phase-contrast microscopy magnification. Eight stubby clawed legs gripping a strand of wet sphagnum moss, each leg ending in four to eight curved claws articulated like grappling hooks. Translucent cuticle reveals internal organs in faint chiaroscuro: ventral nerve cord, muscular pharynx with crystalline stylets retracted, glistening gut tube. Two black eyespots in dorsal head. Slow deliberate posture. Honey-amber and pale teal palette, surrounding water droplet creating prismatic halo. Hyperrealistic optical microscopy, every cuticular bristle rendered. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "8400": " Tardigrade in tun state, dehydrated cryptobiosis form. The animal has retracted its legs and head into a compact barrel shape, cuticle dramatically wrinkled and accordioned, body water content reduced to near zero. Surface texture leathery, glassy reflections from preserved trehalose sugars protecting internal structures. Surrounding substrate dry and crackled. Backlit slightly to reveal the still-organized internal architecture frozen in suspended life. Dusty amber and parchment palette. Photorealistic micro-photography, scientifically literate. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "8700": " Rotifer Brachionus crown of beating cilia in vortex feeding motion. The transparent body shows internal mastax with prominent grinding trophi jaws, a long gut and corona of cilia creating visible water currents drawing in particles. Foot at the posterior with toes for substrate attachment. Carapace lorica armor faintly visible as outer shell. Surrounded by algal cells caught in the feeding vortex. Phase contrast aesthetic with strong halo effect, pale ivory and translucent green palette. Photorealistic, hyper-detailed micro-zoology. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "9000": " Copepod Cyclops mid-swim under darkfield illumination. Streamlined body with prominent single nauplius eye in characteristic crimson coloration, long branched antennae splayed forward for prey detection, abdomen tapering to forked caudal rami. Egg sacs visible at the rear in pearl-translucent clusters carrying developing nauplii. Body bristles set with sensory hairs. Glowing against deep black darkfield background, body translucent enough to reveal internal gut and musculature. Hyperrealistic photomicrography, scientifically accurate. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "9300": " Water mite Hydracarina close-up. Spherical orange-red body covered in fine setae, eight legs splayed in walking posture, each leg jointed and bristled. Mouthparts in the form of a chelate gnathosoma at the front. Surface texture pebbled like miniature alligator hide. Through translucent integument, hint of internal gut diverticula visible. Brightfield microscopy with crisp focus, warm orange and brown palette against pale aqua aquatic background. Photorealistic, hyperrealistic acarology micrography. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "9600": " Planarian flatworm Dugesia in dorsal view. The triangular head bears two simple eyespots like dark teardrops and lateral auricles for chemosensing. The body laterally flattened, dorsal surface mottled with dark and light pigment patches in characteristic species pattern. Pharynx visible as a denser tube along the ventral midline ready to evert for feeding. Surface ciliated for gliding motion. Moist glistening sheen. Photographic clinical micrography, pale tan and chocolate palette against off-white substrate. Photorealistic, hyper-detailed. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "9900": " Free-living nematode Caenorhabditis elegans in dorsoventral view. The slender cylindrical body about one millimeter long, cuticle smooth and translucent, internal anatomy visible through the body wall: pharynx with grinder, gonad arms, intestine, eggs in late development within hermaphrodite. Body in a characteristic sinusoidal posture mid-undulation. Differential interference contrast microscopy aesthetic giving organelle-level detail. Pale champagne and cream palette, scientifically meticulous, hyperrealistic developmental biology imagery. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "10200": " Mosquito larva Culex hanging upside down at the water surface. Siphon tube broken through surface tension for atmospheric breathing, body suspended beneath in characteristic angled posture. Segmented abdomen, thorax with bristles, head with mouth brushes filtering particles from the water column. Internal gut filled with detritus visible through translucent integument. Surface tension film visible as faint refractive ring around the siphon. Brightfield aquatic micrography palette of olive and chestnut against pale aqua. Photorealistic, hyperrealistic micro-zoology. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "10500": " Daphnia magna water flea in lateral view. Translucent carapace shell shows everything inside in extraordinary clarity: single black compound eye, beating heart visible as a faint rhythmic pulsation in the upper body, brood pouch carrying developing parthenogenetic embryos at various stages, intricate branched antennae extending forward used for swimming, hopping locomotion. Gut filled with algal detritus. Phase contrast halo aesthetic with subtle false-color in cool green and warm amber. Photorealistic, hyperrealistic micrography. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "10800": " Mitochondrion in cross-section at electron microscopy resolution. The double membrane envelope clearly resolved as two parallel dark lines separated by intermembrane space, the inner membrane deeply infolded into characteristic accordion cristae jutting into the matrix interior. Cristae studded with tiny stalked F1-F0 ATP synthase complexes visible as raised bumps along the inner membrane surface. Matrix dense with proteins and circular mitochondrial DNA visible as a faint coiled thread. False-color TEM in muted slate and warm sepia. Hyperrealistic ultrastructural biology, scientifically meticulous. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "11100": " Golgi apparatus in cross-section. Stacked flattened cisternae form the characteristic cis-medial-trans architecture, each cisterna a slim disk of membrane, peripheral edges curling and budding off transport vesicles in active vesicular trafficking. Free vesicles surround the stack in profusion, some en route to plasma membrane delivery. Nuclear envelope visible at the corner of the frame for context. Cytoplasm dense with ribosomes and cytoskeletal filaments. False-color TEM aesthetic in dusty rose, ochre, and slate. Photorealistic, hyper-detailed cellular ultrastructure. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "11400": " Cell nucleus interior at chromatin level. Dense heterochromatin clumps near the nuclear envelope inner surface, looser euchromatin spread through the central nucleoplasm, prominent nucleolus visible as a darker spherical region of active rRNA synthesis. Nuclear pores in the envelope appear as ring-shaped openings. Suggestion of individual chromatin fibers as nucleosome bead-on-string strands. False-color TEM rendering in warm rose and bone tones. Hyperrealistic ultrastructural imagery, scientifically rigorous. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "11700": " Cytoskeleton at high magnification cryo-electron tomography aesthetic. Actin filaments visible as fine twin-strand helices forming branched networks, microtubules as wider hollow cylinders running across the field, intermediate filaments as ropes of woven protein strands. Crosslinking proteins visible at junctions. Plasma membrane lipid bilayer at one edge of the field. Cool grey-blue monochromatic palette with subtle warmth. Photorealistic cryo-ET aesthetic, hyperrealistic structural cell biology. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "12000": " Membrane vesicle fusion event captured at the moment of bilayer merger. A small transport vesicle has docked against the larger target membrane, SNARE protein complexes from both membranes intertwined in tight four-helix bundle pulling the bilayers together, the lipid bilayers in mid-fusion as a transient stalk-and-hemifusion intermediate. Surrounding cytoplasm dense with proteins. False-color TEM in cool slate and warm parchment, scientifically meticulous. Hyperrealistic membrane biology, hyper-detailed nanoscale moment. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "12300": " Red blood cells flowing through a capillary lumen at high magnification. Biconcave disc erythrocytes deformed by the narrow passage, single file, jostling against each other and against the endothelial cell wall. The endothelium is a thin glistening layer with prominent cell nuclei bulging into the lumen. Following the erythrocytes, a single leukocyte rolls along the wall surface ruffled with microvilli, preparing for diapedesis. Plasma in between visible as a faintly opalescent fluid carrying drifting platelets. Crimson and salmon palette under transmitted light, hyperrealistic photomicrography. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "12600": " Synaptic junction between two neurons at electron microscopy resolution. Presynaptic terminal swollen with synaptic vesicles clustered against the active zone, several vesicles docked and primed for release. Synaptic cleft as a narrow space about twenty nanometers wide. Postsynaptic density appearing as a thicker electron-dense band on the receiving neuron membrane. Mitochondria in the presynaptic terminal providing energy. False-color TEM aesthetic in cool slate and warm sepia. Hyper-detailed neurobiology, scientifically meticulous. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "12900": " Macrophage in active phagocytosis engulfing a bacterium. The white blood cell has extended pseudopodia around the prey, the cell membrane folding in characteristic phagocytic cup geometry, the bacterium already partially engulfed with the membrane closing over it. Surface of macrophage ruffled with active cytoskeletal protrusions. Internal lysosomes prepared near the forming phagosome ready for fusion. Surrounding plasma with antibody molecules in solution. False-color TEM aesthetic: warm pink macrophage, pale tan bacterium, neutral plasma. Hyperrealistic immunology micrography. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "13200": " Alveolus in lung tissue at scanning electron microscopy. The thin-walled air sac coated with surfactant film, capillaries pressed against the outside surface visible as bumpy vessels carrying erythrocytes within. Type I pneumocytes form the gas exchange surface as flat thin cells, type II pneumocytes appearing as cuboidal cells with surfactant droplet content. Alveolar macrophage patrolling the interior surface. Wet glistening texture. SEM monochromatic grayscale with subtle warm false-color, photorealistic, hyper-detailed. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "13500": " Cross-section of intestinal villus brush border at electron microscopy. The epithelial cell apical surface bristling with thousands of densely packed microvilli forming a uniform brush border, each microvillus a fingerlike membrane protrusion supported by an actin filament core. Above the brush border, the glycocalyx coating as fine fuzzy mat. Below, junctional complexes seal cells together. Mitochondria abundant in the apical cytoplasm. False-color TEM in muted pink and slate, scientifically meticulous, hyperrealistic ultrastructure. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "13800": " Pulling back to medium magnification: a single droplet of pond water on a microscope slide revealed teeming with microscopic life. Inside the curved spherical boundary of the droplet, simultaneously visible: a tardigrade, two paramecia, a rotifer, several diatoms, drifting bacterial chains, a single phage-like particle, foraminiferan tests, mineral grains. All sharing the same suspended liquid universe in dense diorama composition. Droplet surface refracts light into prismatic halos. Cool blue-green palette, photorealistic micrography, contemplative awe. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "14100": " Soil clump at high magnification revealing a hidden teeming ecosystem. Mineral grains, organic detritus, fungal hyphae weaving through, nematodes browsing, mites stalking among the particles, bacterial biofilms coating every surface, springtails and tardigrades in moist crevices. The matrix of life packed into a few cubic millimeters of soil. Warm earth-tone palette of umber, ochre, and chestnut. Photorealistic environmental micrography, hyper-detailed diorama. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "14400": " Air at high magnification: atmospheric microbiome and particulates. Bacteria attached to dust grains drift through frame, pollen grains tumble in slow rotation, fungal spores released from invisible substrate, single virus particles riding on droplet nuclei. Sunlight beams through the air at oblique angles revealing the suspended drifting world normally invisible. Pale gold and silver against translucent blue background. Photorealistic, hyperrealistic aerobiology imagery. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude", + "14700": " Final transcendent micro-macro reveal. The pond drop, the soil clump, the air sample all converge into a single composite vision: the visible universe at every nanometer scale full of life, structure, and pattern. Bacteriophages, bacteria, protists, micrometazoans, subcellular architecture, all overlaid in a multi-scale composition rendered with photographic clarity at each register. Light is patient and uninterested in being looked at. Quiet awe. Photorealistic transcendent finale, painterly micrography bloom, scientifically rigorous beauty. --neg cartoon, anime, illustration, painting, drawing, 3d render, cgi, low quality, blurry, watermark, text, signature, deformed, plastic, toy, doll, fake, oversaturated, neon, glow, smooth, airbrushed, nsfw, nude, child nsfw, nude" + }, + "positive_prompts": "", + "negative_prompts": "nsfw, nude", + "animation_mode": "3D", + "max_frames": 15000, + "border": "wrap", + "angle": "0: (0)", + "zoom": "0: (1.0006+0.0004*sin(0.5*3.14*t/30))", + "translation_x": "0: (0.35*sin(0.5*3.14*t/200))", + "translation_y": "0: (0.5*sin(0.5*3.14*t/240))", + "translation_z": "0: (2.5)", + "transform_center_x": "0: (0.5)", + "transform_center_y": "0: (0.5)", + "rotation_3d_x": "0: (0.06*sin(0.5*3.14*t/180))", + "rotation_3d_y": "0: (0.05*sin(0.5*3.14*t/220))", + "rotation_3d_z": "0: (0.03*sin(0.5*3.14*t/260))", + "enable_perspective_flip": false, + "perspective_flip_theta": "0: (0)", + "perspective_flip_phi": "0: (0)", + "perspective_flip_gamma": "0: (0)", + "perspective_flip_fv": "0: (53)", + "noise_schedule": "0: (0.01)", + "strength_schedule": "0: (0.6)", + "contrast_schedule": "0: (1.0)", + "cfg_scale_schedule": "0: (6)", + "enable_steps_scheduling": false, + "steps_schedule": "0: (25)", + "fov_schedule": "0: (80)", + "aspect_ratio_schedule": "0: (1)", + "aspect_ratio_use_old_formula": false, + "near_schedule": "0: (50)", + "far_schedule": "0: (20000)", + "seed_schedule": "0:(s), 1:(-1), \"max_f-2\":(-1), \"max_f-1\":(s)", + "pix2pix_img_cfg_scale_schedule": "0:(1.5)", + "enable_subseed_scheduling": false, + "subseed_schedule": "0: (1)", + "subseed_strength_schedule": "0: (0)", + "enable_sampler_scheduling": false, + "sampler_schedule": "0: (\"Euler a\")", + "use_noise_mask": false, + "mask_schedule": "0: (\"{video_mask}\")", + "noise_mask_schedule": "0: (\"{video_mask}\")", + "enable_checkpoint_scheduling": false, + "checkpoint_schedule": "0: (\"model1.ckpt\"), 100: (\"model2.safetensors\")", + "enable_clipskip_scheduling": false, + "clipskip_schedule": "0: (2)", + "enable_noise_multiplier_scheduling": false, + "noise_multiplier_schedule": "0: (1.0)", + "resume_from_timestring": false, + "resume_timestring": "", + "enable_ddim_eta_scheduling": false, + "ddim_eta_schedule": "0: (0)", + "enable_ancestral_eta_scheduling": false, + "ancestral_eta_schedule": "0: (1)", + "amount_schedule": "0: (1.0)", + "kernel_schedule": "0: (5)", + "sigma_schedule": "0: (1)", + "threshold_schedule": "0: (0)", + "color_coherence": "LAB", + "color_coherence_image_path": "", + "color_coherence_video_every_N_frames": 1, + "color_force_grayscale": false, + "legacy_colormatch": false, + "diffusion_cadence": 5, + "optical_flow_cadence": "DIS Fine", + "cadence_flow_factor_schedule": "0: (1)", + "optical_flow_redo_generation": "DIS Fine", + "redo_flow_factor_schedule": "0: (1)", + "diffusion_redo": "0", + "noise_type": "perlin", + "perlin_octaves": 4, + "perlin_persistence": 0.5, + "use_depth_warping": false, + "depth_algorithm": "Midas-3-Hybrid", + "midas_weight": 0.5, + "padding_mode": "border", + "sampling_mode": "bicubic", + "save_depth_maps": false, + "video_init_path": "https://deforum.github.io/a1/V1.mp4", + "extract_nth_frame": 1, + "extract_from_frame": 0, + "extract_to_frame": -1, + "overwrite_extracted_frames": false, + "use_mask_video": false, + "video_mask_path": "https://deforum.github.io/a1/VM1.mp4", + "hybrid_comp_alpha_schedule": "0:(0.5)", + "hybrid_comp_mask_blend_alpha_schedule": "0:(0.5)", + "hybrid_comp_mask_contrast_schedule": "0:(1)", + "hybrid_comp_mask_auto_contrast_cutoff_high_schedule": "0:(100)", + "hybrid_comp_mask_auto_contrast_cutoff_low_schedule": "0:(0)", + "hybrid_flow_factor_schedule": "0:(1)", + "hybrid_generate_inputframes": false, + "hybrid_generate_human_masks": "None", + "hybrid_use_first_frame_as_init_image": true, + "hybrid_motion": "None", + "hybrid_motion_use_prev_img": false, + "hybrid_flow_consistency": false, + "hybrid_consistency_blur": 2, + "hybrid_flow_method": "RAFT", + "hybrid_composite": "None", + "hybrid_use_init_image": false, + "hybrid_comp_mask_type": "None", + "hybrid_comp_mask_inverse": false, + "hybrid_comp_mask_equalize": "None", + "hybrid_comp_mask_auto_contrast": false, + "hybrid_comp_save_extra_frames": false, + "parseq_manifest": "", + "parseq_use_deltas": true, + "parseq_non_schedule_overrides": true, + "use_looper": false, + "init_images": "{\n \"0\": \"https://deforum.github.io/a1/Gi1.png\"\n}", + "image_strength_schedule": "0:(0.6)", + "blendFactorMax": "0:(0.35)", + "blendFactorSlope": "0:(0.25)", + "tweening_frames_schedule": "0:(20)", + "color_correction_factor": "0:(0.075)", + "cn_1_overwrite_frames": true, + "cn_1_vid_path": "", + "cn_1_mask_vid_path": "", + "cn_1_enabled": true, + "cn_1_low_vram": false, + "cn_1_pixel_perfect": false, + "cn_1_module": "depth_anything_v2", + "cn_1_model": "diffusion_pytorch_model_promax [9460e4db]", + "cn_1_weight": "0:(0.45)", + "cn_1_guidance_start": "0:(0.0)", + "cn_1_guidance_end": "0:(0.8)", + "cn_1_processor_res": 512, + "cn_1_threshold_a": 64, + "cn_1_threshold_b": 64, + "cn_1_resize_mode": "Inner Fit (Scale to Fit)", + "cn_1_control_mode": "Balanced", + "cn_1_loopback_mode": true, + "cn_2_overwrite_frames": true, + "cn_2_vid_path": "", + "cn_2_mask_vid_path": "", + "cn_2_enabled": false, + "cn_2_low_vram": false, + "cn_2_pixel_perfect": false, + "cn_2_module": "none", + "cn_2_model": "None", + "cn_2_weight": "0:(1)", + "cn_2_guidance_start": "0:(0.0)", + "cn_2_guidance_end": "0:(1.0)", + "cn_2_processor_res": 64, + "cn_2_threshold_a": 64, + "cn_2_threshold_b": 64, + "cn_2_resize_mode": "Inner Fit (Scale to Fit)", + "cn_2_control_mode": "Balanced", + "cn_2_loopback_mode": false, + "cn_3_overwrite_frames": true, + "cn_3_vid_path": "", + "cn_3_mask_vid_path": "", + "cn_3_enabled": false, + "cn_3_low_vram": false, + "cn_3_pixel_perfect": false, + "cn_3_module": "none", + "cn_3_model": "None", + "cn_3_weight": "0:(1)", + "cn_3_guidance_start": "0:(0.0)", + "cn_3_guidance_end": "0:(1.0)", + "cn_3_processor_res": 64, + "cn_3_threshold_a": 64, + "cn_3_threshold_b": 64, + "cn_3_resize_mode": "Inner Fit (Scale to Fit)", + "cn_3_control_mode": "Balanced", + "cn_3_loopback_mode": false, + "cn_4_overwrite_frames": true, + "cn_4_vid_path": "", + "cn_4_mask_vid_path": "", + "cn_4_enabled": false, + "cn_4_low_vram": false, + "cn_4_pixel_perfect": false, + "cn_4_module": "none", + "cn_4_model": "None", + "cn_4_weight": "0:(1)", + "cn_4_guidance_start": "0:(0.0)", + "cn_4_guidance_end": "0:(1.0)", + "cn_4_processor_res": 64, + "cn_4_threshold_a": 64, + "cn_4_threshold_b": 64, + "cn_4_resize_mode": "Inner Fit (Scale to Fit)", + "cn_4_control_mode": "Balanced", + "cn_4_loopback_mode": false, + "cn_5_overwrite_frames": true, + "cn_5_vid_path": "", + "cn_5_mask_vid_path": "", + "cn_5_enabled": false, + "cn_5_low_vram": false, + "cn_5_pixel_perfect": false, + "cn_5_module": "none", + "cn_5_model": "None", + "cn_5_weight": "0:(1)", + "cn_5_guidance_start": "0:(0.0)", + "cn_5_guidance_end": "0:(1.0)", + "cn_5_processor_res": 64, + "cn_5_threshold_a": 64, + "cn_5_threshold_b": 64, + "cn_5_resize_mode": "Inner Fit (Scale to Fit)", + "cn_5_control_mode": "Balanced", + "cn_5_loopback_mode": false, + "skip_video_creation": false, + "fps": 30, + "make_gif": false, + "delete_imgs": false, + "delete_input_frames": false, + "add_soundtrack": "None", + "soundtrack_path": "https://deforum.github.io/a1/A1.mp3", + "r_upscale_video": false, + "r_upscale_factor": "x2", + "r_upscale_model": "realesr-animevideov3", + "r_upscale_keep_imgs": true, + "store_frames_in_ram": false, + "frame_interpolation_engine": "None", + "frame_interpolation_x_amount": 2, + "frame_interpolation_slow_mo_enabled": false, + "frame_interpolation_slow_mo_amount": 2, + "frame_interpolation_keep_imgs": true, + "frame_interpolation_use_upscaled": false, + "sd_model_name": "MOHAWK_v20.safetensors", + "sd_model_hash": "1a89f0fb", + "deforum_git_commit_id": "a94ba3c7", + "outdir": "" +} \ No newline at end of file diff --git a/microcosm/BEST_PRACTICES.txt b/microcosm/BEST_PRACTICES.txt new file mode 100644 index 00000000..136d5ea4 --- /dev/null +++ b/microcosm/BEST_PRACTICES.txt @@ -0,0 +1,41 @@ +DEFORUM BEST PRACTICES, Brian's lab notes (hard-won, every line came from a real render) +Vello: add yours below, or edit anything here. + +== CHECKPOINTS == +- MOHAWK_v20 is the workhorse. Best all-round color + detail for these renders. +- CyberRealisticXL V9 = strongest pure photorealism, but reads flatter on abstract/organic work. +- RealVisXL came out flat and detail-less here. epiCRealism / Juggernaut on disk, barely tested. +- The checkpoint matters MORE than prompt wording for killing the cartoony AI look. + +== THE STREAK / SPAGHETTI ZONE (how renders go bad) == +- Horror CREATURE LoRAs caused the radiating spaghetti-line streaking. They live in models/Lora/SDXL/Risky/, leave them there. +- Cadence 15 + strength 0.7 with 3D depth-warp also spaghettis on its own. Safe zone: cadence <= 10 in 3D (12+ is fine in 2D mode, no depth warp to accumulate), strength <= 0.6. +- Any render past ~3000 frames drifts with master defaults; strength 0.6 + noise 0.01 was the fix that survived an A/B. +- Fractal LoRAs were wrongly blamed once, exonerated. But the fractal/LINE loras (ral-mndlbrt etc. at high weight) still make hated spaghetti lines. Fractal_Fusion at LOW weight is the liked one. + +== SMOOTHNESS == +- Do NOT oscillate image-quality params (strength / noise / CFG / contrast / antiblur on sine waves). Six of them waving at once = visible breathing/flicker. Animate the CAMERA, keep image params FLAT. +- Two proven smoothness paths: (1) LAB color coherence + Looper = locked palette, ultra stable, one mood; (2) color_coherence None + DIS Fine optical flow = smooth AND per-scene color shifts. +- Best-ever recipe (Microcosm v2): MOHAWK, DPM++ 2M SDE/Karras, 40 steps, strength 0.6, noise 0.01, cadence 5, DIS Fine, LAB, translation_z 2.5, midas 0.5, seed 31415. + +== CAMERA / FOV == +- FOV floor is 40. Below that it wonks out. Sweep with cos: "0: (mid-amp*cos(2*3.14*t/PERIOD))", period 900-2000 frames. +- FOV-SPEED COUPLING is the signature move: multiply every camera field by an envelope in phase with the FOV sweep, so telephoto = slow, wide = fast. Keep Z from fully stopping (envelope floor ~0.55). +- Roller-coaster cam: roll never level, banks into turns; yaw/pitch phase-LEAD the translation so the camera looks INTO the curve before it turns. +- 2D FAKE-3D: animation_mode 2D + enable_perspective_flip CAN fake depth, but NEVER oscillate the warp. Sine-waving angle/theta/phi/gamma rocks the flat canvas back and forth = instant seasick wobble (the 008 render Brian hated). If you use it: constant or one-direction drift on the lean, zoom + translation do the movement, no canvas roll. High cadence is safe there (no depth warp). +- midas_weight NEGATIVE (-0.6) = Brian's inverted-depth look. Intentional, not a bug. border: wrap. + +== INIT IMAGES == +- The init's PALETTE + CONTRAST drive the whole render. Start from something colorful and high-contrast, never the dark-on-black images. +- Always use_init=True with a real image. Beware the folder gotcha: settings often point at outputs/deforum_init_images/ while the images actually live in outputs/img2img-images/INIT_IMAGES/. +- Vary the init per render. Reused inits get samey fast. + +== PROMPTS / LORAS == +- Keyframe every ~300 frames, dense 500+ char prompts. One scene subject + a modifier + camera language. +- Photoreal language that works: name a real camera ("shot on a Sony Alpha 1 8K, 85mm f/1.4"), "RAW photo", "indistinguishable from a real photograph". Vague "hyperrealistic" alone does nothing. +- Rotate 1-2 style LoRAs per keyframe for variety; add-detail-xl ~0.5-0.6 as the always-on utility. Anime/painterly/fae LoRAs (Ghibli, Shinkai, xl_more_art, FaeTastic) = instant cartoon; keep them out of photoreal work. +- Organic/surreal subjects render beautifully; mechanical/clockwork content renders cartoony, avoid. +- NEVER bake negative prompts into keyframes. One global negative box, filled by hand. + +== VELLO'S SECTION == +(add your stuff here) diff --git a/microcosm/Microcosm.html b/microcosm/Microcosm.html new file mode 100644 index 00000000..82035a24 --- /dev/null +++ b/microcosm/Microcosm.html @@ -0,0 +1,1951 @@ +Microcosm +
+
+

Microcosm

+ + + + across + + Card size + +
+
+
+ + + + +
+ + + + + + + + + +
+ + + + tick "compare" on the renders you want, like picking TVs at Best Buy +
+
+
+

Compare

+ + + +
+
+
+ + \ No newline at end of file diff --git a/microcosm/README.md b/microcosm/README.md new file mode 100644 index 00000000..94766517 --- /dev/null +++ b/microcosm/README.md @@ -0,0 +1,136 @@ +# Microcosm + +*Deforum render viewer, best-settings recipe, and the notes behind them.* + +Tools for reviewing Deforum renders and dialling in settings, plus the settings and notes behind them. + +Three pieces. The first needs nothing installed, you can use it in about ten seconds. + +| | What it is | Needs | +|---|---|---| +| **[`Microcosm.html`](Microcosm.html)** | Inspect + compare renders | a browser | +| **[`BEST_DEFAULT_settings.txt`](BEST_DEFAULT_settings.txt)** | My best working recipe, ready to load | Deforum | +| **[`BEST_PRACTICES.txt`](BEST_PRACTICES.txt)** | What makes renders good or garbage | nothing | + +The viewer is one file. If you install the Deforum extension, the Deforum tab has an **Open the render viewer** button that opens this exact same `Microcosm.html` in a browser tab, so there's one viewer, reachable whether Stable Diffusion is open or closed. No separate gallery app. + +--- + +## 1. The viewer, no install + +**[Download `Microcosm.html`](Microcosm.html)** (right-click Save link as), then double-click it. + +That's the entire setup. No Python, no pip, no server, no build step, no internet, it's one 291 KB file with everything inline (including the Best Practices screenshots) and zero external references. It works with your wifi off, and nothing you open in it ever leaves your machine. + +### Why it exists + +Deforum writes a video and a settings file side by side, then leaves you guessing. The settings are a wall of JSON full of math like: + +``` +"0: (42-24*cos(2*3.14*t/2000))" +``` + +That describes a value *changing* across thousands of frames. Reading it tells you nothing about what frame 8,400 actually looked like. + +This viewer evaluates that math live against playback. Press play, and the panel under the video shows the prompt, the LoRAs, the FOV and every camera value **at the frame you're watching**. When a LoRA changes it lights up green. So when a render turns out great, or like total garbage, you can see exactly what was happening at that moment. + +### Using it + +- Drag a render's `.mp4` **and** its `_settings.txt` onto the box. (Or a whole folder, or use the Browse buttons.) +- Press play. Watch the panel under the video. +- Tick **compare** on two or more, hit **Compare selected**: side-by-side, synced playback, every parameter aligned in rows with **differences highlighted** and identical ones dimmed. "Differences only" cuts straight to what changed. +- **View** menu: One row / Grid (you pick how many across) / Rows. + +The video and settings must be name-matched: + +``` +MyRender_20260101120000.mp4 +MyRender_20260101120000_settings.txt +``` + +That's exactly how Deforum saves them, so normally it just works. + +--- + +## 2. `BEST_DEFAULT_settings.txt`, the Microcosm recipe + +The actual Microcosm v2 settings, the render this whole thing is named after. Real prompts, real LoRA stack, nothing gutted. Only the machine-specific plumbing (output dir, resume state) has been cleared. + +**To load it**, either: + +- **Drop it on the preset box** in the Deforum tab, then pick it from the **Preset** dropdown. (This fork adds that, drag in any number of settings files and they become presets.) +- Or the old way: type a path into the **Settings File** box, then click **Load all settings**. + +Then swap the prompts for your own and render. + +### What it needs + +**Checkpoint:** `MOHAWK_v20`. Any good SDXL model works, just pick a different one in the normal checkpoint dropdown, or change `sd_model_name` in the file. + +**Init image:** `microcosm-init.png` ships next to this file. Drop it into the **Init image** box, this fork auto-ticks "use init" when you do. (The settings reference it by filename, so point it wherever you keep it.) + +**LoRAs**, three on every keyframe, the rest as accents: + +| LoRA | Weight | Keyframes | +|---|---|---| +| `add-detail-xl` | 0.7 | all 50 | +| `JuggerCineXL2` | 0.55 | all 50 | +| `xl_more_art-full_v1` | 0.35 | all 50 | +| `ral-amber-sdxl` | 0.35-0.45 | 38 | +| `ral-trichome-sdxl` | 0.40 | 31 | +| `ral-iricnt-sdxl` | 0.30 | 27 | +| `coralbugXL` | 0.30-0.40 | 25 | +| `ral-anmlsktn-sdxl-dora` | 0.35 | 20 | +| `Fractal_Fusion-000009` | 0.30 | 17 | +| `HR_Giger_SDXL` | varies | 13 | +| `ral-melting-sdxl` | varies | 12 | +| `epoxy_skull-sdxl`, `ral-blueresin-sdxl`, `fractalex` | varies | 3-7 | + +Missing one isn't fatal, A1111 prints "couldn't find Lora" and carries on without it. The render still works, it just looks different. The three on every keyframe are the ones that matter most. + +**Heads up:** it's set to 15,000 frames, which is the full ~20-hour run. Drop `max_frames` to a few thousand for a first look. + +The recipe, and why (all covered in [`BEST_PRACTICES.txt`](BEST_PRACTICES.txt)): + +``` +steps 40, DPM++ 2M SDE / Karras, CFG 6 +strength 0.6, noise 0.01, cadence 5 +optical flow DIS Fine, color coherence LAB +midas 0.5, translation_z 2.5, FOV 80, seed 31415 +``` + +Strength 0.6 + noise 0.01 is the combination that survived an A/B test past 3,000 frames without degrading. LAB locks the palette so colour doesn't drift over a long render. Cadence 5 keeps it dense. + +--- + +## 3. `BEST_PRACTICES.txt` + +Every line came from a real render that either worked or failed: checkpoint behaviour, the exact settings that cause the "spaghetti line" streaking, the two proven smoothness recipes, camera/FOV rules, init images, prompt and LoRA practice. + +The viewer's **Best Practices** tab lays this out in two columns with a screenshot of the actual Deforum control each note is about, click any screenshot to see it full size. + +There's a **VELLO'S SECTION** at the bottom. Add yours and send it back and I'll merge it in. (The viewer's Best Practices tab has an Edit button that gives you a download for exactly that.) + +--- + +## 4. Opening the viewer from inside Stable Diffusion + +If you installed the Deforum extension, the Deforum tab has an **Open the render viewer** button. It opens this exact same `Microcosm.html` in a browser tab, the same file you can double-click on disk with Stable Diffusion closed. One viewer, reachable either way, so there's no second app to manage. + +`_build_gallery.py` (shipped alongside) is the generator that produces `Microcosm.html`: + +```bash +python _build_gallery.py --standalone # rebuild the single-file viewer +``` + +--- + +## Troubleshooting + +**Windows or the browser warns when opening the HTML**, expected. It's a local file containing JavaScript; the warning is generic. Nothing in it talks to the network. + +**Video shows a still but won't play**, the file's fine; some browsers are fussy with large local videos. Try Chrome or Edge. + +**Panel says "press play" and never fills**, that render has no matching `_settings.txt` (see name-matching above), or only the `.mp4` was dropped. + +**Page looks empty**, nothing's loaded yet. It ships with no renders inside; that's why it's 291 KB and not 40 GB. Drop something in. diff --git a/microcosm/_build_gallery.py b/microcosm/_build_gallery.py new file mode 100644 index 00000000..5b2b0b5b --- /dev/null +++ b/microcosm/_build_gallery.py @@ -0,0 +1,2493 @@ +r"""ONE master gallery combining both tools Brian likes: + - like _FOV_VIEWER: a LIVE panel synced to playback showing the prompt / LoRAs / FOV / camera changing + over time (bigger text, EACH on its own row). + - like _MASTER_RENDER_SHEET: every render as a vertical card with ALL settings listed below. +Scans the ENTIRE img2img-images tree (every render). De-dupes by filename and MOVES duplicates + known-bad +renders (rejected / short test partials) into _trash_review\ (not hard-deleted, per archive-before-delete). +Output: _MASTER_GALLERY.html +""" +import json, os, re, html, base64, subprocess, shutil, sys + +# --standalone: emit a SHAREABLE single-file viewer with NO local videos baked in (the real gallery +# points at 100s of GB of local mp4s, so it can't just be emailed). The standalone build is the same +# page with an empty grid - the recipient drags their OWN renders (+ settings.txt) onto it and gets +# the identical live prompt/LoRA/camera panel and side-by-side compare. One source of truth, no dupes. +STANDALONE = "--standalone" in sys.argv + +def _arg(flag, default=None): + """--flag=value or --flag value""" + for i, a in enumerate(sys.argv): + if a.startswith(flag + "="): return a.split("=", 1)[1] + if a == flag and i + 1 < len(sys.argv): return sys.argv[i + 1] + return default + +def _find_root(): + """Locate the Deforum output folder: --root, then DEFORUM_OUTPUT env, then the standard + A1111 layout relative to this script, then CWD. Keeps the repo usable on any machine.""" + c = _arg("--root") or os.environ.get("DEFORUM_OUTPUT") + if c: return c + here = os.path.dirname(os.path.abspath(__file__)) + for cand in (os.path.join(here, "outputs", "img2img-images"), + os.path.join(os.getcwd(), "outputs", "img2img-images")): + if os.path.isdir(cand): return cand + return os.getcwd() + +def _find_ffprobe(): + """--ffprobe, then FFPROBE env, then PATH. Falls back to bare name (probe just degrades).""" + c = _arg("--ffprobe") or os.environ.get("FFPROBE") + if c: return c + found = shutil.which("ffprobe") + return found or "ffprobe" + +ROOT = _find_root() +OUT = os.path.join(ROOT, "Deforum_Render_Viewer.html") if STANDALONE else os.path.join(ROOT, "_MASTER_GALLERY.html") +FFPROBE = _find_ffprobe() +TRASH = os.path.join(ROOT, "_trash_review") +EXCLUDE = {"INIT_IMAGES", "_render_queue", "_trash_review", "_deferred_old_batch", "_thumbs", + "_gallery_data", "_contact_sheet", "_contact_sheets", "_sheet", "_early", "_NEW_MOVIES", + "prompts from Vello"} + +# Baked-in snapshot of the notes (comments/flags/best practices) so the page shows them even when +# opened as a plain file. When served through the WebUI the live API takes over and edits persist +# to outputs/img2img-images/_gallery_data/gallery_notes.json. +def load_notes_snapshot(): + """Snapshot for the baked page. The STANDALONE build (the file that gets shared) ships the + Best Practices ONLY - per-render comments and deletion flags are private working notes about + renders the recipient doesn't even have, so they'd just show up as orphan entries in their + Saved tab. The local gallery keeps everything.""" + p = os.path.join(ROOT, "_gallery_data", "gallery_notes.json") + try: + with open(p, encoding="utf-8") as fh: + n = json.load(fh) + if STANDALONE: + return {"comments": {}, "flags": [], "best_practices": n.get("best_practices", "")} + return {"comments": n.get("comments", {}), "flags": n.get("flags", []), + "best_practices": n.get("best_practices", "")} + except Exception: + return {"comments": {}, "flags": [], "best_practices": ""} + +# Best Practices illustrations. Each note in BEST_PRACTICES.txt is about a specific Deforum +# control, so the section cards show a crop of that exact control - the way the Deforum docs do +# it. Inlined as data URIs so the shared single-file viewer stays offline and self-contained. +_HERE = os.path.dirname(os.path.abspath(__file__)) +BP_SHOT_DIR = next( + (d for d in (os.path.join(_HERE, "extensions", "deforum", "screenshots", "bp"), + os.path.join(_HERE, "screenshots", "bp")) + if os.path.isdir(d)), "") +BP_SHOTS = [ + ("CHECKPOINTS", "checkpoint", "Top of the page", "The checkpoint dropdown - this choice matters more than prompt wording."), + ("STREAK", "cadence", "Keyframes", "Cadence. Stay at 10 or under in 3D."), + ("STREAK", "strength", "Keyframes > Strength", "Strength schedule. 0.6 or under; hold it flat."), + ("SMOOTHNESS", "subtabs", "Keyframes", "Color coherence and optical flow live under the Coherence sub-tab."), + ("CAMERA", "animmode", "Keyframes", "Animation mode and Border mode. 2D + wrap for the fake-3D look."), + ("CAMERA", "motion", "Keyframes > Motion / Depth Warping & FOV", "Camera schedules. Animate these, not the image params."), + ("INIT", "init", "Init > Image Init", "Use init and Strength. This fork ticks Use init when you drop an image."), + ("PROMPTS", "prompts", "Prompts", "Keyframed prompts, frame number on the left."), + ("PROMPTS", "negative", "Prompts", "The one global negative box. Never bake negatives into keyframes."), +] + + +def load_bp_shots(): + out = [] + for key, fn, panel, cap in BP_SHOTS: + p = os.path.join(BP_SHOT_DIR, fn + ".png") + if not os.path.isfile(p): + continue + with open(p, "rb") as fh: + b64 = base64.b64encode(fh.read()).decode("ascii") + out.append({"key": key, "panel": panel, "cap": cap, + "src": "data:image/png;base64," + b64}) + return out + + +THUMBS = os.path.join(ROOT, "_thumbs") + + +def make_thumb(mp4, name, dur): + """One small poster JPEG per video, cached. preload='none' (the fix for the 111-request + storm) also means the browser never fetches a first frame - without a poster every card + is a blank gray box. Grab a frame ~10% in (frame 0 is often still the init image).""" + os.makedirs(THUMBS, exist_ok=True) + out = os.path.join(THUMBS, name + ".jpg") + if os.path.isfile(out) and os.path.getsize(out) > 1000: + return out + ffmpeg = os.path.join(os.path.dirname(FFPROBE), "ffmpeg.exe") + if not os.path.isfile(ffmpeg): + ffmpeg = shutil.which("ffmpeg") or "ffmpeg" + try: + seek = max(1.0, (dur or 60) * 0.10) + r = subprocess.run([ffmpeg, "-y", "-ss", f"{seek:.1f}", "-i", mp4, "-frames:v", "1", + "-vf", "scale=512:-2", "-q:v", "4", out], + capture_output=True, timeout=60) + if r.returncode == 0 and os.path.isfile(out) and os.path.getsize(out) > 1000: + return out + except Exception: + pass + return None +BAD_MARKERS = ("_rejected", "_short_tests", "_partials") + +def load(p): + for e in ("utf-8", "utf-8-sig"): + try: return json.load(open(p, encoding=e)) + except Exception: pass + return None + +def probe(mp4): + try: + out = subprocess.run([FFPROBE, "-v", "error", "-select_streams", "v:0", + "-show_entries", "stream=nb_frames,width,height", "-show_entries", "format=duration", + "-of", "json", mp4], capture_output=True, text=True, timeout=30) + j = json.loads(out.stdout or "{}"); st = (j.get("streams") or [{}])[0] + return float(j.get("format", {}).get("duration", 0) or 0), st.get("nb_frames") + except Exception: + return 0, None + +def first_expr(sched): + s = str(sched or ""); i, j = s.find("("), s.rfind(")") + return s[i+1:j].strip() if (i != -1 and j != -1 and j > i) else "0" + +def to_js(expr): + return re.sub(r"\b(sin|cos|tan|sqrt|abs)\(", r"Math.\1(", expr) + +def split_prompt(text): + loras = [n for n, w in re.findall(r"]+):([\d.]+)>", text or "") + if n != "add-detail-xl"] # ignore the always-present utility lora when diffing + scene = re.sub(r"]+>", "", text or ""); scene = re.split(r"--neg", scene)[0] + return re.sub(r"\s+", " ", scene).strip(), loras # loras is a LIST for JS diffing + +def parse_sched(s): + out = [[int(a), float(b)] for a, b in re.findall(r"(\d+)\s*:\s*\(?\s*([\d.]+)", str(s or ""))] + return out or [[0, 0.0]] + +# ---- full settings payload: EVERYTHING that can explain why one render looks different ---- +# Brian: "I can't tell why some suck and why some are good, because you're not showing me all the +# parameters and what changed between them." So every card carries its complete settings (minus +# noise keys that can never explain a visual difference), ordered so the levers come first. +SKIP_KEYS = {"prompts", "animation_prompts_positive", "animation_prompts_negative", "positive_prompts", + "init_sample", "image_path", "outdir", "init_image_box", "deforum_git_commit_id", + "sd_model_hash", "batch_name", "resume_from_timestring", "resume_timestring", + "override_settings_with_file", "custom_settings_file", "show_info_on_ui", "motion_preview_mode"} +PRIORITY = ["sd_model_name", "animation_mode", "max_frames", "W", "H", "fps", "steps", "sampler", "scheduler", + "cfg_scale", "cfg_scale_schedule", "strength_schedule", "noise_schedule", "noise_multiplier_schedule", + "diffusion_cadence", "optical_flow_cadence", "optical_flow_redo_generation", "cadence_flow_factor_schedule", + "redo_flow_factor_schedule", "color_coherence", "contrast_schedule", "amount_schedule", + "seed", "seed_behavior", "seed_schedule", + "fov_schedule", "near_schedule", "far_schedule", "midas_weight", "use_depth_warping", "depth_algorithm", + "translation_x", "translation_y", "translation_z", "rotation_3d_x", "rotation_3d_y", "rotation_3d_z", + "zoom", "angle", "enable_perspective_flip", "perspective_flip_fv", "perspective_flip_theta", + "perspective_flip_phi", "perspective_flip_gamma", + "use_init", "init_image", "strength_0_no_init", "use_looper", "init_images", "image_strength_schedule", + "blendFactorMax", "blendFactorSlope", "tweening_frames_schedule", "color_correction_factor", + "border", "sampling_mode", "padding_mode", "color_force_grayscale", "noise_type"] + +def fullify(d): + """Complete, ordered settings dict for a card. ControlNet keys are collapsed to a single + summary (they're ~100 keys of default noise unless actually enabled).""" + out = {} + cn_on = [k for k, v in d.items() if k.startswith("cn_") and "enabled" in k and v] + for k in PRIORITY: + if k in d and k not in SKIP_KEYS: + out[k] = d[k] + for k in sorted(d.keys()): + if k in out or k in SKIP_KEYS or k.startswith("cn_"): + continue + out[k] = d[k] + out["controlnet"] = f"{len(cn_on)} unit(s) enabled" if cn_on else "off" + # long path values -> basenames so columns stay readable + for k in ("init_image", "video_init_path", "video_mask_path", "mask_file", "soundtrack_path", + "color_coherence_image_path"): + if out.get(k): + out[k] = os.path.basename(str(out[k])) + if out.get("init_images"): + out["init_images"] = re.sub(r'"[^"]*[\\/]([^"\\/]+)"', r'"\1"', str(out["init_images"]))[:300] + return {k: ("" if v is None else v) for k, v in out.items()} + +def lora_counts(d): + """Which LoRAs this render actually uses, with keyframe counts - across ALL its prompts.""" + tally = {} + for v in (d.get("prompts", {}) or {}).values(): + for n, w in re.findall(r"]+):([\d.]+)>", str(v)): + key = f"{n} @{w}" + tally[key] = tally.get(key, 0) + 1 + return tally + +# ---- scan whole tree, collect mp4s (skipped entirely for the shareable standalone build) ---- +found = [] +if not STANDALONE: + for dp, dn, fn in os.walk(ROOT): + dn[:] = [d for d in dn if d not in EXCLUDE] + for f in fn: + if f.lower().endswith(".mp4"): + found.append(os.path.join(dp, f)) + +# de-dup by basename + move dups/bad to trash +os.makedirs(TRASH, exist_ok=True) +seen, keep, trashed = {}, [], 0 +def is_bad(p): return any(m in p.lower() for m in BAD_MARKERS) +# prefer the copy in +Master, else shortest path +found.sort(key=lambda p: (0 if "+master_deforum_renders" in p.lower() else 1, len(p))) +for p in found: + base = os.path.basename(p) + if is_bad(p): + try: shutil.move(p, os.path.join(TRASH, base)); trashed += 1 + except Exception: pass + continue + if base in seen: # duplicate filename -> trash this copy + try: shutil.move(p, os.path.join(TRASH, os.path.dirname(p).split(os.sep)[-1] + "__" + base)); trashed += 1 + except Exception: pass + continue + seen[base] = p; keep.append(p) + +keep.sort(key=lambda p: os.path.getmtime(p), reverse=True) + +CAM = [("FOV", "fov_schedule"), ("Zoom Z", "translation_z"), ("Pan X", "translation_x"), + ("Pan Y", "translation_y"), ("Rot X", "rotation_3d_x"), ("Rot Y", "rotation_3d_y"), ("Rot Z", "rotation_3d_z")] +SET_ROWS = [("Checkpoint","sd_model_name"),("Frames","max_frames"),("Cadence","diffusion_cadence"), + ("Steps","steps"),("CFG","cfg_scale_schedule"),("Strength","strength_schedule"),("Noise","noise_schedule"), + ("Midas","midas_weight"),("Color coherence","color_coherence"),("FOV schedule","fov_schedule"), + ("Speed Z","translation_z"),("Init image","init_image")] + +def sset(d, k): + v = d.get(k, "-") + if k == "init_image": return os.path.basename(str(v)) or "-" + return str(first_expr(v)) if ("schedule" in k or k == "translation_z") and "(" in str(v) else str(v) + +def experiment(d): + """One-line summary of what THIS render was testing / what makes it distinct.""" + p = [] + ck = str(d.get("sd_model_name", "")).replace(".safetensors", "") + p.append("MOHAWK" if "MOHAWK" in ck else ("RealVis" if "RealVis" in ck else (ck[:12] or "?"))) + # FOV + fs = str(d.get("fov_schedule", "")) + m = re.search(r"([\d.]+)\s*-\s*([\d.]+)\s*\*\s*cos", fs) + if m: + mid, amp = float(m.group(1)), float(m.group(2)) + per = re.search(r"t/(\d+)\)", fs) + secs = f", {round(int(per.group(1))/30)}s cycle" if per else "" # cos(2pi t/P) period = P frames + p.append(f"FOV sweep {round(mid-amp)}-{round(mid+amp)}{secs}") + else: + mm = re.search(r"\(\s*([\d.]+)\s*\)", fs) + p.append(f"FOV {mm.group(1)}" if mm else "no FOV anim") + # camera + tz, rz = str(d.get("translation_z", "")), str(d.get("rotation_3d_z", "")) + if "cos" in tz and "0.5-0.5*cos" in tz.replace(" ", "") + rz.replace(" ", ""): + p.append("FOV-coupled camera") + elif "cos" in tz and "sin" in rz: + p.append("FOV-coupled speed") + elif "sin" in rz and "+" in rz: + p.append("roller-coaster cam") + elif "sin" in str(d.get("translation_x", "")): + p.append("smooth sine cam") + # cadence / strength / midas if notable + cad = d.get("diffusion_cadence") + if cad not in (8, None): p.append(f"cadence {cad}") + st = first_expr(d.get("strength_schedule")) + try: + sv = float(re.findall(r"[\d.]+", st)[0]) + if abs(sv - 0.7) > 0.03: p.append(f"strength {sv}") + except Exception: pass + # Parseq-style multi-parameter animation: count how many native schedules actually oscillate (not flat) + PARSEQ_FIELDS = ["strength_schedule", "noise_schedule", "noise_multiplier_schedule", + "cfg_scale_schedule", "contrast_schedule", "antiblur_amount_schedule"] + animated = [k for k in PARSEQ_FIELDS if "sin" in str(d.get(k, "")) or "cos" in str(d.get(k, ""))] + if len(animated) >= 3: + p.append(f"Parseq-style ({len(animated)} params animated)") + # Looper: guide image swapped in mid-render + if d.get("use_looper"): + try: + n_loop = len(json.loads(d.get("init_images", "{}"))) + if n_loop > 1: p.append(f"Looper: {n_loop} guide-image swaps") + except Exception: + p.append("Looper enabled") + # scene diversity by SUBJECT DOMAIN (not text) so single-theme renders aren't mislabeled diverse + DOMAINS = { + "ocean/reef": ["coral","reef","fish","ocean","underwater","squid","octopus","jellyfish","wave","sea ","whale"], + "ice/aurora": ["aurora","glacier","ice","frost","snow","frozen","icicle"], + "space": ["galaxy","nebula","supernova","cosmic","star","milky way","void"], + "flowers": ["flower","rose","petal","lotus","tulip","lavender","sunflower","blossom","pistil"], + "waterfall": ["waterfall","rainbow"], + "desert": ["canyon","desert","dune","sandstone","mesa"], + "volcanic": ["lava","volcanic","obsidian","molten","ember"], + "butterfly": ["butterfly","butterflies","hummingbird"], + "forest/trees": ["tree","forest","autumn","bamboo","cherry","eucalyptus","canopy","leaves"], + "crystal": ["crystal","cavern","gem","quartz","amethyst"], + "jungle": ["jungle","mushroom","fern","fungus","mycelium","moss"], + "macabre": ["skeleton","bone","skull","eyeball","fractal eye","rose vine"], + "body/fungal-horror": ["skin","muscle","vein","sinew","hair","flesh","mold"], + "mountain/lake": ["mountain","alpine","koi","lake","mist"], + "storm/sky": ["storm","cloud","god ray","twilight"], + } + prompts = d.get("prompts", {}) or {} + from collections import Counter + tally = Counter() + for v in prompts.values(): + head = re.split(r",", v)[0].lower()[:45] # the PRIMARY subject of the scene + for dom, kws in DOMAINS.items(): + if any(k in head for k in kws): + tally[dom] += 1; break + else: + tally["other"] += 1 + if tally: + total = sum(tally.values()); top, topn = tally.most_common(1)[0] + ndom = len([d2 for d2, c in tally.items() if d2 != "other" and c >= 2]) + if topn / total > 0.55 and top != "other": + p.append(f"single-theme: {top} (samey)") + elif ndom >= 5: + p.append(f"DIVERSE ({ndom} subject-domains)") + return " · ".join(p) + +DATA = {} +cards = [] +for i, mp4 in enumerate(keep): + d = load(mp4[:-4] + "_settings.txt") + dur, nbf = probe(mp4) + rel = os.path.relpath(mp4, ROOT).replace("\\", "/") + name = os.path.basename(mp4)[:-4] + folder = os.path.dirname(rel) + pid = f"v{i}" + if d: + prompts = d.get("prompts", {}) or {} + ks = sorted(prompts, key=lambda x: int(x) if str(x).isdigit() else 0) + kf = [[int(k) if str(k).isdigit() else 0, *split_prompt(prompts[k])] for k in ks] + cam = {lab: {"js": to_js(first_expr(d.get(key))), "anim": ("t" in first_expr(d.get(key)))} for lab, key in CAM} + DATA[pid] = {"fps": d.get("fps", 30) or 30, "kf": kf, "cam": cam, "camlabels": [c[0] for c in CAM], + "strength": parse_sched(d.get("strength_schedule")), "noise": parse_sched(d.get("noise_schedule")), + "name": name, "full": fullify(d), "loras": lora_counts(d)} + exp = experiment(d) + else: + DATA[pid] = {"fps": 30, "kf": [], "cam": {}, "camlabels": [], "name": name, "full": {}, "loras": {}} + exp = "no settings.txt (older render)" + meta = f'{int(dur//60)}:{int(dur%60):02d} · {nbf or "?"} frames' + thumb = make_thumb(mp4, name, dur) + poster_attr = f' poster="{html.escape(os.path.relpath(thumb, ROOT).replace(chr(92), "/"))}"' if thumb else "" + # facets the toolbar filters on (derived once, in Python, so filtering is a cheap attr read) + ck_raw = str(d.get("sd_model_name", "")) if d else "" + ckpt = ("MOHAWK" if "MOHAWK" in ck_raw else "CyberRealistic" if "CyberRealistic" in ck_raw + else "RealVis" if "RealVis" in ck_raw else "Juggernaut" if "uggernaut" in ck_raw + else "epiCRealism" if "picrealism" in ck_raw.lower() else ("other" if ck_raw else "none")) + tags = [] + e_low = exp.lower() + for t, probe_s in [("roller", "roller-coaster"), ("fov-coupled", "fov-coupled"), ("fov-sweep", "fov sweep"), + ("parseq", "parseq-style"), ("looper", "looper:"), ("diverse", "diverse ("), + ("single-theme", "single-theme"), ("axis", "smooth sine cam")]: + if probe_s in e_low: tags.append(t) + if d and str(d.get("animation_mode", "3D")) == "2D": tags.append("2d-mode") + if not d: tags.append("no-settings") + # everything searchable in one lowercase blob: name, folder, checkpoint, tags, and prompt text + hay = " ".join([name, folder, ck_raw, " ".join(tags), exp, + " ".join((d.get("prompts", {}) or {}).values()) if d else ""]).lower() + cards.append(f'''
+
+ + + +
{html.escape(name)}
+
{html.escape(folder or 'root')} · {meta}
+
+
+
press play — live prompt, LoRAs and camera appear here
+
{exp}
+
+
+
+
''') + +# --------------------------------------------------------------------------------------------- +# PRESETS - 8 built-in recipes. Every one of these is a REAL setting-set that actually rendered on +# this project (verified against the on-disk settings files / the deforum skill), not invented: +# 1 Photoreal Master - the current best photoreal stack (CyberRealisticXL, camera-forward prompts) +# 2 Microcosm v2 - Brian's "best render ever", read straight from Microcosm_v2_BEST_EVER_settings.txt +# 3 Roller Coaster Cam - the curve-anticipating camera (yaw/pitch phase-LEAD the turn) +# 4 FOV Sweep Coupled - the signature dolly-zoom FOV sweep w/ FOV-coupled camera speed +# 5 Parseq Multi-Param - 6 native schedules animated on independent periods + Looper image swaps +# 6 Pure Axis Dolly - clean single-axis travel (horizontal), gentle pitch tip +# 7 Laffoley Time Machine - LAB colour-lock + Looper (skill Path 1: palette-consistent abstract) +# 8 Jungle Bioluminescent - DIS Fine optical flow + very low noise (skill Path 2: photoreal/evolving) +# Each is a settings OVERLAY: the fields that define the look. The viewer can merge one over a dropped +# render's full settings to emit a complete, Deforum-loadable settings.txt. +PRESETS = [ + {"name": "1 - Photoreal Master (CyberRealistic XL)", + "use": "Maximum photorealism. The current best stack: real-camera prompt language + CyberRealistic XL. Start here for anything that must not look like AI.", + "settings": { + "sd_model_name": "CyberRealisticXL_V9.0_FP16.safetensors", + "steps": 50, "cfg_scale": 7.5, "cfg_scale_schedule": "0: (7.5)", + "sampler": "DPM++ 2M SDE", "scheduler": "Karras", + "strength_schedule": "0: (0.55)", "noise_schedule": "0: (0.003)", + "diffusion_cadence": 6, "optical_flow_cadence": "DIS Fine", + "cadence_flow_factor_schedule": "0: (1.0)", + "near_schedule": "0: (200)", "sampling_mode": "bicubic", + "use_depth_warping": True, "midas_weight": 0.4, "color_coherence": "None", + "W": 1024, "H": 1024, "fps": 30}}, + + {"name": "2 - Microcosm v2 (best render ever)", + "use": "The gold standard for organic long-form morphing. Exact settings from the render Brian rated his best. LAB locks the palette; cadence 5 keeps it dense.", + "settings": { + "sd_model_name": "MOHAWK_v20.safetensors", + "steps": 40, "cfg_scale_schedule": "0: (6)", + "sampler": "DPM++ 2M SDE", "scheduler": "Karras", + "strength_schedule": "0: (0.6)", "noise_schedule": "0: (0.01)", + "noise_multiplier_schedule": "0: (1.0)", + "diffusion_cadence": 5, "optical_flow_cadence": "DIS Fine", + "color_coherence": "LAB", + "translation_z": "0: (2.5)", "midas_weight": 0.5, "seed": 31415, + "W": 1024, "H": 1024, "fps": 30}}, + + {"name": "3 - Roller Coaster Camera", + "use": "Fluid coaster flight that never sits level. Yaw/pitch phase-LEAD the translation so the camera looks INTO the curve before it turns - the anticipation that makes it feel like a real ride.", + "settings": { + "translation_z": "0: (1.9 + 1.1*sin(t/130) + 0.5*sin(t/47))", + "translation_x": "0: (0.45*sin(t/95) + 0.2*sin(t/38))", + "translation_y": "0: (0.4*sin(t/110 + 1.0) + 0.18*cos(t/44))", + "rotation_3d_z": "0: (0.14 + 0.5*sin(t/95 + 0.5) + 0.12*sin(t/33))", + "rotation_3d_y": "0: (0.04 + 0.13*sin(t/95 + 0.9))", + "rotation_3d_x": "0: (-0.03 + 0.1*sin(t/110 + 1.4))", + "fov_schedule": "0: (80-70*cos(2*3.14*t/900))", + "diffusion_cadence": 6, "strength_schedule": "0: (0.55)"}}, + + {"name": "4 - FOV Sweep + FOV-Coupled Camera", + "use": "The signature dolly-zoom look. FOV breathes 18-66 over 67s and the WHOLE camera is coupled in-phase to it, so it crawls when telephoto and opens up when wide. Z keeps moving (never fully stops).", + "settings": { + "fov_schedule": "0: (42-24*cos(2*3.14*t/2000))", + "translation_z": "0: (1.4*(0.55+0.45*(0.5-0.5*cos(2*3.14*t/2000))))", + "translation_x": "0: (0.28*sin(t/180)*(0.15+0.85*(0.5-0.5*cos(2*3.14*t/2000))))", + "translation_y": "0: (0.24*sin(t/210 + 1.0)*(0.15+0.85*(0.5-0.5*cos(2*3.14*t/2000))))", + "rotation_3d_z": "0: ((0.04 + 0.2*sin(t/160 + 0.5))*(0.15+0.85*(0.5-0.5*cos(2*3.14*t/2000))))", + "rotation_3d_y": "0: ((0.02 + 0.08*sin(t/180 + 0.9))*(0.15+0.85*(0.5-0.5*cos(2*3.14*t/2000))))", + "rotation_3d_x": "0: ((-0.01 + 0.05*sin(t/210 + 1.4))*(0.15+0.85*(0.5-0.5*cos(2*3.14*t/2000))))", + "diffusion_cadence": 6, "strength_schedule": "0: (0.55)"}}, + + {"name": "5 - Parseq-Style Multi-Param + Looper", + "use": "Parseq-like multi-track animation using Deforum's own native schedules: 6 params oscillating on DIFFERENT periods so they drift in/out of phase (not lockstep), plus Looper swapping the guide image every 600 frames.", + "settings": { + "strength_schedule": "0: (0.55 + 0.06*sin(2*3.14*t/1200))", + "noise_schedule": "0: (0.003 + 0.0015*sin(2*3.14*t/900 + 1.0))", + "noise_multiplier_schedule": "0: (1.0 + 0.15*sin(2*3.14*t/1500 + 0.4))", + "cfg_scale_schedule": "0: (7.5 + 1.0*sin(2*3.14*t/1800 + 0.8))", + "contrast_schedule": "0: (1.0 + 0.08*sin(2*3.14*t/2400 + 0.2))", + "antiblur_amount_schedule": "0: (0.02 + 0.02*sin(2*3.14*t/2000 + 1.2))", + "use_looper": True, + "image_strength_schedule": "0: (0.65)", "blendFactorMax": "0: (0.35)", + "blendFactorSlope": "0: (0.25)", "tweening_frames_schedule": "0: (20)", + "color_correction_factor": "0: (0.15 + 0.1*sin(2*3.14*t/1200))", + "diffusion_cadence": 6}}, + + {"name": "6 - Pure Axis Dolly (horizontal)", + "use": "Clean single-axis travel through the world - only sideways motion plus a slow pitch tip. Nothing else moves. Swap translation_x for _y to get the vertical version, or use only _z for a slow push/pull.", + "settings": { + "fov_schedule": "0: (45-25*cos(2*3.14*t/1800))", + "translation_x": "0: (1.3+0.5*sin(2*3.14*t/2100))", + "translation_y": "0: (0)", "translation_z": "0: (0)", + "rotation_3d_x": "0: (0.08*sin(2*3.14*t/1500))", + "rotation_3d_y": "0: (0)", "rotation_3d_z": "0: (0)", + "diffusion_cadence": 6, "strength_schedule": "0: (0.48)", + "noise_schedule": "0: (0.012)"}}, + + {"name": "7 - Laffoley Time Machine (LAB + Looper)", + "use": "Palette-locked abstract/psychedelic morphing. LAB pins the colour scheme to frame 1 so it never drifts across thousands of frames; Looper anchors the morph. Trade-off: one colour mood for the whole render.", + "settings": { + "color_coherence": "LAB", "use_looper": True, + "looper_imageStrength_schedule": "0:(0.75), 60:(0.5)", + "image_strength_schedule": "0: (0.75)", + "strength_schedule": "0: (0.55)", "noise_schedule": "0: (0.005)", + "diffusion_cadence": 6, "sampling_mode": "bicubic"}}, + + {"name": "8 - Jungle Bioluminescent (DIS Fine)", + "use": "Smooth AND colour-varied. Optical flow carries consistency instead of a locked palette, so prompts can fully shift colour/mood per scene. Best for photoreal / nature / evolving-story renders.", + "settings": { + "color_coherence": "None", + "optical_flow_cadence": "DIS Fine", "optical_flow_redo_generation": "DIS Fine", + "cadence_flow_factor_schedule": "0: (1.0)", "redo_flow_factor_schedule": "0: (1.0)", + "noise_schedule": "0: (0.003)", "strength_schedule": "0: (0.55)", + "diffusion_cadence": 6, "midas_weight": 0.4, + "near_schedule": "0: (200)", "sampling_mode": "bicubic"}}, +] + +EXTRA_CSS = r""" +/* ============ real tabs - ONE source of truth for which page is visible ============ + Replaces two earlier collapsible-panel systems (an outer show/hide wrapper toggled by a + panelbar button, and an inner open/closed accordion toggled by the panel's own header) that + were left stacked on top of each other and could desync: clicking the two independent + controls could land the panel in a state where the outer wrapper was hidden while the inner + content reported open, so clicks stopped visibly doing anything. Repro'd live: 8+8 alternating + clicks -> outer .show=false, inner .open=true, panel invisible despite "open" state - the + frantic re-clicking that produces was mistaken for the page hanging. Fixed by deleting both + old systems and using exactly one [hidden] attribute per tab page, nothing else. */ +.tabbar{display:flex;gap:6px;align-items:center;margin:0 16px 12px;max-width:calc(100vw - 36px); + border-bottom:1px solid var(--line);padding-bottom:0} +.tabbtn{background:transparent;border:1px solid transparent;border-bottom:none;color:var(--ink-3); + font-size:13px;font-weight:600;padding:8px 16px;border-radius:8px 8px 0 0;cursor:pointer; + position:relative;top:1px} +.tabbtn:hover{color:var(--ink-2)} +.tabbtn.active{color:var(--ink);background:var(--surface);border-color:var(--line); + border-bottom:1px solid var(--surface)} +.tabbtn .tabcount{color:var(--ink-3);font-family:var(--mono);font-size:11px;margin-left:5px} +.tabpage[hidden]{display:none} +/* drop zone is a persistent, always-visible BOX (Brian: "it needs a box") - not hidden until + a drag starts. It gains an active-drag highlight but is never invisible. */ +.dropzone{margin:0 16px 16px;padding:22px 18px;border:2px dashed var(--line-2);border-radius:var(--r); + color:var(--ink-3);font-size:13px;text-align:center;line-height:1.6;transition:all .15s var(--ease); + max-width:calc(100vw - 36px)} +.dropzone b{color:var(--ink-2)} +.dropzone.drag{border-color:var(--accent);border-style:solid;background:oklch(0.24 0.05 240 / 0.25);color:var(--ink)} +.dzbtn{background:var(--surface-2);border:1px solid var(--line-2);color:var(--ink-2);border-radius:var(--r-sm); + padding:5px 14px;font-size:12.5px;cursor:pointer;margin:0 3px} +.dzbtn:hover{color:var(--ink);border-color:var(--accent)} +.dzlib{margin-top:9px;font-family:var(--mono);font-size:11.5px;color:var(--ink-3)} +.dzstatus{margin-top:8px;font-size:12.5px;line-height:1.5;color:var(--ink-3);max-width:70ch; + margin-left:auto;margin-right:auto} +.dzstatus.err{color:#ffc9c9} +.dzlib b{color:var(--ink-2);font-weight:600} +/* folders bar - the selectable paths, at the very top of the Gallery tab */ +/* the author display:flex below outranks the UA [hidden] rule, so state it explicitly - + without this the server-only folder bar shows up in the shared offline viewer, where + Browse/Save/Rescan have no API to talk to (same trap .fb-ov[hidden] already guards) */ +.dirbar[hidden]{display:none} +.dirbar{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin:0 16px 12px; + background:var(--surface);border:1px solid var(--line);border-radius:var(--r); + padding:10px 14px;max-width:calc(100vw - 36px)} +.dirbar .dbt{font-size:12px;font-weight:650;color:var(--ink);letter-spacing:.02em} +.dirbar label{display:flex;align-items:center;gap:6px;font-size:11.5px;color:var(--ink-3);white-space:nowrap} +.dirbar input{background:var(--bg);border:1px solid var(--line);border-radius:var(--r-sm); + color:var(--ink-2);font-family:var(--mono);font-size:11.5px;padding:5px 8px;width:230px} +.dirbar input:focus{outline:2px solid var(--accent);outline-offset:1px} +.dirstatus{font-size:11.5px;color:var(--ink-3);font-family:var(--mono)} +.dirstatus.err{color:var(--warn)} +/* top row: just the view/compare drop zone (input-folder settings live in the Deforum panel now) */ +.dzrow{display:flex;gap:10px;align-items:stretch;margin:0 16px 14px;max-width:calc(100vw - 36px)} +.dzrow .dropzone{margin:0;flex:1;max-width:none} +.fstat{font-family:var(--mono);font-size:11px;color:var(--ink-3)} +.fstat.ok{color:var(--good)} .fstat.err{color:var(--warn)} +/* server-side folder browser popup */ +.fb-ov{position:fixed;inset:0;z-index:40;background:oklch(0.1 0.01 265 / 0.6);display:flex; + align-items:center;justify-content:center} +.fb-ov[hidden]{display:none} +.fb-panel{width:560px;max-width:92vw;max-height:78vh;background:var(--surface);border:1px solid var(--line-2); + border-radius:var(--r);display:flex;flex-direction:column;overflow:hidden} +.fb-head{display:flex;align-items:center;gap:10px;padding:10px 14px;border-bottom:1px solid var(--line)} +.fb-head span{font-family:var(--mono);font-size:12px;color:var(--ink);flex:1;word-break:break-all} +.fb-list{overflow:auto;flex:1;padding:6px 8px} +.fb-list .fb-item{display:block;width:100%;text-align:left;background:transparent;border:0; + color:var(--ink-2);font-family:var(--mono);font-size:12.5px;padding:6px 9px;border-radius:var(--r-sm);cursor:pointer} +.fb-list .fb-item:hover{background:var(--surface-2);color:var(--ink)} +.fb-foot{display:flex;gap:10px;align-items:center;padding:10px 14px;border-top:1px solid var(--line)} +/* ---- view modes: one giant row (default) / definable grid / full-width rows ---- */ +body.gridmode .grid{display:grid;grid-template-columns:repeat(var(--gcols,4),minmax(0,1fr));gap:14px;min-width:0} +body.gridmode .grid>.card{width:auto;flex:none} +body.listrows .grid{display:block;min-width:0} +body.listrows .grid>.card{display:grid;width:auto;flex:none;margin-bottom:14px; + grid-template-columns:minmax(280px,360px) minmax(300px,400px) minmax(240px,1fr) minmax(340px,1.7fr); + gap:4px 18px} +body.listrows .grid>.card .chead{grid-column:1;grid-row:1} +body.listrows .grid>.card .vidbox{grid-column:1;grid-row:2/7} +body.listrows .grid>.card .live{grid-column:2;grid-row:1/7} +body.listrows .grid>.card .exp{grid-column:3;grid-row:1;margin-top:0} +body.listrows .grid>.card .lorachips{grid-column:3;grid-row:2} +body.listrows .grid>.card .cmts{grid-column:3;grid-row:3} +body.listrows .grid>.card .setfill{grid-column:4;grid-row:1/7;column-count:2;column-gap:26px} +@media (min-width:2400px){body.listrows .grid>.card .setfill{column-count:3}} +/* Best Practices as an illustrated two-column document, not a text dump. Each section shows the + actual Deforum control it's about, the way the Deforum docs do it. column-count + break-inside + keeps a section card whole instead of splitting it across the column gutter. */ +.bpdoc{column-count:2;column-gap:20px} +@media (max-width:1100px){.bpdoc{column-count:1}} +@media (min-width:2200px){.bpdoc{column-count:3}} +.bptitle{font-size:15px;font-weight:650;color:var(--ink);margin:0 0 3px} +.bpsub{color:var(--ink-3);font-size:12px;margin:0} +.bpintro{margin:0 0 12px;break-inside:avoid;-webkit-column-break-inside:avoid} +.bpsec{background:var(--surface);border:1px solid var(--line);border-radius:var(--r); + padding:11px 14px;margin:0 0 10px;break-inside:avoid;-webkit-column-break-inside:avoid} +.bpsec h2{margin:0 0 7px;font-size:11px;letter-spacing:.08em;color:var(--accent); + text-transform:uppercase;font-family:var(--mono);font-weight:650} +.bpsec ul{margin:0;padding-left:16px} +.bpsec li{font-size:12.5px;line-height:1.55;color:var(--ink-2);margin:4px 0} +.bpsec li::marker{color:var(--accent)} +.bpsec p{font-size:12.5px;line-height:1.5;color:var(--ink-2);margin:5px 0} +/* reference-sized, not full-size - the whole document is meant to fit on a screen. + Click a shot to blow it up to full size and read the labels, click again to shrink. */ +.bpfig{margin:8px 0 0;max-width:460px;border:1px solid var(--line);border-radius:7px; + overflow:hidden;background:#0d0d14;cursor:zoom-in} +/* full-size overlay - inside a column a "big" image is still only column-wide, which is + too small to read the Deforum labels */ +#bplightbox{position:fixed;inset:0;z-index:400;background:rgba(0,0,0,.86);display:none; + align-items:center;justify-content:center;padding:24px;cursor:zoom-out} +#bplightbox.on{display:flex} +#bplightbox img{max-width:100%;max-height:88vh;width:auto;border:1px solid var(--line);border-radius:8px} +.bpfig img{display:block;width:100%;height:auto} +.bpfig figcaption{font-size:10.5px;line-height:1.45;color:var(--ink-3);padding:5px 8px; + border-top:1px solid var(--line);background:rgba(255,255,255,.02)} +.bpfig figcaption b{color:var(--accent);font-family:var(--mono);font-weight:650;letter-spacing:.03em} +.bpedithint{color:var(--ink-3);font-size:11.5px;margin-top:7px;font-family:var(--mono)} +.comparewrap{display:none;margin:0 16px 20px;padding:14px;background:#12121a;border:1px solid #2a2a38;border-radius:10px} +.cwhead{display:flex;align-items:center;gap:14px;margin-bottom:10px;flex-wrap:wrap} +.cwhead h2{margin:0;font-size:15px;color:#eaeaf2} +.cwhead label{font-size:13px;color:#cdd} +.cwhead button{background:#3a1e1e;color:#ffb0b0;border:1px solid #5a2a2a;border-radius:6px;padding:5px 12px;cursor:pointer;font-size:12px} +.comparerow{display:flex;gap:16px;flex-wrap:wrap;align-items:flex-start} +.comparerow .card{width:calc(50% - 8px);min-width:380px;flex:1 1 420px} +.dropcard{position:relative} +.rmbtn{position:absolute;top:10px;right:10px;z-index:2;background:#2a2a3a;color:#cdd;border:1px solid #363648;border-radius:5px;padding:3px 9px;cursor:pointer;font-size:11px} +.savepreset{position:absolute;top:10px;right:74px;z-index:2;background:#12301c;color:#8fff af;border:1px solid #2a5a38;border-radius:5px;padding:3px 9px;cursor:pointer;font-size:11px} +.presetnote{color:#7a9;font-size:12.5px;margin:0 16px 12px;line-height:1.5;max-width:90ch} +.pgrid{display:flex;flex-wrap:wrap;gap:12px;margin:0 16px} +.pcard{background:#181820;border:1px solid #2a2a38;border-radius:8px;padding:11px;width:340px;display:flex;flex-direction:column} +.pcard.custom{border-color:#2a5a38} +.pcard h3{margin:0 0 5px;font-size:13px;color:#ffcf80;font-family:monospace} +.pcard .puse{color:#aab;font-size:12px;line-height:1.45;margin-bottom:8px} +.pcard .prows{background:#0c1622;border:1px solid #1d3350;border-radius:5px;padding:7px 8px;margin-bottom:9px;max-height:150px;overflow:auto} +.prow{display:flex;justify-content:space-between;gap:8px;font-family:monospace;font-size:11px;padding:1px 0} +.prow .pk{color:#5cc0ff;white-space:nowrap} +.prow .pv{color:#e0e0e8;text-align:right;word-break:break-all} +.pbtns{display:flex;gap:6px;flex-wrap:wrap;margin-top:auto} +.pbtns button{background:#2a2a3a;color:#cdd;border:1px solid #363648;border-radius:5px;padding:5px 9px;cursor:pointer;font-size:11px} +.pbtns button.primary{background:#123049;color:#bfe0ff;border-color:#1d4a70} +.pbtns button.danger{background:#3a1e1e;color:#ffb0b0;border-color:#5a2a2a} +.pnote{color:#7a9;font-size:12px;margin:0 16px 12px;line-height:1.5;max-width:90ch} +""" + +# Split so the (later-defined) video cards can be injected INSIDE the gallery tabpage - the whole +# point of real tabs is that switching away actually excludes the 44k-node grid from layout via +# [hidden], which only works if the grid lives inside the tabpage element. +EXTRA_HTML_HEAD = """
+ + + + +
+ + + + + + + + + +
+ + + + tick "compare" on the renders you want, like picking TVs at Best Buy +
+
+
+

Compare

+ + + +
+
+
""" + +EXTRA_JS = r""" +var CAM_JS=[["FOV","fov_schedule"],["Zoom Z","translation_z"],["Pan X","translation_x"],["Pan Y","translation_y"],["Rot X","rotation_3d_x"],["Rot Y","rotation_3d_y"],["Rot Z","rotation_3d_z"]]; +var SET_ROWS_JS=[["Checkpoint","sd_model_name"],["Frames","max_frames"],["Cadence","diffusion_cadence"],["Steps","steps"],["CFG","cfg_scale_schedule"],["Strength","strength_schedule"],["Noise","noise_schedule"],["Midas","midas_weight"],["Color coherence","color_coherence"],["FOV schedule","fov_schedule"],["Speed Z","translation_z"],["Init image","init_image"]]; + +function firstExprJS(sched){ + var s=String(sched==null?'':sched); var i=s.indexOf('('), j=s.lastIndexOf(')'); + return (i!==-1 && j!==-1 && j>i) ? s.slice(i+1,j).trim() : '0'; +} + +// Hand-rolled recursive-descent parser/evaluator for the tiny math-schedule language +// (numbers, t, + - * /, parens, sin/cos/tan/sqrt/abs). No eval / no Function() - dropped +// settings files are the least-trusted input on this page, so their expressions are +// walked as data instead of being turned into executable code. +function tokenizeExpr(s){ + var toks=[]; var i=0; var n=s.length; + while(i]+):([\d.]+)>/g; + Array.from(text.matchAll(reLora)).forEach(function(m){ if(m[1]!=='add-detail-xl') loras.push(m[1]); }); + var scene = text.replace(/]+>/g,''); scene = scene.split('--neg')[0]; + scene = scene.replace(/\s+/g,' ').trim(); + return [scene, loras]; +} +function parseSchedJS(s){ + var str=String(s==null?'':s); + var reSched=/(\d+)\s*:\s*\(?\s*([\d.]+)/g; + var out=Array.from(str.matchAll(reSched)).map(function(m){ return [parseInt(m[1]),parseFloat(m[2])]; }); + return out.length?out:[[0,0.0]]; +} +function ssetJS(d,key){ + var v=(d[key]!==undefined && d[key]!==null)?d[key]:'-'; + if(key==='init_image'){ var s=String(v||''); var parts=s.split(/[\\/]/); return parts[parts.length-1]||'-'; } + var vs=String(v); + if((key.indexOf('schedule')!==-1 || key==='translation_z') && vs.indexOf('(')!==-1) return String(firstExprJS(v)); + return vs; +} +function experimentJS(d){ + var p=[]; + var ck=String(d.sd_model_name||'').replace('.safetensors',''); + if(ck.indexOf('MOHAWK')!==-1)p.push('MOHAWK'); + else if(ck.indexOf('CyberRealistic')!==-1)p.push('CyberRealisticXL'); + else if(ck.indexOf('RealVis')!==-1)p.push('RealVis'); + else p.push(ck.slice(0,12)||'?'); + var fs=String(d.fov_schedule||''); + var m=fs.match(/([\d.]+)\s*-\s*([\d.]+)\s*\*\s*cos/); + if(m){ + var mid=parseFloat(m[1]), amp=parseFloat(m[2]); + var per=fs.match(/t\/(\d+)\)/); + var secs=per?(', '+Math.round(parseInt(per[1])/30)+'s cycle'):''; + p.push('FOV sweep '+Math.round(mid-amp)+'-'+Math.round(mid+amp)+secs); + } else { + var mm=fs.match(/\(\s*([\d.]+)\s*\)/); + p.push(mm?('FOV '+mm[1]):'no FOV anim'); + } + var tz=String(d.translation_z||''), rz=String(d.rotation_3d_z||''); + if(tz.indexOf('cos')!==-1 && (tz.replace(/\s/g,'')+rz.replace(/\s/g,'')).indexOf('0.5-0.5*cos')!==-1) p.push('FOV-coupled camera'); + else if(tz.indexOf('cos')!==-1 && rz.indexOf('sin')!==-1) p.push('FOV-coupled speed'); + else if(rz.indexOf('sin')!==-1 && rz.indexOf('+')!==-1) p.push('roller-coaster cam'); + else if(String(d.translation_x||'').indexOf('sin')!==-1) p.push('smooth sine cam'); + var cad=d.diffusion_cadence; + if(cad!==8 && cad!==undefined && cad!==null) p.push('cadence '+cad); + var stv=firstExprJS(d.strength_schedule); + var svm=String(stv).match(/[\d.]+/); + if(svm){ var sv=parseFloat(svm[0]); if(Math.abs(sv-0.7)>0.03) p.push('strength '+sv); } + var PARSEQ_FIELDS=["strength_schedule","noise_schedule","noise_multiplier_schedule","cfg_scale_schedule","contrast_schedule","antiblur_amount_schedule"]; + var animated=PARSEQ_FIELDS.filter(function(k){ var v=String(d[k]||''); return v.indexOf('sin')!==-1||v.indexOf('cos')!==-1; }); + if(animated.length>=3) p.push('Parseq-style ('+animated.length+' params animated)'); + if(d.use_looper){ + try{ var nLoop=Object.keys(JSON.parse(d.init_images||'{}')).length; if(nLoop>1) p.push('Looper: '+nLoop+' guide-image swaps'); } + catch(e){ p.push('Looper enabled'); } + } + var DOMAINS={ + "ocean/reef":["coral","reef","fish","ocean","underwater","squid","octopus","jellyfish","wave","sea ","whale"], + "ice/aurora":["aurora","glacier","ice","frost","snow","frozen","icicle"], + "space":["galaxy","nebula","supernova","cosmic","star","milky way","void"], + "flowers":["flower","rose","petal","lotus","tulip","lavender","sunflower","blossom","pistil"], + "waterfall":["waterfall","rainbow"], + "desert":["canyon","desert","dune","sandstone","mesa"], + "volcanic":["lava","volcanic","obsidian","molten","ember"], + "butterfly":["butterfly","butterflies","hummingbird"], + "forest/trees":["tree","forest","autumn","bamboo","cherry","eucalyptus","canopy","leaves"], + "crystal":["crystal","cavern","gem","quartz","amethyst"], + "jungle":["jungle","mushroom","fern","fungus","mycelium","moss"], + "macabre":["skeleton","bone","skull","eyeball","fractal eye","rose vine"], + "body/fungal-horror":["skin","muscle","vein","sinew","hair","flesh","mold"], + "mountain/lake":["mountain","alpine","koi","lake","mist"], + "storm/sky":["storm","cloud","god ray","twilight"] + }; + var prompts=d.prompts||{}; + var tally={}; + Object.keys(prompts).forEach(function(k){ + var v=String(prompts[k]||''); + var head=v.split(',')[0].toLowerCase().slice(0,45); + var matched=false; + for(var dom in DOMAINS){ + if(DOMAINS[dom].some(function(kw){return head.indexOf(kw)!==-1;})){ tally[dom]=(tally[dom]||0)+1; matched=true; break; } + } + if(!matched) tally['other']=(tally['other']||0)+1; + }); + var keys=Object.keys(tally); + if(keys.length){ + var total=0; keys.forEach(function(k){total+=tally[k];}); + var top=null, topn=0; + keys.forEach(function(k){ if(tally[k]>topn){topn=tally[k];top=k;} }); + var ndom=keys.filter(function(k){return k!=='other'&&tally[k]>=2;}).length; + if(top && topn/total>0.55 && top!=='other') p.push('single-theme: '+top+' (samey)'); + else if(ndom>=5) p.push('DIVERSE ('+ndom+' subject-domains)'); + } + return p.join(' · '); +} + +var dropped=[]; +var dropSeq=0; + +/* JS mirrors of the Python fullify/lora_counts so DROPPED renders get the same full column, + uncommon-value marking, and compare support as library renders */ +var SKIP_JS={prompts:1,animation_prompts_positive:1,animation_prompts_negative:1,positive_prompts:1, + init_sample:1,image_path:1,outdir:1,init_image_box:1,deforum_git_commit_id:1,sd_model_hash:1, + batch_name:1,resume_from_timestring:1,resume_timestring:1,override_settings_with_file:1, + custom_settings_file:1,show_info_on_ui:1,motion_preview_mode:1}; +function fullifyJS(d){ + var out={}, prio=[]; + SGROUPS.forEach(function(g){ prio=prio.concat(g[1]); }); + var cnOn=Object.keys(d).filter(function(k){ return k.indexOf('cn_')===0 && k.indexOf('enabled')!==-1 && d[k]; }); + prio.forEach(function(k){ if(k in d && !SKIP_JS[k]) out[k]=d[k]; }); + Object.keys(d).sort().forEach(function(k){ + if(k in out || SKIP_JS[k] || k.indexOf('cn_')===0) return; + out[k]=d[k]; + }); + out['controlnet']=cnOn.length? cnOn.length+' unit(s) enabled':'off'; + ['init_image','video_init_path','video_mask_path','mask_file','soundtrack_path','color_coherence_image_path'].forEach(function(k){ + if(out[k]){ var s=String(out[k]).split(/[\\/]/); out[k]=s[s.length-1]; } + }); + if(out['init_images']) out['init_images']=String(out['init_images']).slice(0,300); + for(var k in out){ if(out[k]===null||out[k]===undefined) out[k]=''; } + return out; +} +function loraCountsJS(d){ + var t={}, prompts=d.prompts||{}; + Object.keys(prompts).forEach(function(k){ + Array.from(String(prompts[k]).matchAll(/]+):([\d.]+)>/g)).forEach(function(m){ + var key=m[1]+' @'+m[2]; t[key]=(t[key]||0)+1; + }); + }); + return t; +} + +function registerDataJS(pid,d){ + if(!d){ DATA[pid]={fps:30,kf:[],cam:{},camlabels:[],name:pid,full:{},loras:{}}; camFns[pid]={}; return; } + var prompts=d.prompts||{}; + var ks=Object.keys(prompts).sort(function(a,b){return (parseInt(a)||0)-(parseInt(b)||0);}); + var kf=ks.map(function(k){ var sp=splitPromptJS(prompts[k]); return [parseInt(k)||0, sp[0], sp[1]]; }); + var cam={}; + CAM_JS.forEach(function(pair){ + var lab=pair[0], key=pair[1]; + var ex=firstExprJS(d[key]); + cam[lab]={js:ex, anim: ex.indexOf('t')!==-1}; + }); + DATA[pid]={fps:d.fps||30, kf:kf, cam:cam, camlabels:CAM_JS.map(function(p){return p[0];}), + strength:parseSchedJS(d.strength_schedule), noise:parseSchedJS(d.noise_schedule), + name:pid, full:fullifyJS(d), loras:loraCountsJS(d)}; + camFns[pid]={}; + for(var lab in cam){ camFns[pid][lab]=compileExpr(cam[lab].js); } +} + +/* Only these ever matter. A Deforum output folder also holds thousands of PNG frames; turning + every one into a File object took long enough to look like the page had ignored the drop. */ +function dropWanted(name){ return /\.(mp4|txt|json)$/i.test(name); } +function getAllFileEntries(dataTransferItemList){ + return new Promise(function(resolve){ + var items=[]; + for(var i=0;i6){ cb(); return; } + var reader=entry.createReader(); + var all=[]; + (function readBatch(){ + reader.readEntries(function(results){ + if(!results.length){ + var kids=all.filter(function(e2){ return e2.isDirectory || dropWanted(e2.name); }); + var sub=kids.length; + if(!sub){ cb(); return; } + kids.forEach(function(e2){ readEntry(e2, function(){ sub--; if(sub<=0) cb(); }, depth+1); }); + } else { all=all.concat(results); readBatch(); } + }, cb); + })(); + } else { cb(); } + } + }); +} + +async function handleDropFiles(files){ + var videos=files.filter(function(f){return /\.mp4$/i.test(f.name);}); + var texts=files.filter(function(f){return /\.(txt|json)$/i.test(f.name);}); + if(!videos.length){ alert("No .mp4 video found in what you dropped. Drop a rendered video (optionally with its _settings.txt), or a folder containing one."); return; } + if(videos.length>12){ + if(!confirm("Found "+videos.length+" videos in that drop - load the first 12?")) return; + videos=videos.slice(0,12); + } + for(var vi=0; vi=2?' · Compare Mode':''); + head.appendChild(h2); + if(dropped.length>=2){ + var lbl=document.createElement('label'); + var chk=document.createElement('input'); chk.type='checkbox'; chk.id='synclink'; chk.checked=true; + lbl.appendChild(chk); lbl.appendChild(document.createTextNode(' sync playback')); + head.appendChild(lbl); + } + var clearBtn=document.createElement('button'); clearBtn.textContent='clear dropped'; + clearBtn.addEventListener('click', clearDropped); + head.appendChild(clearBtn); + wrap.appendChild(head); + + var row=document.createElement('div'); row.className = dropped.length>=2 ? 'comparerow' : 'grid'; + dropped.forEach(function(item){ row.appendChild(buildDropCardEl(item)); }); + wrap.appendChild(row); + + dropped.forEach(function(item){ + var v=document.getElementById(item.pid); + if(!v) return; + ['timeupdate','seeked'].forEach(function(e){ v.addEventListener(e,function(){ upd(v); syncFrom(v); }); }); + v.addEventListener('play',function(){ upd(v); syncPlay(v,true); }); + v.addEventListener('pause',function(){ syncPlay(v,false); }); + }); + if(typeof buildFreq==='function'){ buildFreq(); dropped.forEach(function(item){ renderColumn(item.pid); }); attachChecks(wrap); } + if(typeof applyFilter==='function') applyFilter(); // refresh the "N of N renders" count +} + +var syncing=false; +function syncFrom(v){ + var chk=document.getElementById('synclink'); + if(!chk || !chk.checked || dropped.length<2 || syncing) return; + syncing=true; + var frac = v.duration? v.currentTime/v.duration : 0; + dropped.forEach(function(item){ + if(item.pid===v.dataset.pid) return; + var ov=document.getElementById(item.pid); + if(ov && ov.duration){ var target=frac*ov.duration; if(Math.abs(ov.currentTime-target)>0.15) ov.currentTime=target; } + }); + syncing=false; +} +function syncPlay(v,playing){ + var chk=document.getElementById('synclink'); + if(!chk || !chk.checked || dropped.length<2) return; + dropped.forEach(function(item){ + if(item.pid===v.dataset.pid) return; + var ov=document.getElementById(item.pid); + if(!ov) return; + if(playing && ov.paused) ov.play().catch(function(){}); + if(!playing && !ov.paused) ov.pause(); + }); +} +function removeDropped(pid){ + dropped=dropped.filter(function(item){ + if(item.pid===pid){ URL.revokeObjectURL(item.url); delete DATA[pid]; delete camFns[pid]; return false; } + return true; + }); + if(typeof selOrder!=='undefined'){ selOrder=selOrder.filter(function(p){ return p!==pid; }); selUpdate(); } + renderCompare(); renderPresets(); +} +function clearDropped(){ + dropped.forEach(function(item){ + URL.revokeObjectURL(item.url); delete DATA[item.pid]; delete camFns[item.pid]; + if(typeof selOrder!=='undefined') selOrder=selOrder.filter(function(p){ return p!==item.pid; }); + }); + dropped=[]; + if(typeof selUpdate==='function') selUpdate(); + renderCompare(); renderPresets(); +} + +// ============================== PRESETS ============================== +// BUILTIN_PRESETS is injected from Python. Custom presets persist in localStorage so a preset you +// save from a good render survives page reloads. Everything stays local - nothing is uploaded. +var LS_KEY='deforum_viewer_custom_presets_v1'; +// The fields that actually define a "look" - what gets captured when you save a render as a preset. +var PRESET_FIELDS=["sd_model_name","steps","cfg_scale","cfg_scale_schedule","sampler","scheduler", + "strength_schedule","noise_schedule","noise_multiplier_schedule","diffusion_cadence", + "optical_flow_cadence","optical_flow_redo_generation","cadence_flow_factor_schedule", + "redo_flow_factor_schedule","color_coherence","contrast_schedule","antiblur_amount_schedule", + "fov_schedule","near_schedule","translation_x","translation_y","translation_z", + "rotation_3d_x","rotation_3d_y","rotation_3d_z","midas_weight","use_depth_warping","sampling_mode", + "use_looper","image_strength_schedule","blendFactorMax","blendFactorSlope", + "tweening_frames_schedule","color_correction_factor","W","H","fps","seed"]; + +function loadCustomPresets(){ + try{ var raw=localStorage.getItem(LS_KEY); return raw?JSON.parse(raw):[]; }catch(e){ return []; } +} +function saveCustomPresets(list){ + try{ localStorage.setItem(LS_KEY, JSON.stringify(list)); return true; } + catch(e){ alert('Could not save preset: '+e.message); return false; } +} +function downloadJSON(obj, filename){ + var blob=new Blob([JSON.stringify(obj,null,4)],{type:'application/json'}); + var url=URL.createObjectURL(blob); + var a=document.createElement('a'); a.href=url; a.download=filename; + document.body.appendChild(a); a.click(); document.body.removeChild(a); + setTimeout(function(){ URL.revokeObjectURL(url); }, 1000); +} +// Merge a preset OVER a dropped render's FULL settings -> a complete, Deforum-loadable settings.txt. +// Without a dropped render we can only emit the overlay itself (documented in the UI + README). +function presetDownload(p){ + var full=null; + for(var i=0;i=list.length) return; + if(!confirm('Delete preset "'+list[idx].name+'"?')) return; + list.splice(idx,1); saveCustomPresets(list); renderPresets(); +} +function buildPresetCard(p, customIdx){ + var card=document.createElement('div'); card.className='pcard'+(p.custom?' custom':''); + var h=document.createElement('h3'); h.textContent=p.name; card.appendChild(h); + var u=document.createElement('div'); u.className='puse'; u.textContent=p.use||''; card.appendChild(u); + var rows=document.createElement('div'); rows.className='prows'; + Object.keys(p.settings).forEach(function(k){ + var r=document.createElement('div'); r.className='prow'; + var kk=document.createElement('span'); kk.className='pk'; kk.textContent=k; + var vv=document.createElement('span'); vv.className='pv'; vv.textContent=String(p.settings[k]); + r.appendChild(kk); r.appendChild(vv); rows.appendChild(r); + }); + card.appendChild(rows); + var btns=document.createElement('div'); btns.className='pbtns'; + var dl=document.createElement('button'); dl.className='primary'; + dl.textContent = 'Download'; + dl.title = presetHasFullBase() + ? 'Merges this preset over your dropped render\'s full settings -> a complete file you can Load All Settings in Deforum.' + : 'No render dropped yet, so this downloads just the preset fields. Drop a render first to get a complete, loadable settings.txt.'; + dl.addEventListener('click', function(){ presetDownload(p); }); + btns.appendChild(dl); + var cp=document.createElement('button'); cp.textContent='Copy JSON'; + cp.addEventListener('click', function(){ + navigator.clipboard.writeText(JSON.stringify(p.settings,null,4)).then(function(){ + cp.textContent='Copied'; setTimeout(function(){ cp.textContent='Copy JSON'; },1200); + }).catch(function(){ alert('Clipboard blocked by the browser; use Download instead.'); }); + }); + btns.appendChild(cp); + if(p.custom && customIdx!==undefined){ + var del=document.createElement('button'); del.className='danger'; del.textContent='Delete'; + del.addEventListener('click', function(){ deleteCustomPreset(customIdx); }); + btns.appendChild(del); + } + card.appendChild(btns); + return card; +} +function renderPresets(){ + var body=document.getElementById('presetbody'); + if(!body) return; + clearEl(body); + var note=document.createElement('div'); note.className='pnote'; + note.textContent = presetHasFullBase() + ? 'A render is loaded, so Download gives you a COMPLETE Deforum settings file: this preset\'s look applied over that render\'s settings. Load it in Deforum via the Settings File box -> Load All Settings.' + : 'Drop a render below first, then a preset download becomes a COMPLETE Deforum settings file (preset merged over that render). Without one, you get just the preset fields as a reference overlay.'; + body.appendChild(note); + var grid=document.createElement('div'); grid.className='pgrid'; + BUILTIN_PRESETS.forEach(function(p){ grid.appendChild(buildPresetCard(p)); }); + loadCustomPresets().forEach(function(p,i){ grid.appendChild(buildPresetCard(p,i)); }); + body.appendChild(grid); +} +function openPresets(){ if(typeof switchTab==='function') switchTab('presets'); } +renderPresets(); + +/* ============ FULL SETTINGS COLUMNS + "why is this one different" marking ============ + Every card lists its COMPLETE settings, grouped, in one long column. For each parameter the + value is compared against the whole library: a value that differs from the majority is marked + (color + asterisk + tooltip of the majority value) - the fastest answer to "why does this one + suck / rock". */ +var SGROUPS=[["MODEL / SAMPLING",["sd_model_name","animation_mode","max_frames","W","H","fps","steps","sampler","scheduler","cfg_scale","cfg_scale_schedule","seed","seed_behavior","seed_schedule"]], + ["IMAGE EVOLUTION",["strength_schedule","noise_schedule","noise_multiplier_schedule","diffusion_cadence","optical_flow_cadence","optical_flow_redo_generation","cadence_flow_factor_schedule","redo_flow_factor_schedule","color_coherence","contrast_schedule","amount_schedule","color_force_grayscale","noise_type"]], + ["CAMERA / 3D",["fov_schedule","near_schedule","far_schedule","midas_weight","use_depth_warping","depth_algorithm","translation_x","translation_y","translation_z","rotation_3d_x","rotation_3d_y","rotation_3d_z","zoom","angle","enable_perspective_flip","perspective_flip_fv","perspective_flip_theta","perspective_flip_phi","perspective_flip_gamma","border","sampling_mode","padding_mode"]], + ["INIT / LOOPER",["use_init","init_image","strength_0_no_init","use_looper","init_images","image_strength_schedule","blendFactorMax","blendFactorSlope","tweening_frames_schedule","color_correction_factor"]]]; +var SGROUP_KEYS={}; SGROUPS.forEach(function(g){ g[1].forEach(function(k){ SGROUP_KEYS[k]=g[0]; }); }); + +function allFullPids(){ return Object.keys(DATA).filter(function(p){ return DATA[p].full && Object.keys(DATA[p].full).length; }); } +var VAL_FREQ=null; +function buildFreq(){ + VAL_FREQ={}; + allFullPids().forEach(function(p){ + var f=DATA[p].full; + for(var k in f){ var v=String(f[k]); (VAL_FREQ[k]=VAL_FREQ[k]||{})[v]=(VAL_FREQ[k][v]||0)+1; } + }); +} +function modalValue(k){ + var m=VAL_FREQ[k]||{}; var best=null,bn=-1; + for(var v in m){ if(m[v]>bn){ bn=m[v]; best=v; } } + return best; +} +function groupedKeys(full){ + var used={}, out=[]; + SGROUPS.forEach(function(g){ + var ks=g[1].filter(function(k){ return k in full; }); + if(ks.length){ out.push([g[0],ks]); ks.forEach(function(k){ used[k]=1; }); } + }); + var rest=Object.keys(full).filter(function(k){ return !used[k]; }); + if(rest.length) out.push(["OTHER",rest]); + return out; +} +function renderColumn(pid){ + var D=DATA[pid]; if(!D) return; + var fill=document.querySelector('.setfill[data-pid="'+pid+'"]'); + if(fill){ + clearEl(fill); + if(!D.full || !Object.keys(D.full).length){ + var e=document.createElement('div'); e.className='srow'; + var sv=document.createElement('span'); sv.className='sv'; sv.textContent='no settings.txt'; + e.appendChild(sv); fill.appendChild(e); + } else { + groupedKeys(D.full).forEach(function(g){ + var h=document.createElement('div'); h.className='sgroup'; h.textContent=g[0]; fill.appendChild(h); + g[1].forEach(function(k){ + var v=String(D.full[k]); + var row=document.createElement('div'); row.className='srow'; + var sk=document.createElement('span'); sk.className='sk'; sk.textContent=k; + var sv=document.createElement('span'); sv.className='sv'; sv.textContent=v.slice(0,120); + var modal=modalValue(k); + if(modal!==null && v!==modal && (VAL_FREQ[k][modal]||0)>=3){ + sv.classList.add('odd'); sv.title='most renders use: '+modal; + } + row.appendChild(sk); row.appendChild(sv); fill.appendChild(row); + }); + }); + } + } + var lc=document.querySelector('.lorachips[data-pid="'+pid+'"]'); + if(lc){ + clearEl(lc); + var names=Object.keys(D.loras||{}); + names.slice(0,14).forEach(function(n){ + var c=document.createElement('span'); c.className='lc'; + c.textContent=n+' ×'+D.loras[n]; lc.appendChild(c); + }); + if(names.length>14){ var m=document.createElement('span'); m.className='lc'; m.textContent='+'+(names.length-14)+' more'; lc.appendChild(m); } + } +} +function renderAllColumns(){ buildFreq(); Object.keys(DATA).forEach(renderColumn); } + +/* ============ Best-Buy COMPARE: tick renders, see them side-by-side with every + parameter aligned in rows, differences highlighted, similarities dimmed ============ */ +var selOrder=[]; +function selUpdate(){ + var bar=document.getElementById('cbar'); + document.querySelectorAll('.cmp-check').forEach(function(c){ + var card=c.closest('.card'); if(card) card.classList.toggle('selected', c.checked); + }); + var n=selOrder.length; + document.getElementById('cbar-count').textContent=n+' selected'; + bar.classList.toggle('on', n>0); + document.getElementById('cbar-go').disabled = n<2; +} +function attachChecks(root){ + (root||document).querySelectorAll('.cmp-check').forEach(function(c){ + if(c.dataset.wired) return; c.dataset.wired='1'; + c.addEventListener('change',function(){ + var pid=c.dataset.pid; + selOrder=selOrder.filter(function(p){ return p!==pid; }); + if(c.checked) selOrder.push(pid); + selUpdate(); + }); + }); +} +function cmpCell(tr, text, cls){ + var td=document.createElement('td'); if(cls) td.className=cls; + td.textContent=text; tr.appendChild(td); return td; +} +function cmpSection(tbody, label, span){ + var tr=document.createElement('tr'); tr.className='sec'; + var td=document.createElement('td'); td.textContent=label; tr.appendChild(td); + var td2=document.createElement('td'); td2.colSpan=span; tr.appendChild(td2); + tbody.appendChild(tr); +} +function buildCompare(){ + var pids=selOrder.slice(); + var scroll=document.getElementById('cmp-scroll'); clearEl(scroll); + var table=document.createElement('table'); table.className='cmp-t'; + var thead=document.createElement('thead'); var thr=document.createElement('tr'); + var th0=document.createElement('th'); th0.textContent='parameter'; thr.appendChild(th0); + pids.forEach(function(pid){ + var th=document.createElement('th'); + var nm=document.createElement('div'); nm.textContent=(DATA[pid]&&DATA[pid].name)||pid; th.appendChild(nm); + var src=document.getElementById(pid); + var v=document.createElement('video'); v.controls=true; v.preload='none'; v.playsInline=true; + if(src){ v.src=src.getAttribute('src')||src.src||''; var po=src.getAttribute('poster'); if(po) v.poster=po; } + v.dataset.cmpvid='1'; + th.appendChild(v); thr.appendChild(th); + }); + thead.appendChild(thr); table.appendChild(thead); + var tbody=document.createElement('tbody'); + + // LORAS: union across selected, presence + keyframe counts per render + var lset={}; pids.forEach(function(p){ Object.keys(DATA[p].loras||{}).forEach(function(n){ lset[n]=1; }); }); + var lnames=Object.keys(lset).sort(); + if(lnames.length){ + cmpSection(tbody,'LORAS',pids.length); + lnames.forEach(function(n){ + var vals=pids.map(function(p){ return (DATA[p].loras||{})[n]||0; }); + var same=vals.every(function(x){ return x===vals[0]; }); + var tr=document.createElement('tr'); tr.className=same?'same':'diff'; + cmpCell(tr,n); + vals.forEach(function(x){ cmpCell(tr, x? ('yes ×'+x):'—', x?'has':'not'); }); + tbody.appendChild(tr); + }); + } + + // SETTINGS: union of every parameter, grouped; diff rows highlighted + var union={}; pids.forEach(function(p){ Object.keys(DATA[p].full||{}).forEach(function(k){ union[k]=1; }); }); + groupedKeys(union).forEach(function(g){ + cmpSection(tbody,g[0],pids.length); + g[1].forEach(function(k){ + var vals=pids.map(function(p){ var f=DATA[p].full||{}; return (k in f)? String(f[k]) : '(absent)'; }); + var same=vals.every(function(x){ return x===vals[0]; }); + var tr=document.createElement('tr'); tr.className=same?'same':'diff'; + cmpCell(tr,k); + vals.forEach(function(x){ cmpCell(tr,x.slice(0,240)); }); + tbody.appendChild(tr); + }); + }); + + // PROMPTS: full keyframe prompt list per render + cmpSection(tbody,'PROMPTS',pids.length); + var tr=document.createElement('tr'); tr.className='diff'; + cmpCell(tr,'keyframe prompts'); + pids.forEach(function(p){ + var td=document.createElement('td'); var cell=document.createElement('div'); cell.className='pcell'; + ((DATA[p]&&DATA[p].kf)||[]).forEach(function(kf){ + var d1=document.createElement('div'); + var fspan=document.createElement('span'); fspan.className='pk2'; fspan.textContent=kf[0]+': '; + d1.appendChild(fspan); + d1.appendChild(document.createTextNode(kf[1]+(kf[2]&&kf[2].length? ' ['+kf[2].join(', ')+']':''))); + cell.appendChild(d1); + }); + if(!cell.childNodes.length) cell.textContent='(no prompt data)'; + td.appendChild(cell); tr.appendChild(td); + }); + tbody.appendChild(tr); + + table.appendChild(tbody); scroll.appendChild(table); + document.getElementById('cmp-overlay').classList.add('on'); + document.body.style.overflow='hidden'; + + // sync playback across the compared videos (by fraction, like the old compare mode) + var vids=[].slice.call(scroll.querySelectorAll('video[data-cmpvid]')); + var syncing2=false; + vids.forEach(function(v){ + v.addEventListener('timeupdate',function(){ + if(!document.getElementById('cmp-sync').checked || syncing2) return; + syncing2=true; + var frac=v.duration? v.currentTime/v.duration:0; + vids.forEach(function(o){ if(o!==v && o.duration && Math.abs(o.currentTime-frac*o.duration)>0.2) o.currentTime=frac*o.duration; }); + syncing2=false; + }); + v.addEventListener('play',function(){ if(document.getElementById('cmp-sync').checked) vids.forEach(function(o){ if(o!==v&&o.paused) o.play().catch(function(){}); }); }); + v.addEventListener('pause',function(){ if(document.getElementById('cmp-sync').checked) vids.forEach(function(o){ if(o!==v&&!o.paused) o.pause(); }); }); + }); +} +document.getElementById('cbar-go').addEventListener('click',function(){ if(selOrder.length>=2) buildCompare(); }); +document.getElementById('cbar-clear').addEventListener('click',function(){ + selOrder=[]; document.querySelectorAll('.cmp-check').forEach(function(c){ c.checked=false; }); selUpdate(); +}); +document.getElementById('cmp-close').addEventListener('click',function(){ + var ov=document.getElementById('cmp-overlay'); + ov.querySelectorAll('video').forEach(function(v){ try{ v.pause(); }catch(e){} }); + ov.classList.remove('on'); document.body.style.overflow=''; +}); +document.getElementById('cmp-diffsonly').addEventListener('change',function(){ + document.getElementById('cmp-overlay').classList.toggle('donly', this.checked); +}); +var _st=document.createElement('style'); +_st.textContent='.cmp-overlay.donly tr.same{display:none}'; +document.head.appendChild(_st); +document.addEventListener('keydown',function(e){ + if(e.key==='Escape' && document.getElementById('cmp-overlay').classList.contains('on')) + document.getElementById('cmp-close').click(); +}); + +/* ===== COMMENTS + DELETION FLAGS + BEST PRACTICES, persisted to the project folder ===== + Served through the WebUI, every edit POSTs to the gallery extension's notes API and lands in + outputs/img2img-images/_gallery_data/gallery_notes.json (keyed by render NAME, so notes survive + rebuilds). Opened as a plain file, the page shows the baked snapshot read-only. Flagging marks + a render for deletion - NOTHING is deleted by the page; Brian reviews the flag list and the + deletion (video + settings + originals) happens deliberately, off-page. */ +var NOTES = NOTES_INIT || {comments:{},flags:[],best_practices:''}; +var API_LIVE=false, NAPI='/deforum-gallery-api'; + +function cardByName(name){ + var b=document.querySelector('.flagbtn[data-name="'+(window.CSS&&CSS.escape?CSS.escape(name):name)+'"]'); + return b? b.closest('.card') : null; +} +function renderFlagStates(){ + document.querySelectorAll('.flagbtn').forEach(function(b){ + var on=NOTES.flags.indexOf(b.dataset.name)!==-1; + b.classList.toggle('on',on); + b.textContent=on? '🗑 flagged' : '🗑 flag'; + var card=b.closest('.card'); if(card) card.classList.toggle('flagged',on); + }); +} +function renderCommentsFor(el){ + var name=el.dataset.name; clearEl(el); + var list=(NOTES.comments||{})[name]||[]; + list.forEach(function(c){ + var d=document.createElement('div'); d.className='c1'; + var ts=document.createElement('span'); ts.className='ts'; ts.textContent=c.ts||''; + d.appendChild(ts); d.appendChild(document.createTextNode(c.text||'')); + el.appendChild(d); + }); + var ta=document.createElement('textarea'); ta.placeholder='add a comment on this render…'; + el.appendChild(ta); + var row=document.createElement('div'); row.className='crow'; + var btn=document.createElement('button'); btn.textContent='save comment'; + if(API_LIVE){ + btn.addEventListener('click',function(){ + var text=ta.value.trim(); if(!text) return; + fetch(NAPI+'/comment',{method:'POST',headers:{'Content-Type':'application/json'}, + body:JSON.stringify({name:name,text:text})}) + .then(function(r){return r.json();}).then(function(j){ + if(j.ok){ NOTES.comments[name]=j.comments; renderCommentsFor(el); renderSaved(); } + else alert('save failed: '+(j.error||'?')); + }).catch(function(e){ alert('save failed: '+e); }); + }); + } else { + btn.disabled=true; + var note=document.createElement('span'); note.className='apinote'; + note.textContent='comments save when opened via the WebUI Render Gallery tab'; + row.appendChild(note); + } + row.insertBefore(btn,row.firstChild); + el.appendChild(row); +} +function renderNotesAll(){ + renderFlagStates(); + document.querySelectorAll('.cmts[data-name]').forEach(renderCommentsFor); +} +function wireFlagBtn(b){ + if(b.dataset.wired) return; b.dataset.wired='1'; + b.addEventListener('click',function(){ + var name=b.dataset.name; + if(!API_LIVE){ alert('Flagging saves when the gallery is opened via the WebUI Render Gallery tab.'); return; } + var flagged=NOTES.flags.indexOf(name)===-1; + fetch(NAPI+'/flag',{method:'POST',headers:{'Content-Type':'application/json'}, + body:JSON.stringify({name:name,flagged:flagged})}) + .then(function(r){return r.json();}).then(function(j){ + if(j.ok){ NOTES.flags=j.flags; renderFlagStates(); renderSaved(); applyFilter(); } + }).catch(function(e){ alert('flag failed: '+e); }); + }); +} +document.querySelectorAll('.flagbtn').forEach(wireFlagBtn); + +// "flagged only" folds into the existing filter pipeline +var _origApplyFilter=applyFilter; +applyFilter=function(){ + _origApplyFilter(); + var fc=document.getElementById('flagchk'); + if(fc && fc.checked){ + document.querySelectorAll('.card[data-pid]').forEach(function(c){ + if(c.hidden) return; + var b=c.querySelector('.flagbtn'); + if(!b || NOTES.flags.indexOf(b.dataset.name)===-1) c.hidden=true; + }); + } +}; +var _fc=document.getElementById('flagchk'); +if(_fc) _fc.addEventListener('change',function(){ applyFilter(); }); + +// ----- Best Practices: view + edit; saved to the project folder via the API, or downloadable ----- +/* Best Practices formatter - renders the plain-text notes as a readable document: + "== HEADING ==" lines become titled section cards, "- " lines become real bullet lists, + wrapped continuation lines fold into their bullet. Edit mode still works on the raw text. */ +function formatBP(text){ + var root=document.createElement('div'); root.className='bpdoc'; + var intro=document.createElement('div'); intro.className='bpintro'; + var sec=null, list=null; + function tgt(){ return sec||root; } + String(text||'').split(/\r?\n/).forEach(function(raw){ + var line=raw.replace(/\s+$/,''); + var m=line.match(/^==\s*(.+?)\s*==$/); + if(m){ + list=null; + sec=document.createElement('section'); sec.className='bpsec'; + var h=document.createElement('h2'); h.textContent=m[1]; sec.appendChild(h); + root.appendChild(sec); return; + } + if(!line.trim()){ list=null; return; } + if(/^- /.test(line.trim()) ){ + if(!list){ list=document.createElement('ul'); tgt().appendChild(list); } + var li=document.createElement('li'); li.textContent=line.trim().slice(2); list.appendChild(li); return; + } + if(/^\s{2,}/.test(raw) && list && list.lastChild){ // wrapped continuation of the last bullet + list.lastChild.textContent += ' ' + line.trim(); return; + } + list=null; + if(!sec){ + var p0=document.createElement('p'); + p0.className = intro.childNodes.length ? 'bpsub' : 'bptitle'; + p0.textContent=line; + intro.appendChild(p0); + if(!root.contains(intro)) root.insertBefore(intro, root.firstChild); + return; + } + var p=document.createElement('p'); p.textContent=line; tgt().appendChild(p); + }); + if(!root.childNodes.length){ + var e=document.createElement('p'); e.className='bpsub'; e.textContent='(empty)'; root.appendChild(e); + } + bpIllustrate(root); + return root; +} +function bpZoom(src){ + var lb=document.getElementById('bplightbox'); + if(!lb){ + lb=document.createElement('div'); lb.id='bplightbox'; + lb.appendChild(document.createElement('img')); + lb.addEventListener('click',function(){ lb.classList.remove('on'); }); + document.body.appendChild(lb); + document.addEventListener('keydown',function(e){ if(e.key==='Escape') lb.classList.remove('on'); }); + } + lb.querySelector('img').src=src; + lb.classList.add('on'); +} +/* Hang the matching Deforum control screenshots off each section, keyed by a word in its heading, + so the notes stay editable plain text and the pictures follow them automatically. */ +function bpIllustrate(root){ + if(typeof BP_SHOTS==='undefined' || !BP_SHOTS.length) return; + Array.prototype.forEach.call(root.querySelectorAll('.bpsec'), function(sec){ + var h=sec.querySelector('h2'); if(!h) return; + var head=h.textContent.toUpperCase(); + BP_SHOTS.forEach(function(s){ + if(head.indexOf(s.key)===-1) return; + var fig=document.createElement('figure'); fig.className='bpfig'; + fig.title='Click to enlarge'; + fig.addEventListener('click',function(){ bpZoom(s.src); }); + var img=document.createElement('img'); img.src=s.src; img.alt=s.cap; img.loading='lazy'; + fig.appendChild(img); + var cap=document.createElement('figcaption'); + var b=document.createElement('b'); b.textContent=s.panel; + cap.appendChild(b); cap.appendChild(document.createTextNode(' '+s.cap)); + fig.appendChild(cap); sec.appendChild(fig); + }); + }); +} +function renderBP(){ + var body=document.getElementById('bpbody'); if(!body) return; + clearEl(body); + body.appendChild(formatBP(NOTES.best_practices)); + var row=document.createElement('div'); row.className='bprow'; + var edit=document.createElement('button'); edit.textContent='Edit'; + edit.addEventListener('click',function(){ + clearEl(body); + var ta=document.createElement('textarea'); ta.value=NOTES.best_practices||''; body.appendChild(ta); + var hint=document.createElement('div'); hint.className='bpedithint'; + hint.textContent='plain text: "== HEADING ==" starts a section, lines beginning "- " become bullets'; + body.appendChild(hint); + var r2=document.createElement('div'); r2.className='bprow'; + if(API_LIVE){ + var save=document.createElement('button'); save.textContent='Save to project folder'; + save.addEventListener('click',function(){ + fetch(NAPI+'/bestpractices',{method:'POST',headers:{'Content-Type':'application/json'}, + body:JSON.stringify({text:ta.value})}) + .then(function(r){return r.json();}).then(function(j){ + if(j.ok){ NOTES.best_practices=ta.value; renderBP(); } else alert('save failed'); + }).catch(function(e){ alert('save failed: '+e); }); + }); + r2.appendChild(save); + } else { + var dl=document.createElement('button'); dl.textContent='Download my edits (send the file back to Brian)'; + dl.addEventListener('click',function(){ + var blob=new Blob([ta.value],{type:'text/plain'}); + var url=URL.createObjectURL(blob); + var a=document.createElement('a'); a.href=url; a.download='best_practices_edited.txt'; + document.body.appendChild(a); a.click(); document.body.removeChild(a); + setTimeout(function(){ URL.revokeObjectURL(url); },1000); + }); + r2.appendChild(dl); + } + var cancel=document.createElement('button'); cancel.className='ghost'; cancel.textContent='Cancel'; + cancel.addEventListener('click',renderBP); + r2.appendChild(cancel); + body.appendChild(r2); + }); + row.appendChild(edit); + if(!API_LIVE){ + var n=document.createElement('span'); n.className='apinote'; + n.textContent='live saving needs the WebUI Render Gallery tab; here Edit gives you a downloadable copy'; + row.appendChild(n); + } + body.appendChild(row); +} +/* ===== live folders + dynamic library ===== + Served via the WebUI, the library is NOT the baked snapshot: /scan walks the folder chosen in + the Folders bar and the page rebuilds its cards from that JSON. Change the folder, hit Rescan, + different library. Opened from disk (no API), the baked snapshot stays as the offline fallback. */ +var libSeq=0; +function wireCardVideo(v){ + ['timeupdate','seeked','play'].forEach(function(e){ v.addEventListener(e,function(){ upd(v); }); }); +} +function buildLibCard(entry){ + var pid='lib'+(libSeq++); + registerDataJS(pid, entry.settings||null); + DATA[pid].name=entry.name; + var card=document.createElement('div'); card.className='card'; + card.dataset.pid=pid; card.dataset.name=entry.name.toLowerCase(); + card.dataset.mtime=entry.mtime||0; + card.dataset.frames=(entry.settings&&entry.settings.max_frames)||0; + card.dataset.dur=0; + card.dataset.hay=(entry.name+' '+String(entry.settings&&entry.settings.sd_model_name||'')+' ' + +JSON.stringify((entry.settings&&entry.settings.prompts)||'')).toLowerCase().slice(0,4000); + + var chead=document.createElement('div'); chead.className='chead'; + var fb=document.createElement('button'); fb.className='flagbtn'; fb.dataset.name=entry.name; + fb.textContent='🗑 flag'; wireFlagBtn(fb); chead.appendChild(fb); + var eb=document.createElement('button'); eb.className='exportbtn'; eb.dataset.name=entry.name; + eb.textContent='⬇ export'; wireExportBtn(eb); chead.appendChild(eb); + var cl=document.createElement('label'); cl.className='cmp'; + var cc=document.createElement('input'); cc.type='checkbox'; cc.className='cmp-check'; cc.dataset.pid=pid; + cl.appendChild(cc); cl.appendChild(document.createTextNode(' compare')); chead.appendChild(cl); + var fn=document.createElement('div'); fn.className='fn'; fn.textContent=entry.name; fn.title=entry.name; + chead.appendChild(fn); + var fd=document.createElement('div'); fd.className='fd'; + fd.textContent=(entry.settings?'':'no settings.txt · ')+(entry.size? Math.round(entry.size/1e6)+' MB':''); + chead.appendChild(fd); + card.appendChild(chead); + + var vb=document.createElement('div'); vb.className='vidbox'; + var v=document.createElement('video'); v.id=pid; v.dataset.pid=pid; + v.controls=true; v.preload='none'; v.playsInline=true; + v.src=entry.video; if(entry.poster) v.poster=entry.poster; + wireCardVideo(v); vb.appendChild(v); card.appendChild(vb); + + var live=document.createElement('div'); live.className='live'; live.id='live-'+pid; + var hint=document.createElement('div'); hint.className='lrow hint'; + hint.textContent='press play — live prompt, LoRAs and camera appear here'; + live.appendChild(hint); card.appendChild(live); + + var exp=document.createElement('div'); exp.className='exp'; + exp.textContent=entry.settings? experimentJS(entry.settings) : 'no settings.txt'; + card.appendChild(exp); + + var lc=document.createElement('div'); lc.className='lorachips'; lc.dataset.pid=pid; card.appendChild(lc); + var cm=document.createElement('div'); cm.className='cmts'; cm.dataset.name=entry.name; card.appendChild(cm); + var sf=document.createElement('div'); sf.className='setfill'; sf.dataset.pid=pid; card.appendChild(sf); + return card; +} +function loadLibrary(){ + var st=document.getElementById('dirstatus'); + if(st){ st.textContent='scanning…'; st.classList.remove('err'); } + return fetch(NAPI+'/scan').then(function(r){ return r.json(); }).then(function(j){ + if(!j.ok){ if(st){ st.textContent=j.error||'scan failed'; st.classList.add('err'); } return; } + Object.keys(DATA).forEach(function(p){ if(p.indexOf('drop')!==0){ delete DATA[p]; delete camFns[p]; } }); + selOrder=selOrder.filter(function(p){ return p.indexOf('drop')===0; }); selUpdate(); + if(gridEl) clearEl(gridEl); + var frag=document.createDocumentFragment(); + j.renders.forEach(function(e){ frag.appendChild(buildLibCard(e)); }); + if(gridEl) gridEl.appendChild(frag); + cardsAll=[].slice.call(document.querySelectorAll('.grid .card[data-pid]')); + buildFreq(); + cardsAll.forEach(function(c){ renderColumn(c.dataset.pid); }); + attachChecks(gridEl); renderNotesAll(); applyFilter(); renderSaved(); + var lib=document.getElementById('dzlib'); + if(lib){ lib.textContent='Live library: '+j.root+' · '+j.renders.length+' renders'; } + if(st) st.textContent=j.renders.length+' renders'; + }).catch(function(e){ if(st){ st.textContent='scan error: '+e; st.classList.add('err'); } }); +} +/* The gallery references ONE folder: where the renders live. (Init-image / video / ControlNet / + model folder settings belong to the Deforum panel, not here.) Browse... opens a server-side + folder picker, because web pages cannot read real filesystem paths from native file dialogs. */ +var DIR_INPUTS={renders:'dir-renders'}; +function autoSaveDirs(changedKey){ + var dirs={}; + Object.keys(DIR_INPUTS).forEach(function(k){ + var el=document.getElementById(DIR_INPUTS[k]); if(el && el.value.trim()) dirs[k]=el.value.trim(); + }); + var st=document.getElementById(changedKey==='renders' ? 'dirstatus' : ('fstat-'+changedKey)) + || document.getElementById('dirstatus'); + return fetch(NAPI+'/config',{method:'POST',headers:{'Content-Type':'application/json'}, + body:JSON.stringify({dirs:dirs})}) + .then(function(r){ return r.json(); }).then(function(j){ + if(j.ok){ + if(st){ st.textContent='saved'; st.className=(st.id==='dirstatus'?'dirstatus':'fstat ok'); } + if(changedKey==='renders') loadLibrary(); + } else if(st){ + st.textContent=j.error||'save failed'; + st.className=(st.id==='dirstatus'?'dirstatus err':'fstat err'); + } + }).catch(function(e){ + if(st){ st.textContent='save error: '+e; st.className=(st.id==='dirstatus'?'dirstatus err':'fstat err'); } + }); +} +function initDirBar(){ + fetch(NAPI+'/config').then(function(r){ return r.json(); }).then(function(c){ + var bar=document.getElementById('dirbar'); if(bar) bar.removeAttribute('hidden'); + Object.keys(DIR_INPUTS).forEach(function(k){ + var el=document.getElementById(DIR_INPUTS[k]); if(el) el.value=(c.dirs&&c.dirs[k])||''; + }); + var sv=document.getElementById('dirsave'); + if(sv) sv.addEventListener('click',function(){ autoSaveDirs('renders'); }); + var rs=document.getElementById('dirrescan'); + if(rs) rs.addEventListener('click',loadLibrary); + }).catch(function(){}); +} +/* server-side folder browser popup */ +var fbTargetInput=null, fbCurrentPath=''; +function fbNav(path){ + var list=document.getElementById('fb-list'), head=document.getElementById('fb-path'), + stat=document.getElementById('fb-stat'), use=document.getElementById('fb-use'); + fetch(NAPI+'/browse?path='+encodeURIComponent(path||'')).then(function(r){ return r.json(); }) + .then(function(j){ + if(!j.ok){ if(stat){ stat.textContent=j.error||'browse failed'; stat.className='fstat err'; } return; } + if(stat){ stat.textContent=''; stat.className='fstat'; } + fbCurrentPath=j.path; + if(head) head.textContent=j.path||'Drives'; + if(use) use.disabled=j.isRoot; + clearEl(list); + if(j.parent!==null && !j.isRoot){ + var up=document.createElement('button'); up.className='fb-item'; up.textContent='⬑ ..'; + up.addEventListener('click',function(){ fbNav(j.parent); }); + list.appendChild(up); + } + j.dirs.forEach(function(d){ + var b=document.createElement('button'); b.className='fb-item'; + b.textContent=(j.isRoot? '' : '📁 ')+d; + b.addEventListener('click',function(){ + fbNav(j.isRoot ? d : (j.path.replace(/[\\/]+$/,'')+'\\'+d)); + }); + list.appendChild(b); + }); + if(!j.dirs.length){ + var e=document.createElement('div'); e.className='fb-item'; e.textContent='(no subfolders)'; + list.appendChild(e); + } + }).catch(function(e){ if(stat){ stat.textContent='browse error: '+e; stat.className='fstat err'; } }); +} +function openBrowse(inputId){ + if(!API_LIVE){ alert('Browsing folders needs the page opened via the WebUI (Render Gallery tab).'); return; } + fbTargetInput=document.getElementById(inputId); + document.getElementById('fb-ov').removeAttribute('hidden'); + fbNav((fbTargetInput&&fbTargetInput.value)||''); +} +(function(){ + document.querySelectorAll('.fbrowse').forEach(function(b){ + b.addEventListener('click',function(){ openBrowse(b.dataset.for); }); + }); + var cl=document.getElementById('fb-close'); + if(cl) cl.addEventListener('click',function(){ document.getElementById('fb-ov').setAttribute('hidden',''); }); + var use=document.getElementById('fb-use'); + if(use) use.addEventListener('click',function(){ + if(fbTargetInput && fbCurrentPath){ + fbTargetInput.value=fbCurrentPath; + var key=Object.keys(DIR_INPUTS).filter(function(k){ return DIR_INPUTS[k]===fbTargetInput.id; })[0]; + autoSaveDirs(key||'renders'); + } + document.getElementById('fb-ov').setAttribute('hidden',''); + }); + var ov=document.getElementById('fb-ov'); + if(ov) ov.addEventListener('click',function(ev){ if(ev.target===ov) ov.setAttribute('hidden',''); }); +})(); +function notesInit(){ + fetch(NAPI+'/state').then(function(r){ if(!r.ok) throw 0; return r.json(); }) + .then(function(n){ NOTES=n; API_LIVE=true; document.body.classList.add('apilive'); + renderNotesAll(); renderBP(); renderSaved(); applyFilter(); + initDirBar(); loadLibrary(); }) + .catch(function(){ API_LIVE=false; renderNotesAll(); renderBP(); renderSaved(); }); +} +// export = download a zip of this render's mp4 + settings (server bundles the pair) +function wireExportBtn(b){ + if(b.dataset.wired) return; b.dataset.wired='1'; + b.addEventListener('click',function(){ + window.location.href = NAPI+'/export?name='+encodeURIComponent(b.dataset.name); + }); +} +document.querySelectorAll('.exportbtn').forEach(wireExportBtn); + +/* ============ SAVED tab: review surface for anything flagged and/or commented ============ + Brian wasn't sure what this tab should be ("the ones we save... I don't know") - this surfaces + exactly the data that's actually persisted (flags + comments), so it's a management view of + what he's tagged rather than a new, untested concept. */ +function renderSaved(){ + var body=document.getElementById('savedbody'); if(!body) return; + clearEl(body); + var names={}; (NOTES.flags||[]).forEach(function(n){ names[n]=1; }); + Object.keys(NOTES.comments||{}).forEach(function(n){ if((NOTES.comments[n]||[]).length) names[n]=1; }); + var list=Object.keys(names).sort(); + var cnt=document.getElementById('savedcount'); + if(cnt) cnt.textContent = list.length ? '('+list.length+')' : ''; + if(!list.length){ + var e=document.createElement('div'); e.className='savedempty'; + e.textContent='Nothing flagged or commented yet. Flag a render for deletion, or add a comment, from the Gallery tab.'; + body.appendChild(e); return; + } + list.forEach(function(name){ + var flagged=(NOTES.flags||[]).indexOf(name)!==-1; + var row=document.createElement('div'); row.className='savedrow'+(flagged?' flagged':''); + var h=document.createElement('h3'); h.textContent=name; row.appendChild(h); + var meta=document.createElement('div'); meta.className='srmeta'; + var jump=document.createElement('button'); jump.textContent='View in Gallery'; + jump.addEventListener('click',function(){ + switchTab('gallery'); + var card=cardByName(name); + if(card) card.scrollIntoView({behavior:'smooth',inline:'center',block:'start'}); + }); + meta.appendChild(jump); + if(flagged){ + var unflag=document.createElement('button'); unflag.textContent='Unflag'; + unflag.addEventListener('click',function(){ + if(!API_LIVE){ alert('Unflagging needs the WebUI Render Gallery tab.'); return; } + fetch(NAPI+'/flag',{method:'POST',headers:{'Content-Type':'application/json'}, + body:JSON.stringify({name:name,flagged:false})}) + .then(function(r){return r.json();}).then(function(j){ + if(j.ok){ NOTES.flags=j.flags; renderFlagStates(); renderSaved(); applyFilter(); } + }).catch(function(e){ alert('unflag failed: '+e); }); + }); + meta.appendChild(unflag); + var tag=document.createElement('span'); tag.textContent='flagged for deletion'; tag.style.color='var(--warn)'; + tag.style.fontSize='11.5px'; tag.style.fontFamily='var(--mono)'; meta.appendChild(tag); + } + row.appendChild(meta); + (NOTES.comments[name]||[]).forEach(function(c){ + var d=document.createElement('div'); d.className='c1'; + var ts=document.createElement('span'); ts.className='ts'; ts.textContent=c.ts||''; + d.appendChild(ts); d.appendChild(document.createTextNode(c.text||'')); + row.appendChild(d); + }); + body.appendChild(row); + }); +} + +// pin the sticky column headers just below the real toolbar height +(function(){ + var ctl=document.querySelector('.ctl'); + function setStick(){ if(ctl) document.documentElement.style.setProperty('--stick',(ctl.offsetHeight+8)+'px'); } + setStick(); window.addEventListener('resize',setStick); +})(); +renderAllColumns(); attachChecks(document); selUpdate(); notesInit(); + +/* view modes, persisted: strip = one giant horizontal row (49-inch friendly); + grid = wrapped cards, N across (user-defined); list = one render per full-width row, + settings spread into text columns. Card-size slider only applies to strip; + the "across" count only applies to grid - each control hides when irrelevant. */ +(function(){ + var vs=document.getElementById('viewsel'), gc=document.getElementById('gridcols'); + if(!vs) return; + function applyView(){ + var m=vs.value; + document.body.classList.toggle('gridmode', m==='grid'); + document.body.classList.toggle('listrows', m==='list'); + document.documentElement.style.setProperty('--gcols', String((gc&&parseInt(gc.value,10))||4)); + var sz=document.getElementById('szwrap'); if(sz) sz.style.display=(m==='strip')?'':'none'; + var gw=document.getElementById('gcwrap'); if(gw) gw.style.display=(m==='grid')?'':'none'; + try{ localStorage.setItem('dg_view3', m); if(gc) localStorage.setItem('dg_gcols', gc.value); }catch(e){} + } + try{ + var sv=localStorage.getItem('dg_view3'); if(sv && ['strip','grid','list'].indexOf(sv)!==-1) vs.value=sv; + var sg=localStorage.getItem('dg_gcols'); if(sg && gc) gc.value=sg; + }catch(e){} + vs.addEventListener('change',applyView); + if(gc) gc.addEventListener('input',applyView); + applyView(); +})(); + +/* ============ TABS: one switch, one state, nothing else touches visibility ============ + Replaces the two independent collapsible-panel systems that could desync (see the CSS comment + at the top of EXTRA_CSS for the repro). [hidden] on the inactive tabpages takes the 44k-node + gallery grid fully out of layout/paint while on another tab - not just visually hidden. */ +var TABS=['gallery','practices','presets','saved']; +function switchTab(name){ + if(TABS.indexOf(name)===-1) name='gallery'; + TABS.forEach(function(t){ + var page=document.getElementById('tabpage-'+t); + if(page){ if(t===name) page.removeAttribute('hidden'); else page.setAttribute('hidden',''); } + }); + document.querySelectorAll('.tabbtn').forEach(function(b){ + var on=b.dataset.tab===name; + b.classList.toggle('active',on); + b.setAttribute('aria-selected', on?'true':'false'); + }); + if(name!=='gallery'){ + // don't leave a render quietly playing behind a tab you can't see + document.querySelectorAll('#tabpage-gallery video').forEach(function(v){ if(!v.paused) v.pause(); }); + } + if(name==='saved') renderSaved(); + try{ localStorage.setItem('deforum_gallery_tab', name); }catch(e){} +} +document.querySelectorAll('.tabbtn').forEach(function(b){ + b.addEventListener('click',function(){ switchTab(b.dataset.tab); }); +}); +(function(){ + var saved=null; + try{ saved=localStorage.getItem('deforum_gallery_tab'); }catch(e){} + switchTab(saved||'gallery'); +})(); + +/* Browse buttons - normal file/folder pickers feeding the SAME pipeline as drag-and-drop + (webkitdirectory gives the whole folder tree; prefiltered to mp4/txt/json so a folder full of + PNG frames doesn't trip the "no mp4 found" alert for the wrong reason) */ +(function(){ + var pf=document.getElementById('pickfiles'), pd=document.getElementById('pickdir'); + var bf=document.getElementById('browsefiles'), bd=document.getElementById('browsedir'); + function useful(fl){ + return [].slice.call(fl||[]).filter(function(f){ return /\.(mp4|txt|json)$/i.test(f.name); }); + } + if(bf&&pf){ + bf.addEventListener('click',function(){ pf.click(); }); + pf.addEventListener('change',function(){ + var fs=useful(pf.files); + if(fs.length) handleDropFiles(fs); else if(pf.files.length) alert('No .mp4 / settings files in that selection.'); + pf.value=''; + }); + } + if(bd&&pd){ + bd.addEventListener('click',function(){ pd.click(); }); + pd.addEventListener('change',function(){ + var fs=useful(pd.files); + if(fs.length) handleDropFiles(fs); else if(pd.files.length) alert('No .mp4 / settings files found in that folder.'); + pd.value=''; + }); + } +})(); + +var dropzoneEl=document.getElementById('dropzone'); +['dragenter','dragover'].forEach(function(e){ + document.addEventListener(e,function(ev){ ev.preventDefault(); dropzoneEl.classList.add('drag'); }); +}); +document.addEventListener('dragleave',function(ev){ if(ev.clientX<=0||ev.clientY<=0) dropzoneEl.classList.remove('drag'); }); +document.addEventListener('drop',function(ev){ + ev.preventDefault(); + if(dropzoneEl) dropzoneEl.classList.remove('drag'); + var dt=ev.dataTransfer; if(!dt) return; + // dataTransfer is only valid during dispatch, so copy the plain list NOW. This is the + // fallback for every case where the directory-entry API hands back nothing - which is what + // made a drop look like it did literally nothing instead of saying so. + var plain=dt.files ? [].slice.call(dt.files) : []; + var hadDirItem=false; + if(dt.items){ for(var i=0;i{html.escape(ROOT)}). Open this page via the WebUI's " + "Render Gallery tab for LIVE folders, rescan, and editing.") + +doc = f'''{HEAD_TITLE} +
+
+

{PAGE_TITLE}

+ + + + across + + Card size + +
+
+{EXTRA_HTML_HEAD.replace("__LIBLINE__", LIB_LINE)} +
{"".join(cards)}
+{EXTRA_HTML_TAIL} + +''' +with open(OUT, "w", encoding="utf-8") as f: + f.write(doc) +print("Wrote:", OUT) +print(f"{len(keep)} renders in gallery | {trashed} duplicate/bad moved to _trash_review") diff --git a/microcosm/microcosm-init.png b/microcosm/microcosm-init.png new file mode 100644 index 00000000..71df1854 Binary files /dev/null and b/microcosm/microcosm-init.png differ diff --git a/microcosm/screenshots/bp/animmode.png b/microcosm/screenshots/bp/animmode.png new file mode 100644 index 00000000..5b75bc9e Binary files /dev/null and b/microcosm/screenshots/bp/animmode.png differ diff --git a/microcosm/screenshots/bp/cadence.png b/microcosm/screenshots/bp/cadence.png new file mode 100644 index 00000000..d0bdf82d Binary files /dev/null and b/microcosm/screenshots/bp/cadence.png differ diff --git a/microcosm/screenshots/bp/checkpoint.png b/microcosm/screenshots/bp/checkpoint.png new file mode 100644 index 00000000..553c0a80 Binary files /dev/null and b/microcosm/screenshots/bp/checkpoint.png differ diff --git a/microcosm/screenshots/bp/init.png b/microcosm/screenshots/bp/init.png new file mode 100644 index 00000000..838388fa Binary files /dev/null and b/microcosm/screenshots/bp/init.png differ diff --git a/microcosm/screenshots/bp/motion.png b/microcosm/screenshots/bp/motion.png new file mode 100644 index 00000000..e7f71603 Binary files /dev/null and b/microcosm/screenshots/bp/motion.png differ diff --git a/microcosm/screenshots/bp/negative.png b/microcosm/screenshots/bp/negative.png new file mode 100644 index 00000000..1fc0d3d7 Binary files /dev/null and b/microcosm/screenshots/bp/negative.png differ diff --git a/microcosm/screenshots/bp/prompts.png b/microcosm/screenshots/bp/prompts.png new file mode 100644 index 00000000..e1f5bf0f Binary files /dev/null and b/microcosm/screenshots/bp/prompts.png differ diff --git a/microcosm/screenshots/bp/strength.png b/microcosm/screenshots/bp/strength.png new file mode 100644 index 00000000..6e3ebd01 Binary files /dev/null and b/microcosm/screenshots/bp/strength.png differ diff --git a/microcosm/screenshots/bp/subtabs.png b/microcosm/screenshots/bp/subtabs.png new file mode 100644 index 00000000..d449c676 Binary files /dev/null and b/microcosm/screenshots/bp/subtabs.png differ diff --git a/screenshots/bp/animmode.png b/screenshots/bp/animmode.png new file mode 100644 index 00000000..5b75bc9e Binary files /dev/null and b/screenshots/bp/animmode.png differ diff --git a/screenshots/bp/cadence.png b/screenshots/bp/cadence.png new file mode 100644 index 00000000..d0bdf82d Binary files /dev/null and b/screenshots/bp/cadence.png differ diff --git a/screenshots/bp/checkpoint.png b/screenshots/bp/checkpoint.png new file mode 100644 index 00000000..553c0a80 Binary files /dev/null and b/screenshots/bp/checkpoint.png differ diff --git a/screenshots/bp/init.png b/screenshots/bp/init.png new file mode 100644 index 00000000..838388fa Binary files /dev/null and b/screenshots/bp/init.png differ diff --git a/screenshots/bp/motion.png b/screenshots/bp/motion.png new file mode 100644 index 00000000..e7f71603 Binary files /dev/null and b/screenshots/bp/motion.png differ diff --git a/screenshots/bp/negative.png b/screenshots/bp/negative.png new file mode 100644 index 00000000..1fc0d3d7 Binary files /dev/null and b/screenshots/bp/negative.png differ diff --git a/screenshots/bp/prompts.png b/screenshots/bp/prompts.png new file mode 100644 index 00000000..e1f5bf0f Binary files /dev/null and b/screenshots/bp/prompts.png differ diff --git a/screenshots/bp/strength.png b/screenshots/bp/strength.png new file mode 100644 index 00000000..6e3ebd01 Binary files /dev/null and b/screenshots/bp/strength.png differ diff --git a/screenshots/bp/subtabs.png b/screenshots/bp/subtabs.png new file mode 100644 index 00000000..d449c676 Binary files /dev/null and b/screenshots/bp/subtabs.png differ diff --git a/screenshots/compare-landing.png b/screenshots/compare-landing.png new file mode 100644 index 00000000..689b4009 Binary files /dev/null and b/screenshots/compare-landing.png differ diff --git a/screenshots/deforum-init-tab.png b/screenshots/deforum-init-tab.png new file mode 100644 index 00000000..1a8705e4 Binary files /dev/null and b/screenshots/deforum-init-tab.png differ diff --git a/screenshots/deforum-keyframes.png b/screenshots/deforum-keyframes.png new file mode 100644 index 00000000..032eba55 Binary files /dev/null and b/screenshots/deforum-keyframes.png differ diff --git a/screenshots/deforum-prompts-tab.png b/screenshots/deforum-prompts-tab.png new file mode 100644 index 00000000..f294fb72 Binary files /dev/null and b/screenshots/deforum-prompts-tab.png differ diff --git a/screenshots/deforum-run-tab.png b/screenshots/deforum-run-tab.png new file mode 100644 index 00000000..746f8722 Binary files /dev/null and b/screenshots/deforum-run-tab.png differ diff --git a/screenshots/deforum-settings-editor.png b/screenshots/deforum-settings-editor.png new file mode 100644 index 00000000..db66e690 Binary files /dev/null and b/screenshots/deforum-settings-editor.png differ diff --git a/scripts/default_settings.txt b/scripts/default_settings.txt index 32e8eb91..a8c4d22b 100644 --- a/scripts/default_settings.txt +++ b/scripts/default_settings.txt @@ -1,21 +1,22 @@ { - "W": 512, - "H": 512, - "show_info_on_ui": true, + "W": 1024, + "H": 1024, + "show_info_on_ui": false, "tiling": false, - "restore_faces": false, + "restore_faces": true, "seed_resize_from_w": 0, "seed_resize_from_h": 0, - "seed": -1, - "sampler": "Euler a", - "steps": 25, - "batch_name": "Deforum_20230812221310", - "seed_behavior": "iter", - "seed_iter_N": 1, - "use_init": false, - "strength": 0.8, - "strength_0_no_init": true, - "init_image": null, + "seed": 1234, + "sampler": "DPM++ 2M SDE", + "scheduler": "Karras", + "steps": 40, + "batch_name": "Deforum_8000_Laffoley_Time_Machine", + "seed_behavior": "schedule", + "seed_iter_N": 1234, + "use_init": true, + "strength": 0.82, + "strength_0_no_init": false, + "init_image": "F:/AI Images/Laffoley Time Machines/00.1-840x841.jpg", "use_mask": false, "use_alpha_as_mask": false, "mask_file": "https://deforum.github.io/a1/M1.jpg", @@ -24,49 +25,57 @@ "mask_brightness_adjust": 1.0, "overlay_mask": true, "mask_overlay_blur": 4, - "fill": 0, + "fill": 1, "full_res_mask": true, "full_res_mask_padding": 4, "reroll_blank_frames": "ignore", "reroll_patience": 10.0, "motion_preview_mode": false, "prompts": { - "0": " tiny cute swamp bunny, highly detailed, intricate, ultra hd, sharp photo, crepuscular rays, in focus, 4k, landscape --neg nsfw, nude", - "30": " anthropomorphic clean cat, surrounded by mandelbulb fractals, epic angle and pose, symmetrical, 3d, depth of field --neg nsfw, nude", - "60": " a beautiful coconut --neg photo, realistic nsfw, nude", - "90": " a beautiful durian, amazing award winning photography --neg nsfw, nude" + "0": " Flying into Paul Laffoley visionary diagrammatic art, The Time Machine, a colossal cosmic mandala of sacred geometry, hand-lettered esoteric text borders glowing, concentric vesica-piscis portals, vivid primary red blue yellow on deep black, blueprint of a metaphysical device, full 3D depth, hyperdetailed psychotronic schematic --neg ugly, deformed, low detail, blurry, modern typography, messy text, photograph, normal people nsfw, nude nsfw, nude", + "700": " Flying through Paul Laffoley The Orgone Motor, an isometric axonometric 3D lattice cube of glowing structural beams, divine invariance machine, psychotronic generator architecture, vivid primary-color blueprint diagram come alive in three dimensions, hand-lettered annotations, sacred geometric engineering --neg ugly, deformed, low detail, blurry, modern typography, messy text, photograph, normal people nsfw, nude nsfw, nude", + "1400": " Penetrating a radiating sun-ray vortex of Paul Laffoley sacred geometry, ouroboros snakes coiling around a central singularity, alchemical time-portal, dense hand-lettered cosmic diagram borders, vivid visionary blueprint, full dimensional depth, hyperdetailed esoteric mandala --neg ugly, deformed, low detail, blurry, modern typography, messy text, photograph, normal people nsfw, nude nsfw, nude", + "2100": " Flying through Paul Laffoley The Fourth Living Creature, a winged geometric deity of concentric mandala wings, Egyptian-cosmic fusion, sacred hieroglyphic borders, vivid primary visionary painting rendered in full 3D dimensional depth, glowing diagrammatic linework --neg ugly, deformed, low detail, blurry, modern typography, messy text, photograph, normal people nsfw, nude nsfw, nude", + "2800": " Climbing through a Paul Laffoley psychotronic cathedral, blueprint schematics of impossible time-machines extruding into 3D architecture, glowing measurement diagrams, esoteric hand-lettered text annotations floating in space, vivid primary color visionary engineering --neg ugly, deformed, low detail, blurry, modern typography, messy text, photograph, normal people nsfw, nude nsfw, nude", + "3500": " Diving into Paul Laffoley Kyklos of Hermocrates, a great wheel-mandala of cyclical time, radial spokes of sacred geometry, diagrammatic cosmology rendered as a spinning dimensional gateway, vivid concentric color rings, full 3D flythrough depth --neg ugly, deformed, low detail, blurry, modern typography, messy text, photograph, normal people nsfw, nude nsfw, nude", + "4200": " Soaring through a Paul Laffoley dimensional grid of nested geometric solids, tetrakishexahedron and heptahedron forms glowing in axonometric projection, time-machine lattice architecture, vivid primary blueprint diagram in full 3D --neg ugly, deformed, low detail, blurry, modern typography, messy text, photograph, normal people nsfw, nude nsfw, nude", + "4900": " Flying through a Paul Laffoley cosmic eye-mandala, concentric iris of sacred geometry, radiating golden ratio spokes, esoteric text encircling the pupil-singularity, vivid visionary diagram, hyperdimensional time-portal depth --neg ugly, deformed, low detail, blurry, modern typography, messy text, photograph, normal people nsfw, nude nsfw, nude", + "5600": " Penetrating a Paul Laffoley vivid chromatic time-tunnel, walls covered in dense diagrammatic sacred geometry and hand-lettered alchemical formulae, radiating perspective lines pulling to a central vanishing portal, full 3D flythrough --neg ugly, deformed, low detail, blurry, modern typography, messy text, photograph, normal people nsfw, nude nsfw, nude", + "6300": " Soaring into a Paul Laffoley perpetual motion device, interlocking geometric rotors of pure sacred mathematics, vivid primary-color schematic rendered as living 3D machinery, esoteric annotation borders, visionary blueprint depth --neg ugly, deformed, low detail, blurry, modern typography, messy text, photograph, normal people nsfw, nude nsfw, nude", + "7000": " Flying through a Paul Laffoley meditation device mandala, vast concentric portal of vivid sacred geometry, hypnotic radial symmetry, hand-lettered cosmic text borders glowing, visionary diagram opening into hyperdimensional depth, full 3D --neg ugly, deformed, low detail, blurry, modern typography, messy text, photograph, normal people nsfw, nude nsfw, nude", + "7700": " Final dive into the singularity of a Paul Laffoley cosmic diagram, all sacred geometry and time-machine schematics collapsing into one luminous central portal, vivid primary visionary apotheosis, esoteric text dissolving into pure dimensional light, transcendent 3D breakthrough --neg ugly, deformed, low detail, blurry, modern typography, messy text, photograph, normal people nsfw, nude nsfw, nude" }, "positive_prompts": "", "negative_prompts": "nsfw, nude", "animation_mode": "3D", - "max_frames": 120, - "border": "replicate", + "max_frames": 8000, + "border": "wrap", "angle": "0: (0)", "zoom": "0: (1.0025+0.002*sin(1.25*3.14*t/30))", - "translation_x": "0: (0)", - "translation_y": "0: (0)", - "translation_z": "0: (1.75)", + "translation_x": "0:(0)", + "translation_y": "0:(0)", + "translation_z": "0:(3), 60:(4.5), 7940:(2.5), 8000:(0)", "transform_center_x": "0: (0.5)", "transform_center_y": "0: (0.5)", - "rotation_3d_x": "0: (0)", - "rotation_3d_y": "0: (0)", - "rotation_3d_z": "0: (0)", + "rotation_3d_x": "0:(0), 100:(0.15), 500:(0.15), 600:(0), 700:(-0.15), 1100:(-0.15), 1200:(0), 2400:(0), 2500:(0.15), 2900:(0.15), 3000:(0), 3100:(-0.15), 3500:(-0.15), 3600:(0), 4800:(0), 4900:(0.15), 5300:(0.15), 5400:(0), 5500:(-0.15), 5900:(-0.15), 6000:(0), 7200:(0), 7300:(0.15), 7700:(0.15), 8000:(0)", + "rotation_3d_y": "0:(0)", + "rotation_3d_z": "0:(0), 1200:(0), 1300:(0.2), 1700:(0.2), 1800:(0), 2600:(-0.1), 3400:(-0.1), 3600:(0), 4800:(0), 4900:(0.2), 5300:(0.2), 5400:(0), 6200:(-0.1), 7000:(-0.1), 7200:(0), 8000:(0)", "enable_perspective_flip": false, "perspective_flip_theta": "0: (0)", "perspective_flip_phi": "0: (0)", "perspective_flip_gamma": "0: (0)", "perspective_flip_fv": "0: (53)", - "noise_schedule": "0: (0.065)", + "noise_schedule": "0: (0.01)", "strength_schedule": "0: (0.65)", "contrast_schedule": "0: (1.0)", - "cfg_scale_schedule": "0: (7)", + "cfg_scale_schedule": "0: (6)", "enable_steps_scheduling": false, "steps_schedule": "0: (25)", - "fov_schedule": "0: (70)", + "fov_schedule": "0: (120)", "aspect_ratio_schedule": "0: (1)", "aspect_ratio_use_old_formula": false, - "near_schedule": "0: (200)", - "far_schedule": "0: (10000)", + "near_schedule": "0: (50)", + "far_schedule": "0: (20000)", "seed_schedule": "0:(s), 1:(-1), \"max_f-2\":(-1), \"max_f-1\":(s)", "pix2pix_img_cfg_scale_schedule": "0:(1.5)", "enable_subseed_scheduling": false, @@ -81,15 +90,15 @@ "checkpoint_schedule": "0: (\"model1.ckpt\"), 100: (\"model2.safetensors\")", "enable_clipskip_scheduling": false, "clipskip_schedule": "0: (2)", - "enable_noise_multiplier_scheduling": true, - "noise_multiplier_schedule": "0: (1.05)", + "enable_noise_multiplier_scheduling": false, + "noise_multiplier_schedule": "0: (1.01)", "resume_from_timestring": false, - "resume_timestring": "20230129210106", + "resume_timestring": "", "enable_ddim_eta_scheduling": false, "ddim_eta_schedule": "0: (0)", "enable_ancestral_eta_scheduling": false, "ancestral_eta_schedule": "0: (1)", - "amount_schedule": "0: (0.1)", + "amount_schedule": "0: (1.0)", "kernel_schedule": "0: (5)", "sigma_schedule": "0: (1)", "threshold_schedule": "0: (0)", @@ -98,10 +107,10 @@ "color_coherence_video_every_N_frames": 1, "color_force_grayscale": false, "legacy_colormatch": false, - "diffusion_cadence": 2, - "optical_flow_cadence": "None", + "diffusion_cadence": 6, + "optical_flow_cadence": "DIS Fine", "cadence_flow_factor_schedule": "0: (1)", - "optical_flow_redo_generation": "None", + "optical_flow_redo_generation": "DIS Fine", "redo_flow_factor_schedule": "0: (1)", "diffusion_redo": "0", "noise_type": "perlin", @@ -143,10 +152,10 @@ "hybrid_comp_save_extra_frames": false, "parseq_manifest": "", "parseq_use_deltas": true, - "parseq_non_schedule_overrides": true, - "use_looper": false, - "init_images": "{\n \"0\": \"https://deforum.github.io/a1/Gi1.png\",\n \"max_f/4-5\": \"https://deforum.github.io/a1/Gi2.png\",\n \"max_f/2-10\": \"https://deforum.github.io/a1/Gi3.png\",\n \"3*max_f/4-15\": \"https://deforum.github.io/a1/Gi4.jpg\",\n \"max_f-20\": \"https://deforum.github.io/a1/Gi1.png\"\n}", - "image_strength_schedule": "0:(0.75)", + "parseq_non_schedule_overrides": true, + "use_looper": true, + "init_images": "{\n \"0\": \"F:/AI Images/Laffoley Time Machines/00.1-840x841.jpg\",\n \"700\": \"F:/AI Images/Laffoley Time Machines/04web_TheOrgoneMotorA.jpg\",\n \"1400\": \"F:/AI Images/Laffoley Time Machines/tumblr_nmux6jHetX1rtynt1o1_1280.jpg\",\n \"2100\": \"F:/AI Images/Laffoley Time Machines/kentfineart-paul-laffoley-the-fourth-living-creature-1975.jpg\",\n \"2800\": \"F:/AI Images/Laffoley Time Machines/05_laffoley.jpg\",\n \"3500\": \"F:/AI Images/Laffoley Time Machines/laffoley Kyklos of Hermocrates.jpg\",\n \"4200\": \"F:/AI Images/Laffoley Time Machines/PL11.webp\",\n \"4900\": \"F:/AI Images/Laffoley Time Machines/PL9.webp\",\n \"5600\": \"F:/AI Images/Laffoley Time Machines/Paul_Laffoley_niji_6.webp\",\n \"6300\": \"F:/AI Images/Laffoley Time Machines/Paul_Laffoley_sdxl.jpg\",\n \"7000\": \"F:/AI Images/Laffoley Time Machines/Paul_Laffoley_v6.webp\",\n \"7700\": \"F:/AI Images/Laffoley Time Machines/a4789610336219d061026dde2b00b2f6.jpg\"\n}", + "image_strength_schedule": "0:(0.60)", "blendFactorMax": "0:(0.35)", "blendFactorSlope": "0:(0.25)", "tweening_frames_schedule": "0:(20)", @@ -237,7 +246,7 @@ "cn_5_control_mode": "Balanced", "cn_5_loopback_mode": false, "skip_video_creation": false, - "fps": 15, + "fps": 30, "make_gif": false, "delete_imgs": false, "delete_input_frames": false, @@ -254,7 +263,7 @@ "frame_interpolation_slow_mo_amount": 2, "frame_interpolation_keep_imgs": true, "frame_interpolation_use_upscaled": false, - "sd_model_name": "revAnimated_v122.safetensors", - "sd_model_hash": "3f4fefd9", - "deforum_git_commit_id": "eb16c856" + "sd_model_name": "MOHAWK_v20.safetensors", + "sd_model_hash": "1a89f0fb", + "deforum_git_commit_id": "5d63a339" } \ No newline at end of file diff --git a/scripts/deforum_helpers/args.py b/scripts/deforum_helpers/args.py index 5be0b3ea..334ad467 100644 --- a/scripts/deforum_helpers/args.py +++ b/scripts/deforum_helpers/args.py @@ -74,7 +74,7 @@ def DeforumAnimArgs(): "type": "radio", "choices": ['replicate', 'wrap'], "value": "replicate", - "info": "controls pixel generation method for images smaller than the frame. hover on the options to see more info" + "info": "how edge pixels are handled when the warped canvas doesn't fill the frame. 'replicate' stretches the nearest edge pixel (safe default, no seams). 'wrap' tiles the opposite edge. SUGGESTED: wrap — the proven setting for the smooth psychedelic long-form renders." }, "angle": { "label": "Angle", @@ -107,7 +107,7 @@ def DeforumAnimArgs(): "label": "Translation Z", "type": "textbox", "value": "0: (1.75)", - "info": "move canvas towards/away from view [speed set by FOV]" + "info": "move canvas towards/away from view [speed set by FOV]. SUGGESTED (smooth long-form): 0: (2.25) — slow steady push-in." }, "transform_center_x": { "label": "Transform Center X", @@ -144,25 +144,25 @@ def DeforumAnimArgs(): "label": "Enable perspective flip", "type": "checkbox", "value": False, - "info": "" + "info": "enables 2D perspective warp to simulate 3D-like movement without using depth maps. Good for stylized 2D animations." }, "perspective_flip_theta": { "label": "Perspective flip theta", "type": "textbox", "value": "0: (0)", - "info": "" + "info": "tilt angle (X-axis pitch) for 2D perspective warp. Positive tilts forward, negative tilts back." }, "perspective_flip_phi": { "label": "Perspective flip phi", "type": "textbox", "value": "0: (0)", - "info": "" + "info": "horizontal lean angle (Y-axis yaw) for 2D perspective warp. Simulates left/right head tilt." }, "perspective_flip_gamma": { "label": "Perspective flip gamma", "type": "textbox", "value": "0: (0)", - "info": "" + "info": "roll angle (Z-axis rotation) for 2D perspective warp." }, "perspective_flip_fv": { "label": "Perspective flip tv", @@ -174,26 +174,26 @@ def DeforumAnimArgs(): "label": "Noise schedule", "type": "textbox", "value": "0: (0.065)", - "info": "" + "info": "amount of noise added per frame. Higher = more flicker/drift. SUGGESTED (proven smooth value): 0.01 — low per-frame noise keeps long renders stable." }, "strength_schedule": { "label": "Strength schedule", "type": "textbox", "value": "0: (0.65)", - "info": "amount of presence of previous frame to influence next frame, also controls steps in the following formula [steps - (strength_schedule * steps)]" + "info": "amount of presence of previous frame to influence next frame, also controls steps via [steps - (strength_schedule * steps)]. SUGGESTED (smooth long-form): 0.7. For vid2vid melt, 0.7-0.8." }, "contrast_schedule": "0: (1.0)", "cfg_scale_schedule": { "label": "CFG scale schedule", "type": "textbox", "value": "0: (7)", - "info": "how closely the image should conform to the prompt. Lower values produce more creative results. (recommended range 5-15)`" + "info": "how closely the image should conform to the prompt. Lower = more creative. SUGGESTED (proven value): 8. (range 5-15)`" }, "enable_steps_scheduling": { "label": "Enable steps scheduling", "type": "checkbox", "value": False, - "info": "" + "info": "allows changing the diffusion step count per keyframe. Mainly useful for unlocking step counts above 200. Otherwise behaves similarly to strength schedule — more steps = more detail but slower renders. Default GitHub value: disabled." }, "steps_schedule": { "label": "Steps schedule", @@ -205,7 +205,7 @@ def DeforumAnimArgs(): "label": "FOV schedule", "type": "textbox", "value": "0: (70)", - "info": "adjusts the scale at which the canvas is moved in 3D by the translation_z value. [Range -180 to +180, with 0 being undefined. Values closer to 180 will make the image have less depth, while values closer to 0 will allow more depth]" + "info": "adjusts the scale at which the canvas is moved in 3D by the translation_z value. [Range -180 to +180, with 0 being undefined. Values closer to 180 will make the image have less depth, while values closer to 0 will allow more depth]. SUGGESTED (smooth long-form): 80." }, "aspect_ratio_schedule": { "label": "Aspect Ratio schedule", @@ -223,19 +223,19 @@ def DeforumAnimArgs(): "label": "Near schedule", "type": "textbox", "value": "0: (200)", - "info": "" + "info": "near clipping plane distance for 3D depth warping. SUGGESTED (proven smooth value): 100. (GitHub default is 200; higher pushes the cutoff back, very low values cause near-plane popping.)" }, "far_schedule": { "label": "Far schedule", "type": "textbox", "value": "0: (10000)", - "info": "" + "info": "far clipping plane distance for 3D depth warping. Controls how far into the scene depth calculations reach. Default GitHub value is 10000. SUGGESTED (proven value): 20000. Rarely needs changing unless you see depth artifacts on distant backgrounds." }, "seed_schedule": { "label": "Seed schedule", "type": "textbox", "value": '0:(s), 1:(-1), "max_f-2":(-1), "max_f-1":(s)', - "info": "" + "info": "keyframe specific seed values. Only active when Seed behavior is set to 'schedule'. Use -1 for random per frame, or set an exact integer to lock a frame to a specific seed. Default wraps: starts and ends on the initial seed (s), random in between." }, "pix2pix_img_cfg_scale_schedule": { "label": "Pix2Pix img CFG schedule", @@ -247,25 +247,25 @@ def DeforumAnimArgs(): "label": "Enable Subseed scheduling", "type": "checkbox", "value": False, - "info": "" + "info": "enables per-frame control of a secondary seed that blends with the main seed. Useful for subtle variation without full randomness. Default GitHub value: disabled." }, "subseed_schedule": { "label": "Subseed schedule", "type": "textbox", "value": "0: (1)", - "info": "" + "info": "the secondary seed value to blend with the main seed each frame. Only active when 'Enable Subseed scheduling' is checked." }, "subseed_strength_schedule": { "label": "Subseed strength schedule", "type": "textbox", "value": "0: (0)", - "info": "" + "info": "how strongly the subseed influences each frame (0=none, 1=full). At 0 the subseed has no effect. Blend in gradually (e.g. 0.1–0.3) for subtle organic variation without breaking temporal coherence." }, "enable_sampler_scheduling": { "label": "Enable sampler scheduling", "type": "checkbox", "value": False, - "info": "" + "info": "allows switching samplers mid-render at specific keyframes. Rarely needed — only use if you want a deliberate style shift at a known frame. Default GitHub value: disabled." }, "sampler_schedule": { "label": "Sampler schedule", @@ -277,25 +277,25 @@ def DeforumAnimArgs(): "label": "Use noise mask", "type": "checkbox", "value": False, - "info": "" + "info": "applies a video mask to control where noise is injected each frame. When enabled, noise only appears in unmasked regions. Requires a mask video source. Default GitHub value: disabled." }, "mask_schedule": { "label": "Mask schedule", "type": "textbox", "value": '0: ("{video_mask}")', - "info": "" + "info": "keyframed mask values. Points to a video mask file that controls which areas of the frame are affected by generation. Only relevant when using Video Input mode or noise masking." }, "noise_mask_schedule": { "label": "Noise mask schedule", "type": "textbox", "value": '0: ("{video_mask}")', - "info": "" + "info": "same as mask schedule but applied specifically to noise injection rather than the full generation. Lets you add noise only in certain regions of the frame." }, "enable_checkpoint_scheduling": { "label": "Enable checkpoint scheduling", "type": "checkbox", "value": False, - "info": "" + "info": "allows switching to a completely different model checkpoint at specific keyframes. Powerful for style shifts mid-render but can cause jarring visual discontinuity. Default GitHub value: disabled." }, "checkpoint_schedule": { "label": "allows keyframing different sd models. Use *full* name as appears in ui dropdown", @@ -307,25 +307,25 @@ def DeforumAnimArgs(): "label": "Enable CLIP skip scheduling", "type": "checkbox", "value": False, - "info": "" + "info": "allows changing CLIP skip per keyframe. CLIP skip controls how many layers from the end of the CLIP text encoder are skipped — higher values (2–4) produce more abstract/loose prompt interpretation, lower values (1) follow prompts more precisely. Default GitHub value: disabled." }, "clipskip_schedule": { "label": "CLIP skip schedule", "type": "textbox", "value": "0: (2)", - "info": "" + "info": "CLIP skip value per keyframe. 1 = full prompt adherence (SD 1.x default). 2 = slightly looser, often used with anime/stylized models. Higher values increasingly ignore fine prompt detail. Only active when 'Enable CLIP skip scheduling' is checked." }, "enable_noise_multiplier_scheduling": { "label": "Enable noise multiplier scheduling", "type": "checkbox", "value": True, - "info": "" + "info": "enables per-frame control of a noise multiplier applied on top of the noise schedule. Default GitHub value: enabled at 1.05. When disabled, noise_schedule values are used as-is with no multiplier." }, "noise_multiplier_schedule": { "label": "Noise multiplier schedule", "type": "textbox", "value": "0: (1.05)", - "info": "" + "info": "scales the noise_schedule value by this multiplier each frame. 1.0 = no change. Values above 1.0 add slightly more noise than scheduled (1.05 is the default — a small boost for organic texture). Values below 1.0 reduce noise further. Only active when 'Enable noise multiplier scheduling' is checked." }, "resume_from_timestring": { "label": "Resume from timestring", @@ -395,7 +395,7 @@ def DeforumAnimArgs(): "type": "dropdown", "choices": ['None', 'HSV', 'LAB', 'RGB', 'Video Input', 'Image'], "value": "LAB", - "info": "choose an algorithm/ method for keeping color coherence across the animation" + "info": "keeps colors consistent across frames. SUGGESTED (proven value): LAB — locks the palette for smooth long-form. HSV preserves hue/sat, RGB simplest. None = colors drift (use None for vid2vid so it follows the source video)." }, "color_coherence_image_path": { "label": "Color coherence image path", @@ -429,14 +429,14 @@ def DeforumAnimArgs(): "maximum": 50, "step": 1, "value": 2, - "info": "# of in-between frames that will not be directly diffused" + "info": "how many in-between frames are generated via warping only (no diffusion). Higher = faster, smoother, less detail per frame. SUGGESTED (proven smooth long-form): 8 — strong consistency for long psychedelic renders. For vid2vid use 1-2 so it tracks the source video." }, "optical_flow_cadence": { "label": "Optical flow cadence", "type": "dropdown", "choices": ['None', 'RAFT', 'DIS Medium', 'DIS Fine', 'Farneback'], "value": "None", - "info": "use optical flow estimation for your in-between (cadence) frames" + "info": "uses optical flow to generate smoother in-between (cadence) frames. RAFT = highest quality/slowest. DIS Fine = good balance. Farneback = fastest. None = simple warping." }, "cadence_flow_factor_schedule": { "label": "Cadence flow factor schedule", @@ -517,8 +517,8 @@ def DeforumAnimArgs(): "type": "number", "precision": None, "value": 0.2, - "info": "sets a midpoint at which a depth-map is to be drawn: range [-1 to +1]", - "visible": False + "info": "sets a midpoint at which a depth-map is to be drawn: range [-1 to +1]. SUGGESTED (signature look): -0.3 — negative inverts the depth for the psychedelic inside-out warp (intentional, not a bug). Positive ~0.4 = conventional 3D depth.", + "visible": True }, "padding_mode": { "label": "Padding mode", @@ -543,7 +543,7 @@ def DeforumAnimArgs(): "video_init_path": { "label": "Video init path/ URL", "type": "textbox", - "value": 'https://deforum.github.io/a1/V1.mp4', + "value": '', "info": "" }, "extract_nth_frame": { @@ -582,14 +582,14 @@ def DeforumAnimArgs(): "video_mask_path": { "label": "Video mask path", "type": "textbox", - "value": 'https://deforum.github.io/a1/VM1.mp4', + "value": '', "info": "" }, "hybrid_comp_alpha_schedule": { "label": "Comp alpha schedule", "type": "textbox", "value": "0:(0.5)", - "info": "" + "info": "blend between source video and generated image when compositing. Higher (0.65-0.8) = footage shows through more (follows the video); lower = more new generated detail. The main follow-vs-transform dial for hybrid. SUGGESTED: 0.65." }, "hybrid_comp_mask_blend_alpha_schedule": { "label": "Comp mask blend alpha schedule", @@ -619,26 +619,26 @@ def DeforumAnimArgs(): "label": "Flow factor schedule", "type": "textbox", "value": "0:(1)", - "info": "" + "info": "strength of the optical-flow motion borrowed from the video. 1.0 = full video motion; lower dampens it. SUGGESTED: 1.0." }, "hybrid_generate_inputframes": { "label": "Generate inputframes", "type": "checkbox", "value": False, - "info": "" + "info": "extract frames from your video for hybrid processing. MUST be ON to use Hybrid Video. Pairs with the Video init path." }, "hybrid_generate_human_masks": { "label": "Generate human masks", "type": "radio", "choices": ['None', 'PNGs', 'Video', 'Both'], "value": "None", - "info": "" + "info": "auto-generate masks of people in the video. Only needed if compositing or protecting human subjects. Leave None unless required." }, "hybrid_use_first_frame_as_init_image": { "label": "First frame as init image", "type": "checkbox", "value": True, - "info": "", + "info": "use the first extracted video frame as the init for frame 0. RECOMMENDED on for vid2vid so the animation starts from your footage.", "visible": False }, "hybrid_motion": { @@ -646,20 +646,20 @@ def DeforumAnimArgs(): "type": "radio", "choices": ['None', 'Optical Flow', 'Perspective', 'Affine'], "value": "None", - "info": "" + "info": "how the video motion drives the animation. Optical Flow (recommended) smoothly follows the video movement - the key to smooth hybrid vid2vid. Perspective/Affine track via matched points. None = no borrowed motion." }, "hybrid_motion_use_prev_img": { "label": "Motion use prev img", "type": "checkbox", "value": False, - "info": "", + "info": "calculate motion against the previous GENERATED frame instead of the previous video frame. Can improve coherence on heavily stylized output.", "visible": False }, "hybrid_flow_consistency": { "label": "Flow consistency mask", "type": "checkbox", "value": False, - "info": "", + "info": "generate a consistency mask that reduces optical-flow ghosting/artifacts on fast or complex motion.", "visible": False }, "hybrid_consistency_blur": { @@ -676,7 +676,7 @@ def DeforumAnimArgs(): "type": "radio", "choices": ['RAFT', 'DIS Medium', 'DIS Fine', 'Farneback'], "value": "RAFT", - "info": "", + "info": "the optical-flow algorithm. DIS Medium (recommended) = good speed/quality balance. RAFT = highest quality, slower. DIS Fine = sharper, slower. Farneback = fastest, roughest.", "visible": False }, "hybrid_composite": 'None', # ['None', 'Normal', 'Before Motion', 'After Generation'] @@ -684,7 +684,7 @@ def DeforumAnimArgs(): "label": "Use init image as video", "type": "checkbox", "value": False, - "info": "", + "info": "use a static init image as the hybrid source instead of the video. Leave off for normal vid2vid.", }, "hybrid_comp_mask_type": { "label": "Comp mask type", @@ -791,7 +791,7 @@ def DeforumArgs(): "type": "radio", "choices": ['iter', 'fixed', 'random', 'ladder', 'alternate', 'schedule'], "value": "iter", - "info": "controls the seed behavior that is used for animation. Hover on the options to see more info" + "info": "iter = seed increments each frame (smooth evolution). fixed = same seed every frame (stable). random = new seed every frame (chaotic). schedule = set seed per keyframe for full control." }, "seed_iter_N": { "label": "Seed iter N", @@ -824,7 +824,7 @@ def DeforumArgs(): "init_image": { "label": "Init image URL", "type": "textbox", - "value": "https://deforum.github.io/a1/I1.png", + "value": "", "info": "Use web address or local path. Note: if the image box below is used then this field is ignored." }, "init_image_box": { @@ -850,7 +850,7 @@ def DeforumArgs(): "mask_file": { "label": "Mask file", "type": "textbox", - "value": "https://deforum.github.io/a1/M1.jpg", + "value": "", "info": "" }, "invert_mask": { @@ -914,14 +914,14 @@ def DeforumArgs(): "type": "radio", "choices": ['reroll', 'interrupt', 'ignore'], "value": "ignore", - "info": "" + "info": "what to do if a frame comes out nearly black/blank. 'reroll' re-generates the frame with a new seed and tries again (up to Patience attempts). 'interrupt' stops the entire render when a blank is detected. 'ignore' keeps the blank frame and continues — safest for long unattended renders. Default GitHub value: ignore." }, "reroll_patience": { "label": "Reroll patience", "type": "number", "precision": None, "value": 10, - "info": "" + "info": "how many times to re-generate a blank frame before giving up. Only matters when 'Reroll blank frames' is set to 'reroll'. If all attempts still produce a blank, Deforum falls back to using the last good frame. Default GitHub value: 10." }, "motion_preview_mode": { "label": "Motion preview mode (dry run).", @@ -1008,6 +1008,7 @@ def DeforumOutputArgs(): "maximum": 240, "step": 1, "value": 15, + "info": "frames per second of the output video. MATCH your source video fps for vid2vid so timing and playback speed are correct.", }, "make_gif": { "label": "Make GIF", @@ -1042,7 +1043,7 @@ def DeforumOutputArgs(): "soundtrack_path": { "label": "Soundtrack path", "type": "textbox", - "value": "https://deforum.github.io/a1/A1.mp3", + "value": "", "info": "abs. path or url to audio file" }, "r_upscale_video": { @@ -1056,12 +1057,14 @@ def DeforumOutputArgs(): "type": "dropdown", "choices": ['x2', 'x3', 'x4'], "value": "x2", + "info": "how much to upscale output. Use x2-x3 to take a 720p render up to 1080p+.", }, "r_upscale_model": { "label": "Upscale model", "type": "dropdown", "choices": ['realesr-animevideov3', 'realesrgan-x4plus', 'realesrgan-x4plus-anime'], "value": 'realesr-animevideov3', + "info": "the upscaler. realesr-animevideov3 suits stylized/animated content; realesrgan-x4plus for photoreal.", }, "r_upscale_keep_imgs": { "label": "Keep Imgs", @@ -1081,7 +1084,7 @@ def DeforumOutputArgs(): "type": "radio", "choices": ['None', 'RIFE v4.6', 'FILM'], "value": "None", - "info": "select the frame interpolation engine. hover on the options for more info" + "info": "post-render smoothing pass. RIFE v4.6 (recommended) generates smooth in-between frames - great for de-janking vid2vid. FILM = slower, better for big morphs. Makes a smoothed video alongside the raw one. SUGGESTED: RIFE v4.6 + Interp X 2-4." }, "frame_interpolation_x_amount": { "label": "Interp X", @@ -1090,6 +1093,7 @@ def DeforumOutputArgs(): "maximum": 10, "step": 1, "value": 2, + "info": "how many smooth in-between frames RIFE/FILM generates per rendered frame. 2 = doubles the framerate. SUGGESTED: 2-4 to smooth janky vid2vid.", }, "frame_interpolation_slow_mo_enabled": { "label": "Slow-Mo", diff --git a/scripts/deforum_helpers/deforum_controlnet.py b/scripts/deforum_helpers/deforum_controlnet.py index cef20cbc..302c81ba 100644 --- a/scripts/deforum_helpers/deforum_controlnet.py +++ b/scripts/deforum_helpers/deforum_controlnet.py @@ -120,36 +120,36 @@ def build_sliders(module, pp): def create_model_in_tab_ui(cn_id): with gr.Row(): - enabled = gr.Checkbox(label="Enable", value=False, interactive=True) - pixel_perfect = gr.Checkbox(label="Pixel Perfect", value=False, visible=False, interactive=True) - low_vram = gr.Checkbox(label="Low VRAM", value=False, visible=False, interactive=True) - overwrite_frames = gr.Checkbox(label='Overwrite input frames', value=True, visible=False, interactive=True) + enabled = gr.Checkbox(label="Enable", value=False, interactive=True, info="turn this ControlNet unit on. Each unit guides generation from your video with a different model (depth, tile, openpose, temporalnet, etc.).") + pixel_perfect = gr.Checkbox(label="Pixel Perfect", value=False, visible=False, interactive=True, info="auto-matches the preprocessor resolution to your output size. RECOMMENDED: on. Overrides the Annotator resolution slider.") + low_vram = gr.Checkbox(label="Low VRAM", value=False, visible=False, interactive=True, info="splits CN processing to save VRAM. Only enable if you get out-of-memory errors - it slows rendering. Leave off on 16GB+.") + overwrite_frames = gr.Checkbox(label='Overwrite input frames', value=True, visible=False, interactive=True, info="re-extract this unit's input frames from the video each run. Leave ON unless you prepared frames manually.") with gr.Row(visible=False) as mod_row: - module = gr.Dropdown(cn_preprocessors, label=f"Preprocessor", value="none", interactive=True) - model = gr.Dropdown(cn_models, label=f"Model", value="None", interactive=True) + module = gr.Dropdown(cn_preprocessors, label=f"Preprocessor", value="none", interactive=True, info="how the input frame is processed before CN sees it (depth_anything_v2=depth map, tile_resample=tile, openpose_full=pose). MUST match the Model family. Use 'none' for models that take the raw frame (ip2p, temporalnet, QR Monster).") + model = gr.Dropdown(cn_models, label=f"Model", value="None", interactive=True, info="the ControlNet model. Must match the preprocessor family AND your checkpoint architecture - SD1.5 CN models only work with SD1.5 checkpoints, SDXL CN only with SDXL.") refresh_models = ToolButton(value=refresh_symbol) refresh_models.click(refresh_all_models, model, model) with gr.Row(visible=False) as weight_row: - weight = gr.Textbox(label="Weight schedule", lines=1, value='0:(1)', interactive=True) + weight = gr.Textbox(label="Weight schedule", lines=1, value='0:(1)', interactive=True, info="how strongly this unit influences the image. 0.3-0.5 = light (more melt/freedom), 0.7-1.0 = strong structural lock. Schedulable: '0:(0.5), 1000:(0.8)'.") with gr.Row(visible=False) as start_cs_row: - guidance_start = gr.Textbox(label="Starting Control Step schedule", lines=1, value='0:(0.0)', interactive=True) + guidance_start = gr.Textbox(label="Starting Control Step schedule", lines=1, value='0:(0.0)', interactive=True, info="at what fraction of the diffusion steps this unit STARTS applying. 0.0 = from the first step. Raise for more early creative freedom.") with gr.Row(visible=False) as end_cs_row: - guidance_end = gr.Textbox(label="Ending Control Step schedule", lines=1, value='0:(1.0)', interactive=True) + guidance_end = gr.Textbox(label="Ending Control Step schedule", lines=1, value='0:(1.0)', interactive=True, info="at what fraction of steps this unit STOPS applying. 1.0 = all the way. Lower (0.8) to free up fine detail at the end.") model_dropdowns.append(model) with gr.Column(visible=False) as advanced_column: - processor_res = gr.Slider(label="Annotator resolution", value=64, minimum=64, maximum=2048, interactive=False) + processor_res = gr.Slider(label="Annotator resolution", value=64, minimum=64, maximum=2048, interactive=False, info="resolution the preprocessor runs at. Match output size (1024 for SDXL, 512-768 for SD1.5). Pixel Perfect overrides this.") threshold_a = gr.Slider(label="Threshold A", value=64, minimum=64, maximum=1024, interactive=False) threshold_b = gr.Slider(label="Threshold B", value=64, minimum=64, maximum=1024, interactive=False) with gr.Row(visible=False) as vid_path_row: - vid_path = gr.Textbox(value='', label="ControlNet Input Video/ Image Path", interactive=True) + vid_path = gr.Textbox(value='', label="ControlNet Input Video/ Image Path", interactive=True, info="path to the video this unit reads for vid2vid - usually the SAME clip as your main Video init path. Leave empty if LoopBack mode is on.") with gr.Row(visible=False) as mask_vid_path_row: # invisible temporarily since 26-04-23 until masks are fixed mask_vid_path = gr.Textbox(value='', label="ControlNet Mask Video/ Image Path (*NOT WORKING, kept in UI for CN's devs testing!*)", interactive=True) with gr.Row(visible=False) as control_mode_row: - control_mode = gr.Radio(choices=["Balanced", "My prompt is more important", "ControlNet is more important"], value="Balanced", label="Control Mode", interactive=True) + control_mode = gr.Radio(choices=["Balanced", "My prompt is more important", "ControlNet is more important"], value="Balanced", label="Control Mode", interactive=True, info="balance of prompt vs ControlNet. Balanced (recommended) = equal. 'My prompt is more important' = looser structure/more style. 'ControlNet is more important' = strong structural lock.") with gr.Row(visible=False) as env_row: - resize_mode = gr.Radio(choices=["Outer Fit (Shrink to Fit)", "Inner Fit (Scale to Fit)", "Just Resize"], value="Inner Fit (Scale to Fit)", label="Resize Mode", interactive=True) + resize_mode = gr.Radio(choices=["Outer Fit (Shrink to Fit)", "Inner Fit (Scale to Fit)", "Just Resize"], value="Inner Fit (Scale to Fit)", label="Resize Mode", interactive=True, info="how the input fits the canvas when aspect ratios differ. 'Inner Fit' (recommended) scales to fit; 'Just Resize' stretches; 'Outer Fit' shrinks to fit.") with gr.Row(visible=False) as control_loopback_row: - loopback_mode = gr.Checkbox(label="LoopBack mode", value=False, interactive=True) + loopback_mode = gr.Checkbox(label="LoopBack mode", value=False, interactive=True, info="feeds the PREVIOUS generated frame into this unit instead of the source video. Essential for TemporalNet (anti-flicker). When on, leave the video path empty.") hide_output_list = [pixel_perfect, low_vram, mod_row, module, weight_row, start_cs_row, end_cs_row, env_row, overwrite_frames, vid_path_row, control_mode_row, mask_vid_path_row, control_loopback_row] # add mask_vid_path_row when masks are working again for cn_output in hide_output_list: @@ -318,9 +318,18 @@ def create_cnu_dict(cn_args, prefix, img_np, mask_np, frame_idx, CnSchKeys): cnet.update_cn_script_in_processing(p, cn_units, is_img2img=is_img2img, is_ui=False) def find_controlnet_script(p): - controlnet_script = next((script for script in p.scripts.alwayson_scripts if script.title().lower() == "controlnet"), None) + controlnet_script = next((script for script in p.scripts.alwayson_scripts if script.title().lower() == "controlnet"), None) if not controlnet_script: - raise Exception("ControlNet script not found.") + registered = [] + for s in p.scripts.alwayson_scripts: + try: + registered.append(s.title()) + except Exception: + registered.append("") + raise Exception( + f"ControlNet script not found. {len(p.scripts.alwayson_scripts)} alwayson scripts registered: {', '.join(registered)}. " + "Check the WebUI terminal for ControlNet load errors at startup (e.g. mediapipe version conflicts)." + ) return controlnet_script def process_controlnet_input_frames(args, anim_args, controlnet_args, video_path, mask_path, outdir_suffix, id): diff --git a/scripts/deforum_helpers/gradio_funcs.py b/scripts/deforum_helpers/gradio_funcs.py index 0cf70b52..57234427 100644 --- a/scripts/deforum_helpers/gradio_funcs.py +++ b/scripts/deforum_helpers/gradio_funcs.py @@ -226,6 +226,56 @@ def disable_by_hybrid_composite_dynamic(choice, comp_mask_type): def disable_by_non_optical_flow(choice): return gr.update(visible=False) if choice != 'Optical Flow' else gr.update(visible=True) +# Settings Sync functions for Editor and Upload +def sync_ui_to_editor(*args): + import json + from .args import get_settings_component_names, DeforumArgs, DeforumAnimArgs, ParseqArgs, LoopArgs, DeforumOutputArgs, pack_args + from .deforum_controlnet import controlnet_component_names + from .settings import get_keys_to_exclude + + settings_component_names = get_settings_component_names() + data = {settings_component_names[i]: args[i] for i in range(len(settings_component_names))} + + args_dict = pack_args(data, DeforumArgs) + anim_args_dict = pack_args(data, DeforumAnimArgs) + parseq_dict = pack_args(data, ParseqArgs) + try: + args_dict["prompts"] = json.loads(data.get('animation_prompts', '{}')) + except: + args_dict["prompts"] = {} + args_dict["animation_prompts_positive"] = data.get('animation_prompts_positive', '') + args_dict["animation_prompts_negative"] = data.get('animation_prompts_negative', '') + loop_dict = pack_args(data, LoopArgs) + controlnet_dict = pack_args(data, controlnet_component_names) + video_args_dict = pack_args(data, DeforumOutputArgs) + + combined = {**args_dict, **anim_args_dict, **parseq_dict, **loop_dict, **controlnet_dict, **video_args_dict} + exclude_keys = get_keys_to_exclude() + filtered_combined = {k: v for k, v in combined.items() if k not in exclude_keys} + + return json.dumps(filtered_combined, ensure_ascii=False, indent=4) + +def sync_editor_to_ui(json_str, *args): + import json + from .settings import load_all_settings + jdata = json.loads(json_str) if isinstance(json_str, str) else json_str + # ui_launch=False returns a list of values matching the components, plus an empty string for the path at the end. + # We slice [:-1] to remove the empty string and match the exact length of settings_component_list. + return load_all_settings(None, *args, ui_launch=False, jdata=jdata)[:-1] + +def process_settings_upload(file_obj, *args): + import json + if not file_obj: + return [gr.update() for _ in args] + try: + with open(file_obj.name, 'r', encoding='utf-8') as f: + jdata = json.load(f) + from .settings import load_all_settings + return load_all_settings(None, *args, ui_launch=False, jdata=jdata)[:-1] + except Exception as e: + print(f"Error loading settings from file upload: {e}") + return [gr.update() for _ in args] + # Upscaling Gradio UI related funcs def vid_upscale_gradio_update_stats(vid_path, upscale_factor): if not vid_path: diff --git a/scripts/deforum_helpers/render.py b/scripts/deforum_helpers/render.py index 964498c3..eb489bab 100644 --- a/scripts/deforum_helpers/render.py +++ b/scripts/deforum_helpers/render.py @@ -92,6 +92,15 @@ def render_animation(args, anim_args, video_args, parseq_args, loop_args, contro os.makedirs(args.outdir, exist_ok=True) print(f"Saving animation frames to:\n{args.outdir}") + # ensure a model is loaded before proceeding - auto-load if not + import modules.shared as sh + if sh.sd_model is None: + print("[Deforum] No model loaded - triggering auto-load from config...") + from modules import sd_models + sd_models.reload_model_weights() + if sh.sd_model is None: + raise RuntimeError("No Stable Diffusion model is loaded. Please select a checkpoint in the A1111 UI before running Deforum.") + # save settings.txt file for the current run save_settings_from_animation_run(args, anim_args, parseq_args, loop_args, controlnet_args, video_args, root) @@ -221,6 +230,7 @@ def render_animation(args, anim_args, video_args, parseq_args, loop_args, contro state.job = f"frame {frame_idx + 1}/{anim_args.max_frames}" state.job_no = frame_idx + 1 + state.textinfo = f"Frame {frame_idx + 1} / {anim_args.max_frames}" if state.skipped: print("\n** PAUSED **") diff --git a/scripts/deforum_helpers/settings.py b/scripts/deforum_helpers/settings.py index 41b5678a..141e51d5 100644 --- a/scripts/deforum_helpers/settings.py +++ b/scripts/deforum_helpers/settings.py @@ -71,8 +71,8 @@ def save_settings_from_animation_run(args, anim_args, parseq_args, loop_args, co s = {} for d in (args.__dict__, anim_args.__dict__, parseq_args.__dict__, loop_args.__dict__, controlnet_args.__dict__, video_args.__dict__): s.update({k: v for k, v in d.items() if k not in exclude_keys}) - s["sd_model_name"] = sh.sd_model.sd_checkpoint_info.name - s["sd_model_hash"] = sh.sd_model.sd_checkpoint_info.hash + s["sd_model_name"] = sh.sd_model.sd_checkpoint_info.name if sh.sd_model else "unknown" + s["sd_model_hash"] = sh.sd_model.sd_checkpoint_info.hash if sh.sd_model else "unknown" s["deforum_git_commit_id"] = get_deforum_version() json.dump(s, f, ensure_ascii=False, indent=4) @@ -95,36 +95,46 @@ def save_settings(*args, **kwargs): combined = {**args_dict, **anim_args_dict, **parseq_dict, **loop_dict, **controlnet_dict, **video_args_dict} exclude_keys = get_keys_to_exclude() filtered_combined = {k: v for k, v in combined.items() if k not in exclude_keys} - filtered_combined["sd_model_name"] = sh.sd_model.sd_checkpoint_info.name - filtered_combined["sd_model_hash"] = sh.sd_model.sd_checkpoint_info.hash + filtered_combined["sd_model_name"] = sh.sd_model.sd_checkpoint_info.name if sh.sd_model else "unknown" + filtered_combined["sd_model_hash"] = sh.sd_model.sd_checkpoint_info.hash if sh.sd_model else "unknown" filtered_combined["deforum_git_commit_id"] = get_deforum_version() print(f"saving custom settings to {settings_path}") with open(settings_path, "w", encoding='utf-8') as f: f.write(json.dumps(filtered_combined, ensure_ascii=False, indent=4)) - - return [""] + status = f"Saved to: {settings_path}" + return [status] -def load_all_settings(*args, ui_launch=False, **kwargs): +def load_all_settings(*args, ui_launch=False, jdata=None, **kwargs): import gradio as gr - settings_path = args[0].strip() + settings_path = args[0].strip() if not jdata else "" settings_path = clean_gradio_path_strings(settings_path) settings_path = os.path.realpath(settings_path) settings_component_names = get_settings_component_names() data = {settings_component_names[i]: args[i+1] for i in range(len(settings_component_names))} - print(f"reading custom settings from {settings_path}") - - if not os.path.isfile(settings_path): - print('The custom settings file does not exist. The values will be unchanged.') - if ui_launch: - return ({key: gr.update(value=value) for key, value in data.items()},) - else: - return list(data.values()) + [""] + + if not jdata: + print(f"reading custom settings from {settings_path}") + if not os.path.isfile(settings_path): + print('The custom settings file does not exist. The values will be unchanged.') + if ui_launch: + return ({key: gr.update(value=value) for key, value in data.items()},) + else: + return list(data.values()) + [""] - with open(settings_path, "r", encoding='utf-8') as f: - jdata = json.load(f) - handle_deprecated_settings(jdata) - if 'animation_prompts' in jdata: - jdata['prompts'] = jdata['animation_prompts'] + with open(settings_path, "r", encoding='utf-8') as f: + try: + jdata = json.load(f) + except Exception as e: + print(f"Error loading settings file: {e}") + if ui_launch: return ({key: gr.update(value=value) for key, value in data.items()},) + else: return list(data.values()) + [""] + + handle_deprecated_settings(jdata) + if 'animation_prompts' in jdata: + jdata['prompts'] = jdata['animation_prompts'] + elif 'prompts' not in jdata and 'animation_prompts' not in jdata: + # if prompts are missing entirely, don't overwrite current ones + jdata['prompts'] = json.loads(data.get('animation_prompts', '{}')) result = {} for key, default_val in data.items(): @@ -159,19 +169,124 @@ def load_all_settings(*args, ui_launch=False, **kwargs): return list(result.values()) + [""] -def load_video_settings(*args, **kwargs): - video_settings_path = args[0].strip() +def stash_init_image(pil_image, current_init_path): + """When the user drops an image into init_image_box, save the PIL to disk + under outputs/deforum_init_images/.png and return the path so it + can be mirrored into the init_image URL textbox. That makes the path + serializable to settings .txt — the box widget itself can't be saved + because PIL objects don't survive JSON. + + Returns (new_init_image_path, status_text). On clear, returns ("", ""). + """ + if pil_image is None: + # User cleared the box. Leave the existing textbox path alone. + return current_init_path, "" + try: + import hashlib + from io import BytesIO + # Hash the PNG bytes so the same image always lands at the same path + # (no orphan duplicates if you drop the same file twice). + buf = BytesIO() + pil_image.save(buf, format="PNG") + png_bytes = buf.getvalue() + digest = hashlib.sha1(png_bytes).hexdigest()[:8] + outdir = os.path.join( + sh.opts.outdir_img2img_samples or "outputs/img2img-images", + "..", "deforum_init_images" + ) + outdir = os.path.realpath(outdir) + os.makedirs(outdir, exist_ok=True) + out_path = os.path.join(outdir, f"init_{digest}.png") + if not os.path.isfile(out_path): + with open(out_path, "wb") as f: + f.write(png_bytes) + return out_path, f"Init image saved -> {out_path}" + except Exception as e: + print(f"[stash_init_image] failed: {e}") + return current_init_path, f"Init image save failed: {e}" + + +def pick_save_path(current_path): + """Open a native Save As dialog (Windows Explorer style) on the server, + which is the same machine as the user since WebUI runs on localhost. + Returns the chosen absolute path, or the unchanged current path on cancel.""" + try: + import tkinter as tk + from tkinter import filedialog + # Default to the resolved current_path so the dialog opens in the right folder + default_dir = "" + default_name = "deforum_settings.txt" + if current_path and current_path.strip(): + cp = clean_gradio_path_strings(current_path.strip()) + cp = os.path.realpath(cp) + if os.path.isdir(os.path.dirname(cp)): + default_dir = os.path.dirname(cp) + default_name = os.path.basename(cp) or default_name + root = tk.Tk() + root.withdraw() + root.attributes("-topmost", True) + chosen = filedialog.asksaveasfilename( + parent=root, + title="Save Deforum settings as...", + initialdir=default_dir or None, + initialfile=default_name, + defaultextension=".txt", + filetypes=[("Settings file", "*.txt *.json"), ("All files", "*.*")], + ) + root.destroy() + if not chosen: + return current_path # user cancelled + return os.path.realpath(chosen) + except Exception as e: + print(f"[Save As] file dialog failed: {e}") + return current_path + + +def load_prompts_only(settings_path, current_prompts, current_pos, current_neg): + """Load only the animation_prompts (+ positive/negative) from a settings file, + leaving every other field untouched. Returns 3 values in order matching the + button's outputs: animation_prompts, animation_prompts_positive, animation_prompts_negative.""" + sp = clean_gradio_path_strings(settings_path.strip()) + sp = os.path.realpath(sp) + if not os.path.isfile(sp): + print(f"[Load only prompts] file not found: {sp}") + return [current_prompts, current_pos, current_neg, ""] + try: + with open(sp, "r", encoding="utf-8") as f: + jdata = json.load(f) + except Exception as e: + print(f"[Load only prompts] error reading {sp}: {e}") + return [current_prompts, current_pos, current_neg, ""] + handle_deprecated_settings(jdata) + prompts = jdata.get("prompts", jdata.get("animation_prompts", None)) + pos = jdata.get("animation_prompts_positive", current_pos) + neg = jdata.get("animation_prompts_negative", current_neg) + if prompts is None: + new_prompts = current_prompts + else: + new_prompts = json.dumps(prompts, ensure_ascii=False, indent=4) if not isinstance(prompts, str) else prompts + print(f"[Load only prompts] loaded prompts from {sp}") + return [new_prompts, pos, neg, ""] + + +def load_video_settings(*args, jdata=None, **kwargs): + video_settings_path = args[0].strip() if not jdata else "" vid_args_names = list(DeforumOutputArgs().keys()) data = {vid_args_names[i]: args[i+1] for i in range(0, len(vid_args_names))} - print(f"reading custom video settings from {video_settings_path}") - jdata = {} - if not os.path.isfile(video_settings_path): - print('The custom video settings file does not exist. The values will be unchanged.') - return [data[name] for name in vid_args_names] + [""] - else: - with open(video_settings_path, "r") as f: - jdata = json.loads(f.read()) - handle_deprecated_settings(jdata) + + if not jdata: + print(f"reading custom video settings from {video_settings_path}") + if not os.path.isfile(video_settings_path): + print('The custom video settings file does not exist. The values will be unchanged.') + return [data[name] for name in vid_args_names] + [""] + else: + with open(video_settings_path, "r") as f: + try: + jdata = json.loads(f.read()) + except Exception as e: + print(f"Error loading video settings: {e}") + return [data[name] for name in vid_args_names] + [""] + handle_deprecated_settings(jdata) ret = [] for key in data: diff --git a/scripts/deforum_helpers/ui_elements.py b/scripts/deforum_helpers/ui_elements.py index f9467e7c..877b357d 100644 --- a/scripts/deforum_helpers/ui_elements.py +++ b/scripts/deforum_helpers/ui_elements.py @@ -111,7 +111,7 @@ def get_tab_keyframes(d, da, dloopArgs): with FormRow(): color_correction_factor = create_gr_elem(dloopArgs.color_correction_factor) # EXTRA SCHEDULES TABS - with gr.Tabs(): + with gr.Tabs(elem_id='strength_schedule_tabs'): with gr.TabItem('Strength'): with FormRow(): strength_schedule = create_gr_elem(da.strength_schedule) diff --git a/scripts/deforum_helpers/ui_left.py b/scripts/deforum_helpers/ui_left.py index aa188637..d775ca91 100644 --- a/scripts/deforum_helpers/ui_left.py +++ b/scripts/deforum_helpers/ui_left.py @@ -50,6 +50,17 @@ def setup_deforum_left_side_ui(): controlnet_dict = setup_controlnet_ui() # ControlNet tab tab_hybrid_params = get_tab_hybrid(da) # Hybrid tab tab_output_params = get_tab_output(da, dv) # Output tab + + # Settings Editor Tab + with gr.TabItem('Settings Editor', elem_id='settings_editor_tab'): + with gr.Row(): + gr.HTML("Use this to directly edit the raw JSON settings. Be careful: invalid JSON or missing keys will cause errors!") + with gr.Row(): + settings_editor_code = gr.Code(language='json', interactive=True, label="Full Settings JSON", elem_id="deforum_settings_editor") + with gr.Row(): + load_ui_to_editor_btn = gr.Button("Load UI to Editor", variant='secondary') + apply_editor_to_ui_btn = gr.Button("Apply Editor to UI", variant='primary') + # add returned gradio elements from main tabs to locals() for key, value in {**tab_run_params, **tab_keyframes_params, **tab_prompts_params, **tab_init_params, **controlnet_dict, **tab_hybrid_params, **tab_output_params}.items(): locals()[key] = value diff --git a/scripts/deforum_helpers/ui_right.py b/scripts/deforum_helpers/ui_right.py index 515528a8..e7105ed8 100644 --- a/scripts/deforum_helpers/ui_right.py +++ b/scripts/deforum_helpers/ui_right.py @@ -19,11 +19,260 @@ from modules.ui import create_output_panel, wrap_gradio_call from modules.call_queue import wrap_gradio_gpu_call from .run_deforum import run_deforum -from .settings import save_settings, load_all_settings, load_video_settings +from .settings import save_settings, load_all_settings, load_video_settings, load_prompts_only, pick_save_path, stash_init_image from .general_utils import get_deforum_version from .ui_left import setup_deforum_left_side_ui from scripts.deforum_extend_paths import deforum_sys_extend import gradio as gr +import os as _os, glob as _glob + + +# --- Preset support (added) ------------------------------------------------------------------ +# A preset is just a complete Deforum settings .txt in the /presets folder at the WebUI root. +# Built-ins are written by _make_presets.py; the render viewer's "save as preset" drops files +# here too, so a good render becomes a reusable recipe. Nothing here parses settings itself - +# selecting a preset hands its path to Deforum's own load_all_settings. +DEFORUM_PRESETS_DIR = _os.path.join(_os.path.dirname(_os.path.abspath(__file__)), + "..", "..", "..", "..", "presets") +DEFORUM_PRESETS_DIR = _os.path.normpath(DEFORUM_PRESETS_DIR) + + +def deforum_preset_label(path): + """'03_Roller_Coaster_Camera_settings.txt' -> '03 - Roller Coaster Camera'""" + b = _os.path.basename(path) + for suf in ("_settings.txt", ".txt"): + if b.endswith(suf): + b = b[: -len(suf)] + break + b = b.replace("_", " ").strip() + if len(b) > 3 and b[:2].isdigit() and b[2:3] == " ": + b = b[:2] + " - " + b[3:] + return b + + +def deforum_list_presets(): + """Labels for the dropdown. Never raises: a bad presets dir just yields an empty list.""" + try: + if not _os.path.isdir(DEFORUM_PRESETS_DIR): + return [] + files = sorted(_glob.glob(_os.path.join(DEFORUM_PRESETS_DIR, "*.txt"))) + return [deforum_preset_label(f) for f in files] + except Exception as e: + print(f"[deforum-presets] could not list presets: {e}") + return [] + + +def deforum_preset_path(label): + """Map a dropdown label back to its file. Returns None if it no longer exists.""" + try: + for f in sorted(_glob.glob(_os.path.join(DEFORUM_PRESETS_DIR, "*.txt"))): + if deforum_preset_label(f) == label: + return f + except Exception as e: + print(f"[deforum-presets] could not resolve preset '{label}': {e}") + return None + + +def _deforum_fix_init_image(d): + """A settings file records init_image as an absolute path. If that file is gone, loading the + preset silently gives you use_init=True pointing at nothing - which is the 'images are missing' + bug. Repair on import: keep a real image, otherwise disable init rather than reference a ghost. + Returns (settings, note).""" + import json as _json + ii = str(d.get("init_image") or "").strip() + if not d.get("use_init"): + return d, None + if ii and _os.path.isfile(ii): + return d, None # image is real, nothing to do + if ii: + # try to recover it by filename from the usual homes before giving up + base = _os.path.basename(ii) + root = _os.path.normpath(_os.path.join(DEFORUM_PRESETS_DIR, "..")) + for cand in (_os.path.join(root, "outputs", "deforum_init_images", base), + _os.path.join(root, "outputs", "img2img-images", "INIT_IMAGES", base)): + if _os.path.isfile(cand): + d["init_image"] = cand + return d, f"init image relinked -> {base}" + d["use_init"] = False + d["init_image"] = "" + return d, f"init image missing ({_os.path.basename(ii) or 'unset'}) -> use_init turned OFF" + + +def deforum_import_presets(files): + """Drag-and-drop any number of Deforum settings files straight into the preset list. + + Each file is validated as JSON, has its init_image repaired (see above), and is copied into + /presets. Nothing is executed and nothing is overwritten silently - a name clash gets a suffix. + Returns (dropdown_update, status_text, settings_path_update). The path update points the + Settings File box at the last file imported, so the caller can immediately load it. + """ + import json as _json, shutil as _shutil + if not files: + return gr.update(), "Nothing dropped.", gr.update() + if not isinstance(files, (list, tuple)): + files = [files] + _os.makedirs(DEFORUM_PRESETS_DIR, exist_ok=True) + added, skipped, notes = [], [], [] + last_path = None + for f in files: + src = getattr(f, "name", None) or (f if isinstance(f, str) else None) + if not src or not _os.path.isfile(src): + skipped.append(f"{f}: not a readable file"); continue + base = _os.path.basename(src) + try: + with open(src, encoding="utf-8-sig") as fh: + d = _json.load(fh) + if not isinstance(d, dict) or "prompts" not in d: + skipped.append(f"{base}: not a Deforum settings file"); continue + except Exception as e: + skipped.append(f"{base}: unreadable JSON ({e})"); continue + + d, note = _deforum_fix_init_image(d) + if note: notes.append(f"{base}: {note}") + # never resume a stale render off an imported preset + d["resume_from_timestring"] = False + d["resume_timestring"] = "" + + stem = base[:-4] if base.lower().endswith(".txt") else base + if not stem.endswith("_settings"): stem += "_settings" + dst = _os.path.join(DEFORUM_PRESETS_DIR, stem + ".txt") + n = 2 + while _os.path.exists(dst): + dst = _os.path.join(DEFORUM_PRESETS_DIR, f"{stem}_{n}.txt"); n += 1 + try: + with open(dst, "w", encoding="utf-8") as fh: + _json.dump(d, fh, indent=4) + added.append(deforum_preset_label(dst)) + last_path = dst + except Exception as e: + skipped.append(f"{base}: could not write ({e})") + + msg = [] + if added: msg.append("Added " + str(len(added)) + ": " + ", ".join(added)) + if notes: msg.append("Fixed: " + " | ".join(notes)) + if skipped: msg.append("Skipped: " + " | ".join(skipped)) + path_update = gr.update(value=last_path) if last_path else gr.update() + return gr.update(choices=deforum_list_presets()), (" ".join(msg) or "Nothing imported."), path_update + + +def _deforum_seed_default_preset(): + """Put the shipped Microcosm recipe into /presets so it shows up in the Preset dropdown out of + the box - both on Brian's machine and on a fresh install. Copies once; never overwrites. Points + init_image at the init that ships beside the recipe so 'use init' isn't left dangling.""" + try: + base = _os.path.normpath(_os.path.join(_os.path.dirname(_os.path.abspath(__file__)), + "..", "..", "microcosm")) + src = _os.path.join(base, "BEST_DEFAULT_settings.txt") + if not _os.path.isfile(src): + return + _os.makedirs(DEFORUM_PRESETS_DIR, exist_ok=True) + dst = _os.path.join(DEFORUM_PRESETS_DIR, "00_Microcosm_BEST_settings.txt") + if _os.path.exists(dst): + return + import json as _json + with open(src, encoding="utf-8-sig") as fh: + d = _json.load(fh) + init = _os.path.join(base, "microcosm-init.png") + if _os.path.isfile(init): + d["init_image"] = init + d["resume_from_timestring"] = False + d["resume_timestring"] = "" + with open(dst, "w", encoding="utf-8") as fh: + _json.dump(d, fh, indent=4) + print("[deforum-presets] seeded default preset: 00 - Microcosm BEST") + except Exception as e: + print(f"[deforum-presets] could not seed default preset: {e}") + + +_deforum_seed_default_preset() + + +def deforum_viewer_url(): + """URL that opens the standalone render viewer (microcosm/Microcosm.html) in a browser tab, + served by A1111's own /file= endpoint. Same single file you can also double-click on disk - + no separate gallery extension, no iframe. Returns '' if the file isn't found.""" + try: + import urllib.parse as _up + p = _os.path.normpath(_os.path.join(_os.path.dirname(_os.path.abspath(__file__)), + "..", "..", "microcosm", "Microcosm.html")) + if not _os.path.isfile(p): + return "" + return "/file=" + _up.quote(p.replace("\\", "/")) + except Exception: + return "" + + +# --- Folder settings (added): init images / video+ControlNet inputs / models ----------------- +# These belong HERE in the Deforum panel (they are Deforum's inputs), not in the render gallery. +# Stored in the same shared config the gallery extension uses, so both stay in agreement. +_DEFORUM_WEBUI_ROOT = _os.path.dirname(DEFORUM_PRESETS_DIR) +_DEFORUM_SHARED_CONFIG = _os.path.join(_DEFORUM_WEBUI_ROOT, "outputs", "img2img-images", + "_gallery_data", "config.json") +_DEFORUM_FOLDER_DEFAULTS = { + "init": _os.path.join(_DEFORUM_WEBUI_ROOT, "outputs", "img2img-images", "INIT_IMAGES"), + "video": _os.path.join(_DEFORUM_WEBUI_ROOT, "outputs", "deforum_video_inputs"), +} + + +def _deforum_shared_cfg_load(): + import json + try: + with open(_DEFORUM_SHARED_CONFIG, encoding="utf-8") as fh: + return json.load(fh) + except Exception: + return {} + + +def deforum_folder_get(key): + c = _deforum_shared_cfg_load() + return (c.get("dirs") or {}).get(key) or _DEFORUM_FOLDER_DEFAULTS.get(key, "") + + +def deforum_folder_set(key, value): + import json + value = str(value or "").strip() + if not value: + return + c = _deforum_shared_cfg_load() + c.setdefault("dirs", {})[key] = value + try: + _os.makedirs(_os.path.dirname(_DEFORUM_SHARED_CONFIG), exist_ok=True) + tmp = _DEFORUM_SHARED_CONFIG + ".tmp" + with open(tmp, "w", encoding="utf-8") as fh: + json.dump(c, fh, indent=4) + _os.replace(tmp, _DEFORUM_SHARED_CONFIG) + except Exception as e: + print(f"[deforum-folders] could not save config: {e}") + + +def deforum_models_dir(): + """The folder the CURRENT session actually loads checkpoints from (read-only here: + it is fixed at launch by --ckpt-dir, or defaults to models/Stable-diffusion).""" + try: + from modules import shared, paths + d = getattr(shared.cmd_opts, "ckpt_dir", None) + return d or _os.path.join(paths.models_path, "Stable-diffusion") + except Exception: + return _os.path.join(_DEFORUM_WEBUI_ROOT, "models", "Stable-diffusion") + + +def deforum_pick_folder(current): + """Native Windows folder dialog (this WebUI runs on the same machine as the browser).""" + try: + import tkinter as tk + from tkinter import filedialog + root = tk.Tk() + root.withdraw() + root.attributes("-topmost", True) + picked = filedialog.askdirectory( + initialdir=current if current and _os.path.isdir(current) else None, + title="Select folder") + root.destroy() + return picked.replace("/", "\\") if picked else (current or "") + except Exception as e: + print(f"[deforum-folders] folder picker failed: {e}") + return current or "" +# --------------------------------------------------------------------------------------------- def on_ui_tabs(): # extend paths using sys.path.extend so we can access all of our files and folders @@ -32,7 +281,18 @@ def on_ui_tabs(): i1_store_backup = f"

Deforum extension version 3.1, for auto1111 v1.9 | Git commit: {get_deforum_version()}

" i1_store = i1_store_backup - with gr.Blocks(analytics_enabled=False) as deforum_interface: + deforum_css = """ + /* Gallery starts compact, zoom control scales it */ + #deforum_gallery_container { min-height: unset !important; } + #deforum_gallery { min-height: unset !important; height: 280px !important; transition: height 0.2s; } + #deforum_gallery > div { height: 100% !important; } + #deforum_gallery button.thumbnail-item { height: 100% !important; } + #deforum_gallery button.thumbnail-item img { object-fit: contain !important; height: 100% !important; width: auto !important; } + #deforum_zoom_row { position: relative; z-index: 500; } + #deforum_preview_zoom { display: flex; align-items: center; gap: 4px; padding: 2px 0; } + #deforum_preview_zoom button:hover { background: #3a3d56 !important; } + """ + with gr.Blocks(analytics_enabled=False, css=deforum_css) as deforum_interface: components = {} dummy_component = gr.Label(visible=False) with gr.Row(elem_id='deforum_progress_row').style(equal_height=False, variant='compact'): @@ -73,7 +333,7 @@ def close_vid(): # Close video button related func ) id_part = 'deforum' with gr.Row(elem_id=f"{id_part}_generate_box", variant='compact'): - skip = gr.Button('Pause/Resume', elem_id=f"{id_part}_skip", visible=False) + skip = gr.Button('Pause/Resume', elem_id=f"{id_part}_skip", visible=True) interrupt = gr.Button('Interrupt', elem_id=f"{id_part}_interrupt", visible=True) interrupting = gr.Button('Interrupting...', elem_id=f"{id_part}_interrupting", elem_classes="generate-box-interrupting", tooltip="Interrupting generation...") submit = gr.Button('Generate', elem_id=f"{id_part}_generate", variant='primary') @@ -96,6 +356,15 @@ def close_vid(): # Close video button related func outputs=[], ) + # Force live preview in modal lightbox so fullscreen view updates during render + gr.HTML("""""", visible=False) + gr.HTML("""
+ Preview: + + + + +
""", elem_id="deforum_zoom_row") output_panel = create_output_panel("deforum", opts.outdir_img2img_samples) if isinstance(output_panel, tuple): deforum_gallery = output_panel[0] @@ -106,12 +375,59 @@ def close_vid(): # Close video button related func generation_info = output_panel.generation_info html_info = output_panel.infotext + # --- Preset dropdown (added): pick a proven recipe, it loads into every field below. + # Presets are ordinary complete settings files in F:\stable-diffusion-webui\presets\, + # so this reuses Deforum's own load_all_settings - no parallel loader to drift. + with gr.Row(variant='compact'): + preset_dropdown = gr.Dropdown( + label="Preset", choices=deforum_list_presets(), value=None, + elem_id='deforum_preset_dropdown', scale=5, + info="Loads a saved recipe into all settings below. Files live in /presets. Swap prompts after loading.") + refresh_presets_btn = gr.Button('Refresh', elem_id='deforum_refresh_presets_btn', scale=1) + with gr.Row(variant='compact'): + preset_drop = gr.File( + label="Drop a settings file here, it's added to the Preset list above and loaded straight in (drop several to add them all)", + file_count="multiple", file_types=[".txt", ".json"], + elem_id='deforum_preset_drop') with gr.Row(variant='compact'): - settings_path = gr.Textbox("deforum_settings.txt", elem_id='deforum_settings_path', label="Settings File", info="settings file path can be relative to webui folder OR full - absolute") + preset_status = gr.Textbox(value="", label="Last preset action", interactive=False, lines=1, + elem_id='deforum_preset_status') + _viewer_url = deforum_viewer_url() + if _viewer_url: + with gr.Row(variant='compact'): + gr.HTML( + f'Open the render viewer' + ' opens the same ' + 'Microcosm.html you can double-click with Stable Diffusion closed') + with gr.Accordion("Folders, init images, video/ControlNet inputs, models", open=False): + with gr.Row(variant='compact'): + init_folder_tb = gr.Textbox(value=deforum_folder_get('init'), scale=5, + label="Init images folder", elem_id='deforum_init_folder', + info="Where your init images live.") + init_browse_btn = gr.Button('Browse…', scale=1, elem_id='deforum_init_browse') + with gr.Row(variant='compact'): + video_folder_tb = gr.Textbox(value=deforum_folder_get('video'), scale=5, + label="Video / ControlNet inputs folder", elem_id='deforum_video_folder', + info="Source videos for video-to-video and ControlNet.") + video_browse_btn = gr.Button('Browse…', scale=1, elem_id='deforum_video_browse') + with gr.Row(variant='compact'): + gr.Textbox(value=deforum_models_dir(), interactive=False, scale=6, + label="Models (checkpoints) folder, read-only", + elem_id='deforum_models_folder', + info="Fixed at launch. To change it, add --ckpt-dir \"D:\\path\" (and --lora-dir for LoRAs) to COMMANDLINE_ARGS in Start Deforum.bat, then restart.") + with gr.Row(variant='compact'): + settings_path = gr.Textbox("deforum_settings.txt", elem_id='deforum_settings_path', label="Settings File", info="Path of the loaded settings. Set automatically when you pick a preset or drop a file above; type a path here to load one from elsewhere.") with gr.Row(variant='compact'): save_settings_btn = gr.Button('Save Settings', elem_id='deforum_save_settings_btn') - load_settings_btn = gr.Button('Load All Settings', elem_id='deforum_load_settings_btn') - load_video_settings_btn = gr.Button('Load Video Settings', elem_id='deforum_load_video_settings_btn') + save_as_settings_btn = gr.Button('Save As...', elem_id='deforum_save_as_settings_btn') + load_settings_btn = gr.Button('Load all settings', elem_id='deforum_load_settings_btn') + load_video_settings_btn = gr.Button('Load only video settings', elem_id='deforum_load_video_settings_btn') + load_prompts_only_btn = gr.Button('Load only prompts', elem_id='deforum_load_prompts_only_btn') + with gr.Row(variant='compact'): + save_status = gr.Textbox(value="", elem_id='deforum_save_status', label="Last save / load", interactive=False, lines=1) component_list = [components[name] for name in get_component_names()] @@ -133,21 +449,123 @@ def close_vid(): # Close video button related func save_settings_btn.click( fn=wrap_gradio_call(save_settings), inputs=[settings_path] + settings_component_list + video_settings_component_list, - outputs=[], + outputs=[save_status], ) - + + # Save As: opens a real native Windows file picker via tkinter (server-side, + # but server = your machine since WebUI is on localhost). Then saves to the chosen path. + save_as_settings_btn.click( + fn=pick_save_path, + inputs=[settings_path], + outputs=[settings_path], + ).then( + fn=wrap_gradio_call(save_settings), + inputs=[settings_path] + settings_component_list + video_settings_component_list, + outputs=[save_status], + ) + + # Load only prompts: read animation_prompts + positive/negative from a file, + # leave every other setting alone. + prompts_comp = components["animation_prompts"] + prompts_pos_comp = components["animation_prompts_positive"] + prompts_neg_comp = components["animation_prompts_negative"] + load_prompts_only_btn.click( + fn=wrap_gradio_call(load_prompts_only), + inputs=[settings_path, prompts_comp, prompts_pos_comp, prompts_neg_comp], + outputs=[prompts_comp, prompts_pos_comp, prompts_neg_comp, save_status], + ) + + # When the user drops an image into the init_image_box, save it under + # outputs/deforum_init_images/.png and mirror that path into the + # init_image URL textbox. The textbox IS persisted by save_settings, so + # the next time the settings file is loaded, init_image points at the + # same PNG on disk and the image effectively "comes back", even though + # the PIL box widget itself can't be serialized. + init_image_box_comp = components["init_image_box"] + init_image_comp = components["init_image"] + init_image_box_comp.change( + fn=stash_init_image, + inputs=[init_image_box_comp, init_image_comp], + outputs=[init_image_comp, save_status], + ) + load_settings_btn.click( fn=wrap_gradio_call(lambda *args, **kwargs: load_all_settings(*args, ui_launch=False, **kwargs)), inputs=[settings_path] + settings_component_list, outputs=settings_component_list, ) + # --- Preset dropdown wiring (added) --- + # Selecting a preset resolves its label to a file path and hands it to the SAME + # load_all_settings the button uses, so there is no second code path to drift. + # Also mirrors the path into settings_path so it's obvious what got loaded (and so + # "Save Settings" doesn't silently overwrite the preset unless that's intended). + def _load_preset(preset_label, *args): + path = deforum_preset_path(preset_label) if preset_label else None + if not path: + # unknown/removed preset: change nothing rather than wiping the user's settings + return [gr.update() for _ in settings_component_list] + return load_all_settings(path, *args, ui_launch=False) + + preset_dropdown.change( + fn=wrap_gradio_call(_load_preset), + inputs=[preset_dropdown] + settings_component_list, + outputs=settings_component_list, + ) + preset_dropdown.change( + fn=lambda label: (deforum_preset_path(label) or "") if label else gr.update(), + inputs=[preset_dropdown], + outputs=[settings_path], + ) + refresh_presets_btn.click( + fn=lambda: gr.update(choices=deforum_list_presets()), + inputs=[], + outputs=[preset_dropdown], + ) + # drag-and-drop any number of settings files: they become presets AND the last one loads + # straight into the UI. One drop box, one behaviour - no separate "upload settings" box. + preset_drop.upload( + fn=deforum_import_presets, + inputs=[preset_drop], + outputs=[preset_dropdown, preset_status, settings_path], + ).then( + fn=wrap_gradio_call(lambda *args, **kwargs: load_all_settings(*args, ui_launch=False, **kwargs)), + inputs=[settings_path] + settings_component_list, + outputs=settings_component_list, + ) + + # folder settings: Browse opens a native folder dialog; any change persists to the + # shared config (the same file the render gallery reads its folder settings from) + init_browse_btn.click(fn=deforum_pick_folder, inputs=[init_folder_tb], outputs=[init_folder_tb]) + video_browse_btn.click(fn=deforum_pick_folder, inputs=[video_folder_tb], outputs=[video_folder_tb]) + init_folder_tb.change(fn=lambda v: deforum_folder_set('init', v), inputs=[init_folder_tb], outputs=[]) + video_folder_tb.change(fn=lambda v: deforum_folder_set('video', v), inputs=[video_folder_tb], outputs=[]) + load_video_settings_btn.click( fn=wrap_gradio_call(load_video_settings), inputs=[settings_path] + video_settings_component_list, outputs=video_settings_component_list, ) + # New Settings Editor logic + from .gradio_funcs import sync_ui_to_editor, sync_editor_to_ui + + settings_editor_code = components['settings_editor_code'] + load_ui_to_editor_btn = components['load_ui_to_editor_btn'] + apply_editor_to_ui_btn = components['apply_editor_to_ui_btn'] + + load_ui_to_editor_btn.click( + fn=sync_ui_to_editor, + inputs=settings_component_list, + outputs=[settings_editor_code], + ) + + apply_editor_to_ui_btn.click( + fn=sync_editor_to_ui, + inputs=[settings_editor_code] + settings_component_list, + outputs=settings_component_list, + ) + # handle persistent settings - load the persistent file upon UI launch def trigger_load_general_settings(): print("Loading general settings...") diff --git a/style.css b/style.css index 7d6467f6..a86edeff 100644 --- a/style.css +++ b/style.css @@ -41,6 +41,25 @@ Contact the authors: https://deforum.github.io/ display: none !important; } +/* Hide the send-to buttons row under the Deforum gallery (img2img, inpaint, extras icons) */ +#image_buttons_deforum { + display: none !important; +} + +/* Live preview: container fills gallery, image maintains aspect ratio */ +#tab_deforum_interface .livePreview { + position: absolute !important; + top: 0 !important; + left: 0 !important; + width: 100% !important; + height: 100% !important; +} +#tab_deforum_interface .livePreview img { + width: 100% !important; + height: calc(100% - 30px) !important; + object-fit: contain !important; +} + #main_top_info_accord .label-wrap { gap:2px; padding: 0.5rem; @@ -80,4 +99,5 @@ Contact the authors: https://deforum.github.io/ #tab_deforum_interface .file-preview-holder { overflow-y: auto; max-height: 60px; -} \ No newline at end of file +} + diff --git a/tools/Deforum_Compare_Portable/Deforum_Compare_Portable.html b/tools/Deforum_Compare_Portable/Deforum_Compare_Portable.html new file mode 100644 index 00000000..6bbc34a6 --- /dev/null +++ b/tools/Deforum_Compare_Portable/Deforum_Compare_Portable.html @@ -0,0 +1,1505 @@ + + + + + +Deforum Compare (Portable) + + + + + + +
+

Deforum Compare — Portable

+

Compare your Deforum renders side by side: every video plays inline, you rate them + with stars, jot notes, and zoom into any one at full size. Notes and ratings are saved + automatically in this browser.

+

Click below and pick any Deforum output folder. It scans that folder + and all subfolders, matches each settings file to its rendered video, + and shows everything in one table.

+ +
+ Drop settings files or whole folders here to quick-compare +
Drop a folder (imports its settings + movie, ignores stills), or drop a settings .txt + its .mp4 together to pair them. A lone .txt loads settings only. Then click Compare.
+ +
+ +
+ Your notes are private & local. Ratings and notes live in this + browser only (nothing is uploaded). Use Export notes any time to save a CSV backup. + To share your notes with someone else, send them the exported CSV. +
+
+ + + +
+ + +
+
+
+ + + + + + diff --git a/tools/Deforum_Compare_Portable/Launch Deforum Compare.bat b/tools/Deforum_Compare_Portable/Launch Deforum Compare.bat new file mode 100644 index 00000000..a34135d4 --- /dev/null +++ b/tools/Deforum_Compare_Portable/Launch Deforum Compare.bat @@ -0,0 +1,35 @@ +@echo off +title Deforum Compare (Portable) - KEEP THIS WINDOW OPEN +echo ============================================================ +echo Deforum Compare (Portable) +echo. +echo A small local server is starting so the folder picker works. +echo KEEP THIS WINDOW OPEN while you use the tool. +echo Close it when you are finished. +echo ============================================================ +echo. + +REM Serve from THIS folder, wherever it happens to live +cd /d "%~dp0" + +REM Pick the port +set PORT=48217 + +REM Start a tiny static web server in the background (needs Python) +start "DeforumCompareServer" /min python -m http.server %PORT% +if errorlevel 1 ( + echo. + echo Python was not found. Trying py launcher... + start "DeforumCompareServer" /min py -m http.server %PORT% +) + +REM Give the server a second to come up, then open the browser +timeout /t 2 >nul +start "" chrome "http://localhost:%PORT%/Deforum_Compare_Portable.html" +if errorlevel 1 start "" "http://localhost:%PORT%/Deforum_Compare_Portable.html" + +echo. +echo Opened in your browser: http://localhost:%PORT%/Deforum_Compare_Portable.html +echo If nothing opened, paste that address into Chrome or Edge. +echo. +pause diff --git a/tools/Deforum_Compare_Portable/READ ME FIRST.txt b/tools/Deforum_Compare_Portable/READ ME FIRST.txt new file mode 100644 index 00000000..6ed97cc7 --- /dev/null +++ b/tools/Deforum_Compare_Portable/READ ME FIRST.txt @@ -0,0 +1,49 @@ +DEFORUM COMPARE (PORTABLE) +========================== + +What it does +------------ +Opens any Deforum output folder (and all its subfolders), finds every render +video, matches it to its settings file, and shows them all in one table you can +scroll through. Play videos inline, rate them with stars, write notes, and +zoom into any one at full size. Notes and ratings save automatically. + + +How to run it +------------- +1. Double-click "Launch Deforum Compare.bat" +2. A small black window opens and your browser opens the tool. + KEEP THE BLACK WINDOW OPEN while you use it. Close it when you're done. +3. In the browser, click "Open Folder" and pick your Deforum outputs folder. +4. Click any video (or its blue "Zoom" button) to see it full size. + Use the LEFT / RIGHT arrow keys to step through them one by one. + + +Requirements +------------ +- Windows +- Google Chrome or Microsoft Edge (NOT Firefox or Safari) +- Python installed (the same Python the Deforum / Stable Diffusion setup uses). + If double-clicking the .bat says "python not found", install Python from + python.org and check "Add Python to PATH" during install. + + +Why the black window / local server? +------------------------------------- +Browsers only allow the "pick a folder" feature on a real web address +(http://localhost), not on a file opened directly from disk. The .bat starts a +tiny local server on your own machine so the folder picker works. Nothing is +uploaded anywhere — it's 100% local and private. + + +Your notes are private +---------------------- +Ratings and notes are stored in your own browser only. Nothing leaves your +computer. To share your notes with someone, use the "Export notes" button to +save a CSV file and send them that. + + +Sharing this tool +----------------- +Send the WHOLE folder (both files). It works from anywhere — Desktop, a USB +stick, wherever you put it.