Repository navigation
Video generation via stable-diffusion.cpp #3527
Replies: 7 comments 6 replies
|
@ramkrishna2910 @jeremyfowers @bitgamma this is the RFC for #3506, following the new policy. |
|
@Bekhouche can you describe the quantization crash in more detail (or point me to an upstream issue)? I have a feeling I fixed that one already in one of my branches, so might as well push a fix upstream and get that one out of the way. |
|
@pwilkin Sure. It is not a load crash, I had that wrong in the RFC. sd-cpp master-827-97d2990, Vulkan, RX 7900 XTX 24 GB, Windows. Wan2.1-T2V-1.3B fp16 + umt5-xxl-encoder-Q5_K_M + wan_2.1_vae, with --vae-tiling --diffusion-fa. The model loads fine (10083 MB total, text encoder 7132 MB). It dies on the first generation, in T5 conditioning: ggml_vulkan: Device memory allocation of size 4200595456 failed. The odd part: Q8_0 works on the same GPU with the same flags, and it is the bigger file (5.7 GB vs 3.9 GB). So it does not look like a VRAM shortage, more like the k-quant path needing one large contiguous buffer. No upstream issue for this exact case. leejet/stable-diffusion.cpp#1718 looks like the same mechanism with a different conditioner, and #942 is Wan on Vulkan. |
|
Thanks for opening this @Bekhouche. |
|
@Bekhouche please detail the new proposed API with all fields. Ideally, we want to be at compatible with https://developers.openai.com/api/docs/guides/video-generation at least for the base use-cases |
|
@bitgamma Here are all the fields, split by phase, so it is clear what #3506 ships now and what the API needs to grow into later. Phase 0: what already existsstable-diffusion.cpp is already inside Lemonade, and it already supports video. Nothing exposes it, so the feature is there but users cannot reach it. #3506 does not add an engine. It opens the one we already install. Phase 1:
|
| Field | Required | Type | Default |
|---|---|---|---|
prompt |
yes | string | none |
model |
yes | string | none |
negative_prompt |
no | string | none |
video_frames |
no | int | recipe option, then 33 |
fps |
no | int | recipe option, then 24 |
width / height |
no | int | recipe option, then backend default |
steps |
no | int | recipe option |
cfg_scale |
no | number | recipe option |
sampling_method |
no | string | recipe option |
flow_shift |
no | number | recipe option |
seed |
no | int | random |
output_format |
no | string | webm (also webp, avi) |
The response is one JSON object with b64_json, mime_type, output_format, frame_count and fps.
Phase 2: progress and cancellation
This adds no new generation fields. It changes the response shape. The server returns a job instead of a finished video.
This is a smaller change than it looks. /sdcpp/v1/vid_gen is already asynchronous. It answers with 202 and a poll URL. Today I poll it in a loop and hide this from the caller. So showing the job means removing that loop, not writing new code. Lemonade also already has a job engine with pause, interrupt and resume. This phase fixes three risks I listed above: no progress, no way to cancel, and very large responses. It also answers #3121.
Phase 3: more input modes
These are the fields that Phase 1 does not have. The backend already supports all of them. Each one needs a file as input, so they change the request shape.
| Mode | Backend input | New fields |
|---|---|---|
| Image to video | --init-img |
one reference image |
| First and last frame | --init-img + --end-img |
a second reference image |
| Video to video / control | --control-video, --control-image, --control-strength |
a reference video, plus strength |
| Video editing (Wan VACE) | --vace-strength |
a source video, plus strength |
| Reference guided | -r/--ref-image (can repeat), --ip-adapter-image |
one or more reference images |
| Ref2VA (MiniMax-H3) | --ref-video, --ref-audio, --ref-video-audio |
reference video and audio |
How this fits the OpenAI guide
The OpenAI shape covers Phase 1 and part of Phase 3. It has text to video, and image to video through input_reference. Remix is close to video editing. But end frame, control video, many reference images and reference audio have no OpenAI field. Those would stay as Lemonade extras. So we can be compatible for the common cases, but not for everything the backend can do.
There are four places where Phase 1 does not match today, and I think you are right that it should:
- Sync or async. OpenAI returns a job and the client checks it. Mine keeps the HTTP connection open for several minutes. This is Phase 2.
- Route. OpenAI uses
/v1/videos. I used/v1/videos/generationsto match our image routes. - Length and size. OpenAI uses
secondsandsize. I usevideo_frameswithfps, andwidthwithheight, because that is what the model takes. - How the file is returned. OpenAI serves the bytes from a content endpoint. I return base64 inside the response, like our image endpoints.
Point 4 becomes more important in Phase 3. Reference images and videos do not fit well in a JSON body, so the create call needs multipart, like OpenAI does for input_reference. We already do this with images: /images/generations is JSON and /images/edits is multipart.
What I propose
Move the Phase 2 shape into #3506 now: POST /v1/videos that accepts JSON or multipart and returns id, status, progress, created_at and model, then GET /v1/videos/{id} to check it, and GET /v1/videos/{id}/content to get the file. Phase 1 would still ship text to video only, but the shape would then have room for Phase 3 without a breaking change later.
Two questions:
- Names. Should
secondsandsizebe the documented names, and we convert to frames usingfps, keepingvideo_frames,widthandheightas extras? Or should we keep the model names as the main ones? - Scope. Should the Phase 2 shape go into feat(backends): video generation via stable-diffusion.cpp #3506, or should feat(backends): video generation via stable-diffusion.cpp #3506 stay as it is and Phase 2 come next? I prefer to do it now, so we do not ship an API and then change it.
Thanks also @ramkrishna2910 for the Strix Halo CI offer. That covers the exact gap I wrote about in the maintenance plan, and I will take it up.
|
I like the approach but would like to address one thought on the API shape:S I would still keep familiar OpenAI-style naming where it makes sense, but define Lemonade's video API around generic async job semantics from day one. Video generations can take minutes, sd.cpp is already async internally, and progress/cancellation are much easier to support cleanly that way than by starting with a synchronous API and changing it later. Hugging Face's Inference Providers may also be worth looking at as another reference: they already abstract text-to-video across multiple providers, but use their own task API rather than extending OpenAI compatibility to video: For the public API I'd also keep the common path backend-neutral and user-facing, e.g. duration and size, while exposing things like frames, fps, width/height and sd.cpp-specific controls as optional advanced parameters rather than making backend details part of the core API. This also fits #3426 nicely: the server should own the generation lifecycle and backend-specific orchestration, while clients/MCP interact with one stable capability instead of knowing how a particular backend handles jobs internally. |
Uh oh!
There was an error while loading. Please reload this page.
Proposal size: Major feature (spans multiple well-scoped PRs)
Note: The first phase is already written and open as PR #3506. I am writing this RFC now to follow the new policy.
User story
As someone running Lemonade locally, I want to create short videos from a text prompt, so I can use a local video model in the same way I already use local models for images and speech.
Today this is not possible, even though the engine is already installed. Lemonade includes stable-diffusion.cpp, and this backend already supports video models such as Wan and LTX. But Lemonade does not make these models available to users. Cloud model discovery also skips video models. So right now there is no way to generate a video in Lemonade.
This was requested in discussion #2981 in August, but there was no answer for about four weeks. The request had two main parts: an API endpoint for video generation, and a way to view the video in the desktop app.
High-level design
Add a new video endpoint that takes a text prompt and returns a short video. It sits next to the existing image, speech, and 3D endpoints.
For the user it works like image generation: send a prompt, get a result.
This first phase covers text to video only.
stable-diffusion.cpp also supports other video modes: image to video, first-and-last-frame to video, and video to video using control frames. Wan also has a VACE mode for video editing. These are not part of phase 1, but the endpoint should be able to grow into them later.
There is one open question here. Text to video only needs a JSON request. The other modes need an input image or video, so they may need a different request format. Lemonade already does this for images:
/images/generationstakes JSON, and/images/editstakes multipart form data. I would like feedback on whether to plan for this now, or to add a separate endpoint later.Breaking changes
None. This only adds a new endpoint, a label, and a catalog entry. Existing APIs and behaviour do not change.
Maintenance plan
I will maintain the video part of the stable-diffusion.cpp backend. I have worked with generative AI and diffusion models for the last two to three years, so this is the area I can support best.
I am also happy to help with image generation issues when needed, but video is the part I commit to maintain.
Automated testing will cover less than usual, and I want to be clear about this.
CI can test that:
These tests do not download models, so they can run on normal CI runners.
CI cannot test video generation itself. The test needs about 8.5 GB of model weights and a GPU, because CPU inference is too slow. One short video takes about three minutes on a discrete GPU.
There is also a limit on what a test can check. A test can check that the file is a real video, that it has the right number of frames, and that the frames are not all the same. So a single image repeated many times would fail. What a test cannot check is quality. It cannot tell if the video matches the prompt or looks right. A person has to watch it for that.
So the generation test is optional and needs a running server with a GPU. For most changes the automated checks are enough. When a change can affect the output itself, or when a new model is added, someone should also watch a video. I have a discrete GPU and I can do this.
Ongoing maintenance
Risks
The second and third points are the main things I would fix next, in the progress and cancellation phase below.
Issue #3121 already asks for progress reporting in the stable-diffusion backend. That phase would also answer it for video.
Phases
Phase 1 is already open as PR #3506. After that:
The last two are a direction, not a promise for the next PR. I mention them because they show the endpoint is not a dead end, and because video has the same small model or big model choice that text already has.
One more thing, better to say now than to find later: the desktop app follows the list of labels in the docs, and it checks how many labels there are. Adding a video label needs a change on the app side at the same time, or the app build breaks after the next merge.
All reactions