MediaRouter / docs /generation-wan.md
basyx's picture
Upload 794 files
1b2323a verified
|
Raw
History Blame Contribute Delete
8.25 kB

WAN 2.2 generation provider

Status

MediaRouter integrates the audited WAN 2.2 Hugging Face worker as the wan generation provider. The registered public model ID is wan2.2. The underlying worker model reported by /v1/info is Wan-AI/Wan2.2-I2V-A14B-Diffusers; it is metadata, not the MediaRouter model identifier.

FLUX is a separately configured optional image provider; it does not share WAN credentials, request fields, worker IDs, or publishing behavior.

Worker contract verified

The configured worker is expected to expose:

Method Endpoint Authentication Use
GET /health public Liveness only
GET /ready public Loaded model and whether it accepts jobs
GET /v1/info public Model identity/capability discovery
POST /v1/generate Bearer Authenticated multipart image-to-video submission
GET /v1/jobs/{id} Bearer Job reconciliation
POST /v1/jobs/{id}/cancel Bearer Queued-job cancellation only
GET /v1/jobs/{id}/output Bearer Completed MP4 stream

The worker reports:

{
  "id": "wan2.2",
  "name": "WAN 2.2 FP8 AOTI Faster",
  "type": "video",
  "task": "image-to-video",
  "model_id": "Wan-AI/Wan2.2-I2V-A14B-Diffusers",
  "fps": 16
}

Model availability is deliberately stricter than a successful HTTP health check. MediaRouter advertises wan2.2 as available only after all of these are true: WAN is completely configured, /health is healthy, /ready says ready with model_loaded: true and accepting_jobs: true, /ready names wan2.2, and /v1/info reports the exact wan2.2 image-to-video model, the audited Wan-AI/Wan2.2-I2V-A14B-Diffusers underlying model, and 16 FPS.

Server configuration

Set these only in backend deployment secrets:

WAN_SPACE_URL=https://your-wan-worker.hf.space
WAN_SPACE_TOKEN=replace-with-the-worker-secret
AI_WORKER_CONNECT_TIMEOUT_SECONDS=10
AI_WORKER_REQUEST_TIMEOUT_SECONDS=60
AI_WORKER_READ_TIMEOUT_SECONDS=300
AI_WORKER_MAX_RETRIES=3
AI_WORKER_RETRY_BACKOFF_SECONDS=0.5
GENERATION_WORKER_ENABLED=true
GENERATION_WORKER_INTERVAL_SECONDS=5
GENERATION_WORKER_POLL_BACKOFF_SECONDS=2
GENERATION_JOB_STALE_AFTER_SECONDS=900

WAN_SPACE_URL and WAN_SPACE_TOKEN must be configured together. The token must meet the worker's 32–4096-character requirement. They are never exposed through REST, browser data, MCP, n8n, SDK results, audit records, or logs.

WAN is optional: omitted or invalid WAN settings leave only WAN unavailable; they do not stop MediaRouter, social publishing, or unrelated workers.

Request contract

WAN is image-to-video. The caller references an existing canonical, workspace-owned image asset; no local path, worker URL, worker header, or output URL may be sent by a client.

{
  "provider": "wan",
  "model_id": "wan2.2",
  "modality": "video",
  "input_asset_id": "canonical-image-asset-uuid",
  "prompt": "Slow cinematic cloud movement over a mountain valley",
  "wan": {
    "negative_prompt": "blur, artifacts",
    "duration_seconds": 0.5,
    "steps": 4,
    "guidance_scale": 1.0,
    "guidance_scale_2": 1.0,
    "seed": 42,
    "randomize_seed": false
  }
}

wan is a strict typed Pydantic object. Its worker-verified fields are:

