Skip to content
Open
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
5725f7a
feat(model): add Wan 2.2 image generation support (Phases 0-2)
lstein May 9, 2026
ad4a31e
feat(model): Wan 2.2 Phase 3 + tokenizer-load fix
lstein May 9, 2026
f9a22c1
feat(model): Wan 2.2 Phase 4 - GGUF transformer support
lstein May 9, 2026
11b7eb3
feat(model): Wan 2.2 Phase 5 - LoRA support
lstein May 10, 2026
22799af
feat(model): Wan 2.2 Phase 7 - reference-image (I2V) conditioning
lstein May 11, 2026
5d5f8cb
test(wan): add Phase 8 inpaint regression tests
lstein May 11, 2026
c595452
feat(wan): Phase 9 piece #1 - linear-view T2V txt2img graph builder
lstein May 11, 2026
727eff9
feat(wan): add Wan 2.2 starter models and bundle
lstein May 12, 2026
6c076c5
fix(wan): recall low-noise transformer, component source, and standal…
lstein May 12, 2026
b9b0665
chore(frontend): typegen
lstein May 12, 2026
2d1add8
feat(wan): add default Wan 2.2 T2V and I2V workflows
lstein May 12, 2026
19d5c53
feat(videos): Phase 1 - backend video storage, records, REST API
lstein May 12, 2026
a0913ea
feat(videos): Phase 2 - polymorphic gallery list endpoint
lstein May 12, 2026
c9aff11
feat(videos): Phase 3 - frontend RTK endpoints + MP4 upload routing
lstein May 12, 2026
7cf98cb
feat(videos): Phase 4 - mixed gallery grid with video play badge
lstein May 12, 2026
50d9588
feat(videos): Phase 5 - inline video player in the image viewer
lstein May 12, 2026
1f62b44
fix(videos): accept MP4 (and other video) drops on the fullscreen dro…
lstein May 12, 2026
c9ce8d6
feat(videos): right-click context menu on video items
lstein May 12, 2026
216322f
feat(wan): Phase 6 - Wan 2.2 T2V/I2V workflow nodes
lstein May 12, 2026
87982e9
feat(wan): add Wan 2.2 T2V and I2V starter video workflows
lstein May 12, 2026
cac3662
fix(wan): startup crash from stringified VideoOutput annotation
lstein May 12, 2026
7f89d69
feat(wan): add Wan 2.2 Lightning T2V starter workflow
lstein May 12, 2026
325fbbd
feat(wan): add Wan 2.2 Lightning T2V and I2V starter workflows
lstein May 12, 2026
715df66
fix(wan): use FFMPEG plugin (not pyav) for MP4 encode
lstein May 12, 2026
9117315
feat(wan): log VAE decode and MP4 encode milestones in wan_l2v
lstein May 12, 2026
7b4eee1
fix(wan): switch video thumbnail/probe to imageio[ffmpeg] backend
lstein May 12, 2026
a7dfb3e
fix(videos): handle VideoField outputs in invocation_complete
lstein May 12, 2026
9f212d7
feat(video): add 'Frame from Video' invocation
lstein May 12, 2026
e29e738
feat(video): add 'Concatenate Videos' invocation
lstein May 12, 2026
e5d1fd8
fix(videos): show full-resolution first frame in viewer
lstein May 12, 2026
d477fea
fix(nodes): show 'Save in gallery' on video-output nodes
lstein May 12, 2026
321bdd8
chore: remove unwanted planning documents
lstein May 12, 2026
ce8859b
chore: fix ruff I001 import-order violations
lstein May 13, 2026
405d263
fix(videos): restrict uploads to MP4 only
lstein May 13, 2026
2e8f7c4
chore(videos): clean up stale @knipignore on consumed hooks
lstein May 13, 2026
577ea88
docs(videos): document invalidate/select race in addVideosToGallery
lstein May 13, 2026
537ef6c
feat(video): add Video Primitive invocation and VideoField input UI
lstein May 13, 2026
b077727
chore(backend): ruff
lstein May 13, 2026
bfbe641
chore(frontend): typegen
lstein May 13, 2026
0e6a0cf
Merge branch 'main' into lstein/feature/wan-video-support
JPPhoto May 13, 2026
73d7450
feat(wan): split Wan 2.2 starter bundle into T2V and I2V
lstein May 13, 2026
0361dd0
fix(videos): tighten multiuser isolation in list and board-move endpo…
lstein May 13, 2026
f6408e7
fix(boards): cascade video deletion when deleting a board with media
lstein May 13, 2026
94f5c0c
fix(videos): return affected_boards from board move/remove endpoints
lstein May 13, 2026
6d514ef
fix(videos): stream uploads, FileResponse for full video + thumbnail
lstein May 13, 2026
e529719
fix(videos): localize video UI strings
lstein May 13, 2026
1ab9627
fix(video-invocations): exact frame counts and odd-tf transitions
lstein May 13, 2026
a764380
docs(gallery): describe video gallery items, upload, and deletion
lstein May 13, 2026
2208ff5
test(videos): regression coverage for PR #9163 review fixes
lstein May 13, 2026
fa0de57
feat(wan): add 'Wan 2.2 I2V Ideal Dimensions' invocation
lstein May 13, 2026
c68def2
feat(wan): swap target_short_side int for 480p/720p/1080p preset drop…
lstein May 13, 2026
3ae6b9b
fix(wan): empty_cache around the I2V reference-image VAE encode
lstein May 13, 2026
e7699b6
feat(wan): support TI2V-5B in the video denoise node (T2V mode)
lstein May 13, 2026
07a366f
fix(wan): instantiate TI2V-5B VAE with the right architectural config
lstein May 13, 2026
1596c9b
fix(wan): variant-aware default scheduler for standalone installs
lstein May 13, 2026
5a2ca3b
feat(wan): TI2V-5B image-to-video support
lstein May 13, 2026
9449a33
fix(videos): show denoise progress overlay over the video viewer
lstein May 13, 2026
d870233
chore(lint): apply ruff format + isort across recent Wan video work
lstein May 13, 2026
ef283bc
docs(features): add user guide for Wan 2.2 video generation
lstein May 13, 2026
a3bdc33
fix(nodes): skip image-DTO fetch for videos in Current Image node
lstein May 13, 2026
e01c991
fix(videos): clear stale progress overlay + force first-frame paint
lstein May 14, 2026
5ec7e33
fix(hotkeys): skip image-DTO fetch for videos in GlobalImageHotkeys
lstein May 14, 2026
53b2f4d
fix(wan): empty CUDA cache between A14B expert swaps
lstein May 14, 2026
add40b0
feat(videos): allow drag-and-drop to change a video's board
lstein May 14, 2026
f0e2aa4
fix(wan): force outgoing A14B expert off GPU on swap
lstein May 14, 2026
fd4fdfe
fix(gallery): restore shift/ctrl-click range selection in image grid
lstein May 14, 2026
a421f9c
chore(typegen): regenerate schema.ts
lstein May 14, 2026
2106f10
chore(startup): silence HF tokenizers fork-after-parallelism warning
lstein May 14, 2026
672df1a
chore(startup): hoist TOKENIZERS_PARALLELISM=false to module level
lstein May 14, 2026
ea5ab1b
feat(videos): replace window.confirm with ConfirmationAlertDialog
lstein May 14, 2026
7c04b48
fix(gallery): refetch polymorphic gallery cache on image completion
lstein May 14, 2026
e980c54
review: address 2nd-pass code review findings
lstein May 14, 2026
5d82828
Merge branch 'main' into lstein/feature/wan-video-support
lstein May 14, 2026
ca2a2cd
chore(frontend): typegen
lstein May 14, 2026
aafc871
Merge remote-tracking branch 'refs/remotes/origin/lstein/feature/wan-…
lstein May 14, 2026
4cd9d70
fix(gallery): multi-select context menu actions for videos
lstein May 14, 2026
48e9ec0
Merge branch 'main' into lstein/feature/wan-video-support
JPPhoto May 15, 2026
b09e65c
fix(multiuser): address Pfannkuchensack PR #9163 review findings
lstein May 15, 2026
4883850
Merge branch 'main' into lstein/feature/wan-video-support
lstein May 15, 2026
7ea0fab
chore(openapi): regenerate openapi.json
lstein May 15, 2026
0fafffc
feat(workflows): add "Image to Video - Add Frames" starter workflow
lstein May 15, 2026
15a7657
Merge remote-tracking branch 'upstream/main' into lstein/feature/wan-…
lstein May 15, 2026
e1070c9
fix(gallery): video viewer polish and selection regressions
lstein May 15, 2026
a2b2409
fix(gallery): bulk video drag-to-board and shift-click range selection
lstein May 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 0 additions & 169 deletions USER_ISOLATION_IMPLEMENTATION.md

