Most production video pipelines do not break because a model renders badly. They break because the model cannot hold a character, a set or a voice steady across a dozen short clips generated on different days. According to the Vidu Q4 product page, the model is aimed squarely at that continuity problem: it is described as an AI video model from Shengshu Technology that "generates video and sound together", with reference images and voice references as first-class inputs rather than an afterthought.
That framing matters for anyone building a repeatable workflow. The same page states that Vidu Q4 "does not support text-to-video yet" and that "Every Vidu Q4 video begins with at least one image". Two operating modes are documented. Image-to-video takes one image plus a prompt and returns a 3 to 16 second clip. Reference-to-video takes 1 to 15 reference images and up to 3 voice references and produces one clip of 1 to 16 seconds. Some API hosts, the page notes, list a lower ceiling of 12 reference images, so the scripted limit should be read from the host you actually call, not from the marketing page.
When a clip could be produced from text alone, the prompt was the whole specification. With image-first generation the specification migrates into assets: a base frame, a set of character references, an optional voice reference, and a prompt that describes motion rather than appearance. Practically, that means a job manifest has to version binary assets, not just strings. If the reference set is not pinned, a rerun next week is not a rerun at all; it is a new experiment wearing the same job name.
The second consequence is that a single "generate video" step becomes two verification steps. One checks that the job definition still satisfies the documented input constraints. The other checks the returned artefact against the intent. Both are cheap to automate and both fail loudly when someone edits a manifest by hand.
The snippet below is a local validator only. It does not call the service; it rejects malformed jobs before they reach the queue, which is where most wasted generations originate. The limits encode the documented ranges, with the reference ceiling as a parameter so a stricter host can be injected.
from dataclasses import dataclass, field from pathlib import Path MAX_REFS_DEFAULT = 15 # product page; some API hosts list 12 @dataclass class ClipJob: name: str prompt: str duration_s: int resolution: str # 540p, 720p, 1080p, 2K, 4K base_image: Path refs: list = field(default_factory=list) voices: list = field(default_factory=list) mode: str = "image-to-video" # or "reference-to-video" def validate(job, max_refs=MAX_REFS_DEFAULT): errors = [] if not job.base_image.exists(): errors.append(f"base image missing: {job.base_image}") lo, hi = (3, 16) if job.mode == "image-to-video" else (1, 16) if not lo <= job.duration_s <= hi: errors.append(f"{job.mode} duration must be {lo}-{hi}s, got {job.duration_s}") if not 1 <= len(job.refs) <= max_refs: errors.append(f"need 1-{max_refs} reference images, got {len(job.refs)}") if len(job.voices) > 3: errors.append(f"at most 3 voice references, got {len(job.voices)}") if job.resolution not in {"540p", "720p", "1080p", "2K", "4K"}: errors.append(f"unsupported resolution tier: {job.resolution}") if not job.prompt.strip(): errors.append("prompt is empty; motion still has to be described") for r in list(job.refs) + list(job.voices): if not Path(r).exists(): errors.append(f"reference asset missing: {r}") return errors
Two design notes are worth keeping. First, the resolution tier is a discrete set rather than a free integer, which mirrors how the output is described on the product page and keeps billing estimates stable. Second, the validator refuses an empty prompt even though an image is mandatory: the image carries appearance, the prompt carries motion, and a job with no motion instruction tends to return a slow zoom that has to be discarded.
A clip that returns successfully is not a clip that is usable. A review checklist that a non-author can apply in under a minute catches most of the expensive mistakes:
The gate should write its result back onto the job record: pass, reject reason, and the asset hash of what was reviewed. Without that hash, a later "it looked fine last week" claim cannot be checked.
Three failure classes deserve separate handling. A malformed job is a validator failure and never reaches the service. A rejected generation is a creative failure: keep the reference set fixed and change exactly one element of the prompt, otherwise the two runs cannot be compared. A transport or capacity failure is infrastructure: retry with backoff, and keep the manifest byte-identical so the retry is still the same experiment.
The page also notes that "Vidu Q4 Preview is an early version released before the full Vidu Q4" and that "specs, limits and prices can still change". That is a scheduling constraint as much as a technical one. Pin the model version in the manifest, log the version string next to every output, and treat a silent change in tier availability as a build break rather than a surprise. For budgeting, the honest position is that cost scales with the requested duration and output tier; exact figures have to be read from the provider at the time of the run rather than hard-coded into a spreadsheet from memory.
A stopping rule keeps a batch from quietly burning a day. If two consecutive reruns of the same job with the same pinned references are rejected, stop and inspect the reference set instead of regenerating. Reference drift is the most common root cause of a job that "used to work", and no number of retries fixes a stale costume sheet.
The useful mental model is that Vidu Q4 turns a text prompt into one input among several. Teams that already version assets, gate outputs and log job definitions will find that the model slots into an existing pipeline with a manifest change. Teams that treat generation as a chat box will produce clips they cannot reproduce. The product page is the right place to check current input limits before freezing a manifest, because the reference ceiling and preview status are exactly the kind of numbers that move.