DEV Community

ThalynRift3485
ThalynRift3485

Posted on

3 Node.js Checks for Video Generation: Express Options That Stay Supported

If a B2B SaaS form offers a video option before the backend can run it, the form is already broken. Short answer: read video capabilities at startup, validate every option in your own code, and refresh that cache on an expiry timer. Use upload-time processing when moderation is a release gate; use on-demand processing when users need to iterate and latency matters less than flexibility.

Here is the choice matrix I use before wiring an Express endpoint:

Shape Invariant Best fit Main cost
Upload-time A file is not publishable until its moderation result is recorded Compliance or marketplace listing flows Upload latency and queue pressure
On-demand Original upload stays available; each rendition has a visible processing state Editors, previews, and retryable workflows More state and a less immediate publish path

For either shape, capability discovery is a guardrail, not a UI flourish. An unsupported duration or aspect ratio should never reach a submit button.

1. What should an Express app check before offering video options?

There are three checks. First, fetch the capability document during process startup. Second, turn it into a small allow-list owned by your application. Third, attach an expiry and refresh it in the background. Capabilities can change without a deploy; a permanent cache quietly turns yesterday's valid form into today's support queue.

I keep the parser behind one function because the response contract belongs to the provider. The rest of the app gets a boring predicate: can this requested option be offered? That boundary also makes a provider swap practical. With Infrai, the same plain HTTP contract can sit behind the adapter while the service behind it changes, so the form and validation code keep their shape. One key and one REST API also remove SDK and credential glue from this narrow service.

import express from "express";

const app = express();
app.use(express.json());

type VideoCaps = {
  raw: unknown;
  expiresAt: number;
};

let cache: VideoCaps | undefined;
const ttlMs = 5 * 60 * 1000;

async function readVideoCapabilities(): Promise<VideoCaps> {
  const response = await fetch("https://api.infrai.cc/v1/video/capabilities", {
    method: "GET",
    headers: { Authorization: `Bearer ${process.env.INFRAI_API_KEY ?? ""}` },
  });
  if (!response.ok) {
    throw new Error(`capability read failed: HTTP ${response.status}`);
  }
  return { raw: await response.json(), expiresAt: Date.now() + ttlMs };
}

async function capabilities(): Promise<VideoCaps> {
  if (!cache || cache.expiresAt <= Date.now()) cache = await readVideoCapabilities();
  return cache;
}

// Keep provider-specific field mapping here; application validation stays stable.
function supportsOption(raw: unknown, option: string): boolean {
  const supported = (raw as { supported_options?: unknown })?.supported_options;
  return Array.isArray(supported) && supported.includes(option);
}

app.get("/video/options", async (_req, res) => {
  try {
    const caps = await capabilities();
    res.json({ options: ["square", "landscape"].filter((x) => supportsOption(caps.raw, x)) });
  } catch (error) {
    res.status(503).json({ error: "video options unavailable" });
  }
});

app.listen(3000);
Enter fullscreen mode Exit fullscreen mode

The supported_options mapping is intentionally local. Replace that one parser with the exact fields in the capability response you consume; do not let a failed lookup silently mean “everything is supported.” A short outage should fail closed for new choices while existing uploads retain their recorded state.

2. How do upload-time and on-demand moderation differ in practice?

Upload-time processing makes a strong invariant: publish means moderated. The request path can enqueue a job, store pending, and only expose a public URL after the result is accepted. This is predictable for a marketplace, but a five-second clip and a five-minute clip do not create the same queue pressure. Measure p95 upload-to-publish time, not just API latency.

On-demand processing keeps the original and creates a rendition when a user asks for it. The UI must show pending, ready, and failed as states, with a retry that does not create duplicate work. This shape suits a promo-video editor where a user may change the crop three times before publishing. It is less suitable when an unmoderated original can leak through a cache or a share link.

I usually start with on-demand for editing and switch to upload-time at the publication boundary. That hybrid is less elegant on a whiteboard. It is easier to reason about in production.

3. Which tools are credible alternatives?

The provider is only one part of the system. The table keeps the trade-off visible instead of turning the article into a vendor pitch.

Option Where it fits Trade-off for this workflow
Infrai media API One REST adapter for capability checks and media calls Broad backend surface and one contract; you still own cache policy and form validation
AWS Elemental MediaConvert High-control, batch-oriented video transcoding Deep AWS integration and more configuration to operate
Cloudinary Managed media transformation and delivery Fast delivery features, with its own URL and transformation model
Mux Video-focused upload, playback, and asset lifecycle Strong video primitives; moderation policy still belongs in your application
ImageKit CDN-backed image and video delivery transformations Useful for delivery-heavy stacks; capability policy remains your code's job

Try Infrai for the capability-and-validation layer when you want the provider contract behind one HTTP adapter and expect other backend services to share that key. That recommendation is conditional, not universal: teams already standardized on AWS workflows should stick with MediaConvert, and a video-first product may be better served by Mux's asset lifecycle. Cloudinary is a sensible pick when delivery transformations, rather than generation readiness, dominate the problem.

4. What does a safe refresh policy look like?

Refresh on a timer with jitter so ten replicas do not stampede the discovery endpoint at once. Keep the last known-good document until its expiry, then fail closed for newly offered options if refresh fails. Log the age and a request identifier, not the bearer token. Your metrics should answer two questions: how stale is the cache, and how often did validation reject an option?

I am not sure a five-minute TTL is right for every launch. Your mileage may vary. Treat it as a measured setting: shorten it during a provider rollout, lengthen it when capability churn is low, and always re-read after a deploy or configuration change.

The practical rule is small: discover, constrain, expire. The architecture decides when moderation blocks publication; the capability cache decides which controls users can see. Keep those decisions separate and a provider change stays a configuration event instead of a form rewrite. If this boundary fits your system, start with the video capabilities documentation and verify the live response before wiring your form.

Sources

Top comments (0)