Field Required Range/default
input_asset_id yes Readable owned image; max 20 MiB at WAN submission
prompt yes Nonblank, 1–4000 characters
negative_prompt no Max 4000 characters; omitted uses WAN's default
duration_seconds no 0.5–5.0; WAN default 5.0
steps no 1–30; WAN default 4
guidance_scale no 0–10; WAN default 1
guidance_scale_2 no 0–10; WAN default 1
seed no 0–2147483647; WAN default 42
randomize_seed no Boolean; WAN default false

width, height, and num_frames are rejected. WAN derives supported dimensions from the source image and frames from duration at 16 FPS. The worker additionally rejects unreadable images, source sides above 16384, source images above 40,000,000 pixels, and derived dimensions outside 480–832 or not divisible by 16. Unknown top-level and WAN options are rejected; MediaRouter does not forward arbitrary provider fields. Output is a streamed video/mp4 file.

Job lifecycle and idempotency

POST /v1/generation/requests
        ↓ 202 (MediaRouter job ID only)
durable generation request + job
        ↓
GenerationWorker claims with database row lock
        ↓
WAN multipart submission
        ↓
persist opaque WAN worker job ID
        ↓
bounded status polling
        ↓
stream /output β†’ staging β†’ validation β†’ canonical asset
        ↓
MediaRouter job succeeds

The reconciliation queue uses a durable, bounded lease in the existing job's next_attempt_at field. This prevents separate worker processes from polling or ingesting the same WAN output at the same time; a crashed worker's lease expires and another worker can reconcile the already-bound remote job without submitting it again.

The public API never returns the WAN job ID as the MediaRouter job identity. The database protects (provider, external_job_id) uniqueness and every lookup/cancellation starts with the caller's workspace-owned MediaRouter job.

The API idempotency key creates one logical MediaRouter request/job for an identical request and reports conflict for a changed request. WAN itself has no submission idempotency protocol. MediaRouter therefore never automatically resubmits after a connection failure, timeout, 502, or 504 that could have created a remote job while losing its response. Such a submission is recorded as GENERATION_SUBMISSION_AMBIGUOUS and is not retried. This is a safe at-most-once submission strategy, not an exactly-once guarantee.

Received 429 and 503 rejection responses may be retried within the durable generation attempt limit. Polling uses the shared bounded retry policy for connection failures, timeouts, 429, 502, 503, and 504; 400, 401, 403, invalid worker job IDs, validation failures, generic 500s, and programming failures are not retried automatically.

Cancellation and status

WAN supports cancellation only while the remote job is queued. A confirmed worker cancelled response moves the MediaRouter job to cancelled. A WAN 409 WAN_JOB_NOT_CANCELLABLE for a running job is a cancellation failure: MediaRouter preserves the active job and never claims GPU inference stopped.

WAN state is normalized into the existing generation state machine:

WAN state MediaRouter state
queued queued after worker identity is bound
running running
completed output finalization, then succeeded
failed failed unless a separately safe pre-acceptance retry applies
cancelled cancelled

Output and security

On completion, WAN returns only a video type and filename. The adapter creates a validated internal descriptor for the fixed relative endpoint /v1/jobs/{worker-job-id}/output, video/mp4, and the opaque worker job ID. It never trusts a worker filesystem path or arbitrary output URL.

The shared worker client rejects non-server-configured worker origins, redirects, private literal IPs, unsafe endpoint paths, URL traversal, signed URLs, and client-supplied output locations. MP4 bytes are streamed without loading the output into memory, staged in a controlled directory, size and checksum verified where available, FFprobe/MediaValidator checked, then registered as a workspace-owned canonical asset. The canonical asset ID, MIME type, size, checksum, and safe media metadata are attached to the generation job.

Verification status

Mocked protocol tests cover model discovery, readiness, multipart translation, non-idempotent submission behavior, output normalization, cancellation, typed parameter rejection, optional configuration, and the shared worker runtime retry/SSRF/redaction behavior. A live WAN smoke test requires both WAN_SPACE_URL and WAN_SPACE_TOKEN; it is intentionally not run in normal CI and must be reported as not verified when those secrets are absent.