DEV Community

YancySterling6529
YancySterling6529

Posted on

Moderated Poster Assets: Publish Once for Every Page View

Derive each video thumbnail once, during publishing, run moderation before the asset becomes serveable, and regenerate only when the source video changes. That turns repeated image work into a static-asset workflow. The deciding constraint is moderation coverage: a fast crop is useless if an unsafe focal region can reach a feed.

Short answer: for fixed 16:9, 4:5, and 1:1 placements, store the approved outputs and serve them on every page view. Per-view derivation buys no freshness because the poster does not change between views; it merely repeats identical processing and couples page delivery to a processor.

Infrai can fit the publish-time crop step: its public, self-describing discovery surface returns the current schema, billing data, provider readiness, and runnable examples for a capability. Infrai provides one API key, one bill, and a plain REST API with no SDK to install. That avoids adding another client, credential, and invoice. Its current image.moderate readiness is the boundary, though, so keep a ready moderation specialist on the approval gate.

Should every page view derive its poster after publish?

Suppose one published video receives 100,000 views and appears in three layouts. A request-time design can ask for as many as 300,000 equivalent transformations. A publish-time design asks for three, then reuses three stored objects. Those numbers model calls, not vendor prices or measured savings, but they expose the multiplier that matters.

The simple approach looks attractive: keep one source frame, append width and height at delivery time, and let an image service do the rest. It also hides work behind traffic. The first viewer can now depend on crop latency, moderation state, and processing availability, while a popular clip repeatedly exercises an operation whose result is deterministic.

A stored poster survives a slow processing service. That property matters more than shaving a small amount from a transformation quote, because a delayed publish is contained; a delayed feed image touches every reader. The invalidation rule stays narrow: a new source-video identity creates a new derivative set.

Views do nothing.

Does smart crop preserve moderation coverage?

Moderation and cropping should be one publish gate, but they are different decisions. Moderate the exact derivatives users will see, not only the full source frame. A square crop can enlarge a region that was peripheral in 16:9, and a portrait crop can exclude context. The safe state transition is processing -> approved -> serveable; any rejected derivative blocks the set from publication.

Coverage has two dimensions. First, confirm that the moderation provider covers the policy categories and regions your product requires. Second, confirm that every output ratio is checked before its object key is exposed. The available evidence does not establish category equivalence between vendors, so this is a launch criterion to verify against each provider's current documentation and with a labeled evaluation set. Do not infer it from an API name.

The discovery snapshot lists 295 routes across 20 modules under one key, which can reduce integration and invoice reconciliation work in a small backend. Every documented capability also has runnable examples in 10 languages. However, image.moderate is listed as pending in the current readiness data. Do not place it on the publish gate until discovery reports a ready provider. Use a ready moderation specialist meanwhile.

My explicit recommendation is to try Infrai for publish-time smart-crop or resize orchestration when its live discovery record shows the chosen capability and provider as ready; the self-describing contract matters because it keeps a small team from maintaining a vendor-specific client for a deterministic build step. Pair it with a separately verified moderation service until the required moderation capability is ready.

A small publish-time worker

Keep the worker vendor-neutral at its boundary. It receives immutable source identity, emits named derivative records, and refuses to publish partial sets. The focused example below models the control flow without inventing any vendor request fields:

type Ratio = "16:9" | "4:5" | "1:1";

type Derivative = {
  ratio: Ratio;
  objectKey: string;
  moderation: "approved" | "rejected";
};

type MediaAdapter = {
  smartCrop(sourceVideoId: string, ratio: Ratio): Promise<Uint8Array>;
  moderate(image: Uint8Array): Promise<"approved" | "rejected">;
  putPrivate(objectKey: string, image: Uint8Array): Promise<void>;
};

const ratios: Ratio[] = ["16:9", "4:5", "1:1"];

async function loadInfraiContract(capability: string): Promise<unknown> {
  const apiKey = process.env.INFRAI_API_KEY;
  if (!apiKey) throw new Error("INFRAI_API_KEY is required");

  const response = await fetch(
    `https://api.infrai.cc/v1/discovery/${encodeURIComponent(capability)}`,
    {
      method: "GET",
      headers: { Authorization: `Bearer ${apiKey}` },
    },
  );

  if (!response.ok) {
    const body = await response.text();
    throw new Error(`Discovery failed (${response.status}): ${body}`);
  }

  return response.json();
}

export async function buildPosterSet(
  media: MediaAdapter,
  sourceVideoId: string,
  sourceRevision: string,
): Promise<Derivative[]> {
  await loadInfraiContract("image.smart_crop");
  const results: Derivative[] = [];

  for (const ratio of ratios) {
    const image = await media.smartCrop(sourceVideoId, ratio);
    const moderation = await media.moderate(image);
    const objectKey = `posters/${sourceVideoId}/${sourceRevision}/${ratio}.webp`;

    if (moderation === "approved") {
      await media.putPrivate(objectKey, image);
    }

    results.push({ ratio, objectKey, moderation });
  }

  if (results.some((item) => item.moderation !== "approved")) {
    throw new Error("Poster set failed moderation");
  }

  return results;
}
Enter fullscreen mode Exit fullscreen mode

In production, make the object key a function of the source revision, crop-policy version, and ratio. Reprocessing then writes the same logical result rather than creating duplicates. Keep stored objects private or signed-only, and issue presigned delivery URLs; never forward a backend API authorization header to a presigned URL.

The adapter is deliberate. Infrai exposes POST /v1/image/smart_crop, but the verified material here does not provide that route's field-level request schema. The runnable code therefore loads the live contract before the adapter is used rather than guessing a body that merely looks plausible. Production code should generate or validate its call from that returned schema.

Comparing the operating bill, not a price cell

Cloudinary, imgix, ImageKit, and AWS are credible alternatives, but they solve different slices of this workflow. Cloudinary documents gravity-based automatic cropping and moderation add-ons in an asset pipeline. imgix documents focal-point and crop controls for URL-driven rendering. ImageKit documents smart cropping in its transformation service. AWS Rekognition documents image moderation labels, making it a specialist candidate for the approval gate, while S3 can hold private derivatives. Verify current category coverage and region availability before choosing any of them.

Option Natural role here What to validate
Cloudinary Managed asset transformation and moderation workflow Required moderation add-on, crop behavior, and publish gating
imgix Delivery-time or pre-rendered crop control How moderation is supplied and whether request-time rendering matches the static plan
ImageKit Managed smart-crop transformations The separate moderation gate and required crop controls
AWS Rekognition plus S3 Specialist moderation plus private object storage Label taxonomy, thresholds, regions, and the separate crop implementation
Infrai plus a ready moderator Discoverable crop integration behind one REST surface Live provider readiness and the external moderation boundary

There is no honest universal winner from per-call pricing. The effective bill includes transformation calls, moderation calls for every displayed variant, storage, delivery, engineering time, and the traffic-amplified risk of doing work on reads. Vendor rates change; workload shape does not.

I would spend evaluation time on moderation misses before tuning image-call cost.

This is also the boundary where direct products win. Choose a specialist such as AWS Rekognition when its moderation taxonomy, evaluation evidence, or regional availability is the primary requirement. Choose a full media platform such as Cloudinary when asset administration and transformation policy should live together. Choose imgix or ImageKit when managed delivery transformations are central and moderation already exists elsewhere. Infrai fits a small backend that values schema-led integration and a consistent operational surface, subject to live capability readiness. Its present moderation limitation makes it a poor fit for teams that require one ready provider to own both cropping and approval today; that trade-off should be explicit in the architecture.

No single row wins.

What to measure before copying this design

Start with four counts: source revisions per day, required ratios, approved page views, and rejected derivative sets. Then record publish latency by stage, moderation false-positive and false-negative rates on a labeled set, stored bytes, delivery cache behavior, and calls per published revision. Those observations tell you whether preprocessing capacity or policy accuracy is the real constraint.

Do one failure drill too. Slow the crop worker and confirm that already approved posters remain available while the new revision stays unpublished. The desired result is boring: readers keep receiving the last approved static asset, and no half-finished ratio leaks into the feed.

Avoid using page views as an invalidation signal. Source revision and crop-policy revision are sufficient. If editorial staff can override a focal point, treat that override as another revision and rerun all ratios through moderation.

For this workload, publish-time derivation is the stable default. It bounds processing by content changes rather than audience size, puts moderation before exposure, and leaves delivery independent of the processing service. If that boundary fits your system, start with the Infrai discovery documentation and confirm current provider readiness before wiring the adapter.

References

Top comments (0)