This file was deleted.

4 changes: 3 additions & 1 deletion docs/src/content/docs/start-here/system-requirements.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Hardware Requirements
sidebar:
order: 1
lastUpdated: 2026-02-18
lastUpdated: 2026-05-11
---

import { Tabs, TabItem, Steps } from '@astrojs/starlight/components'
Expand All @@ -28,6 +28,8 @@ The requirements below are rough guidelines for best performance. GPUs with less
| FLUX.2 Klein 4B | 1024x1024 | Nvidia 30xx+ | 12GB | 16GB | FP8 works with 8GB+; Diffusers + encoder |
| FLUX.2 Klein 9B | 1024x1024 | Nvidia 40xx | 24GB | 32GB | FP8 works with 12GB+; Diffusers + encoder |
| Z-Image Turbo | 1024x1024 | Nvidia 20xx+ | 8GB | 16GB | Q4_K 8GB; Q8/BF16 16GB+ |
| Wan 2.2 A14B (T2V/I2V) | 1280x720 | Nvidia 30xx+ | 12GB | 32GB | Dual-expert MoE; Q4_K_M 12GB; Q8 18GB+; Diffusers requires 32GB+ |
| Wan 2.2 TI2V-5B | 1280x720 | Nvidia 20xx+ | 8GB | 16GB | Single transformer; Q4_K_M 6GB+; Q8 8GB+; Diffusers 12GB+ |

