Skip to content

Serve video as a job at /v1/videos, matching the wan2gp-api container - #68

Merged
TroyHernandez merged 3 commits into
mainfrom
feat/async-video-serve
Sep 22, 2026
Merged

TroyHernandez merged 3 commits into
mainfrom
feat/async-video-serve

Conversation

@TroyHernandez

Copy link
Copy Markdown
Contributor

diffuseR::serve's video endpoint was POST /v1/videos/generations returning
raw mp4 bytes synchronously. This moves it to the create/poll/download job
shape the wan2gp-api container now uses, so a client written for that
contract (xtx.api's wan2gp_api backend) can talk to either service
unchanged:

POST   /v1/videos              -> 202 {id, status}
GET    /v1/videos/{id}         -> {status, progress, ...}
GET    /v1/videos/{id}/content -> the mp4

The server is single-threaded and holds the model in-process, so true
background async is not possible without a second model copy. Generation is
still synchronous on create (the create call blocks for the render), but the
result is stored behind a job id and fetched separately, which makes the
contract uniform with the container. A bounded LRU (max_jobs, default 8)
keeps recent results and evicts old files. POST /v1/images/generations and
the CUDA-OOM-exits-for-restart behaviour are unchanged.

Verification

  • test_serve.R: 44 assertions pass against source (pkgload::load_all),
    covering create/status/content and eviction with the model call stubbed.

diffuseR::serve's video endpoint was POST /v1/videos/generations returning
raw mp4 bytes synchronously. Move it to the create/poll/download job shape
the wan2gp-api container now uses, so a client written for that contract
(xtx.api's wan2gp_api backend) can talk to either service unchanged:

  POST   /v1/videos              -> 202 {id, status}
  GET    /v1/videos/{id}         -> {status, progress, ...}
  GET    /v1/videos/{id}/content -> the mp4

The server is single-threaded and holds the model in-process, so true
background async is not possible without a second model copy: generation is
still synchronous on create (the create call blocks for the render), but the
result is stored behind a job id and fetched separately, and the split makes
the contract uniform with the container. A bounded LRU (max_jobs, default 8)
keeps recent results and evicts old files. Image generation
(/v1/images/generations) and the CUDA-OOM-exits-for-restart behaviour are
unchanged. test_serve.R covers create/status/content and eviction with the
model call stubbed (44 assertions pass).
@TroyHernandez
TroyHernandez merged commit 17e1e7f into main Sep 22, 2026
2 checks passed
@TroyHernandez
TroyHernandez deleted the feat/async-video-serve branch September 22, 2026 21:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant