Video Generation Capability Checks — Before Offering Express Users Unsupported Options

Video Generation Capability Checks — Before Offering Express Users Unsupported Options

视频生成能力检查——在向 Express 用户提供不支持的选项之前

Use upload-time background removal only when every accepted source can be decoded, the transformation can finish outside the request path, and the original is retained. Otherwise, store the original and generate a derivative on demand behind a capability check. That decision rule applies equally to promo video generation: an Express or Node.js application should check the source asset and requested output contract before offering options to users. It keeps a logistics catalog honest while a temporary processor failure remains separate from the source of record. 仅当所有被接受的源文件都能被解码、转换过程可以在请求路径之外完成,且原始文件被保留时,才使用上传时的背景移除功能。否则,应存储原始文件,并在能力检查之后按需生成衍生文件。该决策规则同样适用于宣传视频生成:Express 或 Node.js 应用程序在向用户提供选项之前,应检查源资产和请求的输出契约。这既能保证物流目录的准确性,又能将临时的处理器故障与原始记录分离开来。

Short answer: capability is a property of the asset, operation, and output contract together. Do not expose a generic remove background switch because a service happens to be configured. Inspect the upload, record normalized metadata, probe the selected processor with that metadata, and return an option only when the full contract is satisfiable. 简而言之:能力是资产、操作和输出契约共同的属性。不要仅仅因为某个服务已配置就暴露一个通用的“移除背景”开关。应检查上传内容,记录标准化的元数据,用这些元数据探测选定的处理器,并且仅在完整契约可满足时才返回选项。

How should Node.js check video generation capabilities before offering options? The concrete job is mundane but unforgiving. A logistics operator uploads product photos for a catalog, and the system produces transparent-background derivatives for listing pages, labels, or marketplace feeds before those assets enter a promo video workflow. The architectural choice is when that work runs: immediately after upload, or only when a consumer asks for the derivative. Node.js 应如何在提供选项前检查视频生成能力?这项具体工作虽然平凡但要求严苛。物流操作员上传产品照片到目录,系统在这些资产进入宣传视频工作流之前,为列表页面、标签或市场信息流生成透明背景的衍生文件。架构上的选择在于何时执行该工作:是上传后立即执行,还是仅在消费者请求衍生文件时执行。

Although the HTTP layer may be Express on Node.js, capability discovery does not belong in a framework-specific conditional. Put it behind a narrow domain interface so the route can ask one question and render the answer without knowing decoder or processor details. The invariant is that the original object remains immutable. A background-removal result is a derivative with its own content type, dimensions, processor revision, and lifecycle. Replacing the original throws away evidence needed for reprocessing and makes a bad mask much harder to unwind. I would reject that design in the ADR even if it made the first implementation shorter: the lost rollback path is a bad exchange for a few fewer storage keys. 尽管 HTTP 层可能是基于 Node.js 的 Express,但能力发现不应放在特定于框架的条件判断中。应将其置于一个狭窄的领域接口之后,这样路由只需询问一个问题并渲染答案,而无需了解解码器或处理器的细节。不变原则是原始对象必须保持不可变。背景移除的结果是一个拥有独立内容类型、尺寸、处理器版本和生命周期的衍生文件。替换原始文件会丢弃重新处理所需的证据,并使错误的遮罩更难撤销。即使这能缩短首次实现的时间,我也会在架构决策记录(ADR)中拒绝这种设计:丢失回滚路径是以牺牲少量存储键为代价的糟糕交换。

Three more invariants matter. First, advertised options must come from a capability decision made for the specific asset, not from a static feature flag. Second, the output contract must name a format that can represent the required result; transparency is not an abstract promise. MDN’s image format guide documents that JPEG does not support alpha transparency, while PNG and WebP do. Third, retries must not create conflicting derivatives. A stable job key derived from the source identity and transformation specification gives the worker an idempotency boundary. The failure boundary should also be explicit. Upload acceptance ends after the original is durably stored and its basic metadata is recorded. Transformation failure belongs to the derivative job. This separation matters in the same way an OTP send differs from account creation: accepting the primary action and completing a downstream delivery are related events, but pretending they are one transaction creates awkward retries and misleading user states. 还有三个不变原则很重要。第一,广告宣传的选项必须来自针对特定资产的能力决策,而不是来自静态的功能标志。第二,输出契约必须指定一种能够表示所需结果的格式;透明度不是一个抽象的承诺。MDN 的图像格式指南记录了 JPEG 不支持 Alpha 透明度,而 PNG 和 WebP 支持。第三,重试不得创建冲突的衍生文件。从源标识和转换规范派生的稳定作业键为工作进程提供了幂等性边界。故障边界也应明确。上传接受在原始文件被持久化存储且其基本元数据被记录后即告结束。转换失败属于衍生作业。这种分离的重要性与 OTP 发送和账户创建的区别类似:接受主要操作和完成下游交付是相关事件,但假装它们是同一个事务会产生尴尬的重试和误导性的用户状态。

Invariants and failure boundaries / 不变原则与故障边界

Treat file extension, declared MIME type, and decoded content as three different signals. An object named crate.jpg can arrive with an incorrect Content-Type; trusting either string before decoding lets unsupported or malformed data reach expensive processing. The decoder result should supply width, height, frame count where applicable, and the actual media type. Limits on byte size, pixel count, and processing time belong before the transformation queue. Stop there. Metadata is evidence, not permission. A useful capability record is deliberately small: source media type, dimensions, alpha presence, operation name, requested output type, and the processor contract revision used for the decision. Avoid copying arbitrary embedded metadata into logs. Product photos can contain camera and location fields that have no operational value, and retaining them expands the compliance surface without improving the mask. 将文件扩展名、声明的 MIME 类型和解码后的内容视为三个不同的信号。一个名为 crate.jpg 的对象可能带有错误的 Content-Type;在解码前信任这两个字符串中的任何一个,都会让不支持或格式错误的数据进入昂贵的处理流程。解码器结果应提供宽度、高度、适用时的帧数以及实际的媒体类型。字节大小、像素数和处理时间的限制应在转换队列之前进行。到此为止。元数据是证据,而非许可。一个有用的能力记录应刻意保持精简:源媒体类型、尺寸、Alpha 通道存在情况、操作名称、请求的输出类型以及用于决策的处理器契约版本。避免将任意嵌入的元数据复制到日志中。产品照片可能包含没有操作价值的相机和位置字段,保留它们只会扩大合规风险,而不会改善遮罩效果。

There are two independent rejection classes. A permanent rejection means the asset cannot satisfy the contract, such as requesting transparent JPEG output. A transient rejection means the operation is valid but capacity or a dependency is temporarily unavailable. The UI may hide a permanently impossible choice, but it should represent transient unavailability as retryable rather than quietly changing the requested format. Spam-filter work teaches the same lesson: policy rejection and delivery delay demand different recovery paths. That distinction matters. 存在两类独立的拒绝情况。永久拒绝意味着资产无法满足契约,例如请求透明的 JPEG 输出。瞬时拒绝意味着操作本身有效,但容量或依赖项暂时不可用。UI 可以隐藏永久不可能的选择,但应将瞬时不可用表示为可重试,而不是悄悄更改请求的格式。垃圾邮件过滤工作也教导了同样的道理:策略拒绝和交付延迟需要不同的恢复路径。这种区别至关重要。

Decision point / 决策点

Process after upload / 上传后处理Process on demand / 按需处理
First derivative latency / 首个衍生文件延迟Paid before a consumer asks / 在消费者请求前支付Paid on the first request / 在首次请求时支付
Work for unused assets / 未使用资产的工作量Always incurred / 总是产生Avoided / 避免
Upload request / 上传请求Keep asynchronous; return after original storage / 保持异步;在原始存储后返回Unchanged by transformation / 不受转换影响
Failure visibility / 故障可见性Job state is available before consumption / 在消费前即可获取作业状态Consumer encounters pending or failed state / 消费者遇到挂起或失败状态
Cache strategy / 缓存策略Derivative can be pre-populated / 衍生文件可预填充Derivative must use a stable cache key / 衍生文件必须使用稳定的缓存键
Best fit / 最佳适用场景Most accepted photos need the same derivative / 大多数接受的照片需要相同的衍生文件Demand is sparse or output contracts vary / 需求稀疏或输出契约多变

Neither column wins universally. My first instinct for a catalog is upload-time generation because it makes downstream video assembly pleasantly boring. The correction comes from looking at demand, not taste: if only a small subset of shipment photos becomes promotional material, eager processing manufactures unused derivatives. In a feed where nearly every SKU needs one transparent PNG, an asynchronous upload-time job buys predictable readiness. For archival shipment photos that are rarely published, on-demand work avoids creating derivatives nobody reads. The traffic shape resolves the choice; the mere presence of a processing API does not. This is an explicit trade-off between readiness and wasted work, not a universal rule. Put capability discovery before option presentation. 没有哪一列是普遍适用的。对于目录,我的第一直觉是上传时生成,因为它使下游的视频组装变得非常简单。修正这一想法需要观察需求而非个人偏好:如果只有一小部分发货照片成为宣传材料,那么急切处理只会制造出未使用的衍生文件。在几乎每个 SKU 都需要一个透明 PNG 的信息流中,异步的上传时作业能带来可预测的就绪状态。对于很少发布的存档发货照片,按需工作避免了创建无人阅读的衍生文件。流量形态决定了选择;仅仅存在处理 API 并不意味着必须使用它。这是就绪性与浪费工作量之间的明确权衡,而非普遍规则。请将能力发现置于选项展示之前。