:::tip[`tmpfs` on Linux]
If your temporary directory is mounted as a `tmpfs`, ensure it has sufficient space.
Expand Down
17 changes: 17 additions & 0 deletions invokeai/app/api/dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from invokeai.app.services.board_image_records.board_image_records_sqlite import SqliteBoardImageRecordStorage
from invokeai.app.services.board_images.board_images_default import BoardImagesService
from invokeai.app.services.board_records.board_records_sqlite import SqliteBoardRecordStorage
from invokeai.app.services.board_video_records.board_video_records_sqlite import SqliteBoardVideoRecordStorage
from invokeai.app.services.boards.boards_default import BoardService
from invokeai.app.services.bulk_download.bulk_download_default import BulkDownloadService
from invokeai.app.services.client_state_persistence.client_state_persistence_sqlite import ClientStatePersistenceSqlite
Expand All @@ -24,6 +25,7 @@
SeedreamProvider,
)
from invokeai.app.services.external_generation.startup import sync_configured_external_starter_models
from invokeai.app.services.gallery.gallery_default import SqliteGalleryService
from invokeai.app.services.image_files.image_files_disk import DiskImageFileStorage
from invokeai.app.services.image_records.image_records_sqlite import SqliteImageRecordStorage
from invokeai.app.services.images.images_default import ImageService
Expand Down Expand Up @@ -51,6 +53,9 @@
from invokeai.app.services.style_preset_records.style_preset_records_sqlite import SqliteStylePresetRecordsStorage
from invokeai.app.services.urls.urls_default import LocalUrlService
from invokeai.app.services.users.users_default import UserService
from invokeai.app.services.video_files.video_files_disk import DiskVideoFileStorage
from invokeai.app.services.video_records.video_records_sqlite import SqliteVideoRecordStorage
from invokeai.app.services.videos.videos_default import VideoService
from invokeai.app.services.workflow_records.workflow_records_sqlite import SqliteWorkflowRecordsStorage
from invokeai.app.services.workflow_thumbnails.workflow_thumbnails_disk import WorkflowThumbnailFileStorageDisk
from invokeai.backend.stable_diffusion.diffusion.conditioning_data import (
Expand All @@ -62,6 +67,7 @@
QwenImageConditioningInfo,
SD3ConditioningInfo,
SDXLConditioningInfo,
WanConditioningInfo,
ZImageConditioningInfo,
)
from invokeai.backend.util.logging import InvokeAILogger
Expand Down Expand Up @@ -107,6 +113,7 @@ def initialize(
raise ValueError("Output folder is not set")

image_files = DiskImageFileStorage(f"{output_folder}/images")
video_files = DiskVideoFileStorage(f"{output_folder}/videos")

model_images_folder = config.models_path
style_presets_folder = config.style_presets_path
Expand All @@ -131,6 +138,10 @@ def initialize(
bulk_download = BulkDownloadService()
image_records = SqliteImageRecordStorage(db=db)
images = ImageService()
video_records = SqliteVideoRecordStorage(db=db)
videos = VideoService()
board_video_records = SqliteBoardVideoRecordStorage(db=db)
gallery = SqliteGalleryService(db=db)
invocation_cache = MemoryInvocationCache(max_cache_size=config.node_cache_size)
tensors = ObjectSerializerForwardCache(
ObjectSerializerDisk[torch.Tensor](
Expand All @@ -152,6 +163,7 @@ def initialize(
ZImageConditioningInfo,
QwenImageConditioningInfo,
AnimaConditioningInfo,
WanConditioningInfo,
],
ephemeral=True,
),
Expand Down Expand Up @@ -221,6 +233,11 @@ def initialize(
workflow_thumbnails=workflow_thumbnails,
client_state_persistence=client_state_persistence,
users=users,
videos=videos,
video_files=video_files,
video_records=video_records,
board_video_records=board_video_records,
gallery=gallery,
)

ApiDependencies.invoker = Invoker(services)
Expand Down
97 changes: 97 additions & 0 deletions invokeai/app/api/routers/gallery.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
from typing import Optional

from fastapi import HTTPException, Query
from fastapi.routing import APIRouter

from invokeai.app.api.auth_dependencies import CurrentUserOrDefault
from invokeai.app.api.dependencies import ApiDependencies
from invokeai.app.api.routers.images import _assert_board_read_access
from invokeai.app.services.gallery.gallery_common import GalleryItem, GalleryItemNamesResult
from invokeai.app.services.image_records.image_records_common import ImageCategory, ResourceOrigin
from invokeai.app.services.shared.pagination import OffsetPaginatedResults
from invokeai.app.services.shared.sqlite.sqlite_common import SQLiteDirection

gallery_router = APIRouter(prefix="/v1/gallery", tags=["gallery"])


@gallery_router.get(
"/items/",
operation_id="list_gallery_items",
response_model=OffsetPaginatedResults[GalleryItem],
)
async def list_gallery_items(
current_user: CurrentUserOrDefault,
origin: Optional[ResourceOrigin] = Query(default=None, description="The origin of items to list."),
categories: Optional[list[ImageCategory]] = Query(
default=None,
description="The categories to include. Shared between images and videos.",
),
is_intermediate: Optional[bool] = Query(default=None, description="Whether to list intermediate items."),
board_id: Optional[str] = Query(
default=None,
description="The board id to filter by. Use 'none' to find items without a board.",
),
offset: int = Query(default=0, description="The page offset"),
limit: int = Query(default=10, description="The number of items per page"),
order_dir: SQLiteDirection = Query(default=SQLiteDirection.Descending, description="The order of sort"),
starred_first: bool = Query(default=True, description="Whether to sort by starred items first"),
search_term: Optional[str] = Query(default=None, description="The term to search for"),
) -> OffsetPaginatedResults[GalleryItem]:
"""Returns a paginated, time-sorted stream of polymorphic gallery items (images + videos)."""
if board_id is not None and board_id != "none":
_assert_board_read_access(board_id, current_user)

return ApiDependencies.invoker.services.gallery.list_items(
offset=offset,
limit=limit,
starred_first=starred_first,
order_dir=order_dir,
origin=origin,
categories=categories,
is_intermediate=is_intermediate,
board_id=board_id,
search_term=search_term,
user_id=current_user.user_id,
is_admin=current_user.is_admin,
)


@gallery_router.get(
"/items/names",
operation_id="get_gallery_item_names",
response_model=GalleryItemNamesResult,
)
async def get_gallery_item_names(
current_user: CurrentUserOrDefault,
origin: Optional[ResourceOrigin] = Query(default=None, description="The origin of items to list."),
categories: Optional[list[ImageCategory]] = Query(
default=None,
description="The categories to include. Shared between images and videos.",
),
is_intermediate: Optional[bool] = Query(default=None, description="Whether to list intermediate items."),
board_id: Optional[str] = Query(
default=None,
description="The board id to filter by. Use 'none' to find items without a board.",
),
order_dir: SQLiteDirection = Query(default=SQLiteDirection.Descending, description="The order of sort"),
starred_first: bool = Query(default=True, description="Whether to sort by starred items first"),
search_term: Optional[str] = Query(default=None, description="The term to search for"),
) -> GalleryItemNamesResult:
"""Returns an ordered (kind, name) list — used to drive virtualized gallery selection."""
if board_id is not None and board_id != "none":
_assert_board_read_access(board_id, current_user)

try:
return ApiDependencies.invoker.services.gallery.list_item_names(
starred_first=starred_first,
order_dir=order_dir,
origin=origin,
categories=categories,
is_intermediate=is_intermediate,
board_id=board_id,
search_term=search_term,
user_id=current_user.user_id,
is_admin=current_user.is_admin,
)
except Exception:
raise HTTPException(status_code=500, detail="Failed to get gallery item names")
Loading
Loading