DEV Community

Cover image for Building an honest 1080p-first MP4 conversion flow
EthanCole
EthanCole

Posted on

Building an honest 1080p-first MP4 conversion flow

A quality selector looks like a simple input until the selected value depends on a third-party pipeline.

If a UI says "1080p," users naturally read that as an output guarantee. But when the source and provider decide what is actually available, that label creates a contract the system may not be able to keep.

While working on a companion YouTube-to-MP4 flow, I found a more honest model: treat 1080p as the first attempt, keep the delivered resolution explicit, and make fallback part of the state machine rather than an invisible exception.

Separate Requested Quality From Delivered Quality

The workflow tries 1080p first, then can fall back to 720p, 480p, or 360p. The important implementation lesson is that "requested" and "delivered" are different fields.

Conceptually, the provider loop looks like this:

const candidates = ["1080p", "720p", "480p", "360p"];

for (const resolution of candidates) {
  const result = await requestProviderResult({ resolution });

  if (result.available) {
    return {
      requestedResolution: "1080p",
      deliveredResolution: resolution,
      result,
    };
  }
}

return { state: "failed", reason: "no_available_result" };
Enter fullscreen mode Exit fullscreen mode

That is conceptual pseudocode, not a claim about the exact production implementation. Its purpose is to make the contract visible: a successful fallback is still a success, but it is not a 1080p success.

The UI should preserve that distinction. Showing only "complete" hides information the user needs to judge the result.

Duration Validation Belongs To The Route

Quality selection also changes validation.

In this workflow, the 1080p route is limited to 90 minutes, while lower-resolution routes use a 120-minute limit. That means duration is not one global constant checked before every request. It belongs to the selected route.

A useful validation result should therefore explain both the limit and the next valid option. For example, a 100-minute source does not fit the 1080p route, but it may fit a lower-resolution route. The interface should state that before starting a long-running provider job.

This is better than a vague "video too long" error because it leaves the user with an actionable decision.

Model Progress As Product State

Provider-backed conversion is asynchronous and can become temporarily unavailable. A two-state model—idle or downloaded—is too small.

The user-facing state machine needs at least these stages:

  1. Input accepted and normalized.
  2. Conversion job started.
  3. Provider progress available.
  4. MP4 result returned with its actual resolution.
  5. Result previewed where supported.
  6. Temporary result link opened or downloaded.
  7. Failure surfaced with a retryable or terminal reason.

Progress is not decorative. It tells the user whether waiting is still rational. The actual delivered resolution is not metadata for analytics only; it is part of the result.

Treat Preview As A Postcondition

A provider returning a media URL does not prove that the file fits the user's task.

Preview provides a postcondition the user can evaluate: does it play, is the picture and audio usable, and is the delivered resolution acceptable? That turns download from an automatic final state into a deliberate handoff.

It also keeps the product contract narrow. The converter can prepare and expose a result. The user still decides whether the result is useful.

Temporary Delivery Is Not Storage

The returned media link belongs to a third-party delivery path. It should be modeled as temporary handoff data, not as a permanent asset URL.

That affects copy and implementation:

  • do not promise permanent availability;
  • do not treat the result URL as a user library;
  • make provider failures and retries explicit;
  • let the user save a permitted result after preview instead of implying the service hosts it indefinitely.

The same boundary applies to source coverage. Accepting standard YouTube URLs, short links, Shorts links, and raw video IDs reduces input friction, but it does not mean every video or provider request will succeed.

The Contract I Would Keep

The most useful version of this workflow says exactly what it can control:

  • it can attempt 1080p before lower resolutions;
  • it can report the resolution actually delivered;
  • it can enforce route-specific duration limits;
  • it can expose progress, preview, and a temporary result handoff;
  • it cannot guarantee provider availability, universal URL support, or 1080p for every source.

There is also a non-technical boundary worth keeping in the main flow: only process video you own or have permission to download. The project is not affiliated with YouTube.

The live product surface that prompted this design note is available as a concrete reference:

https://youtubetowav.io/youtube-to-mp4-converter

Disclosure: This article was created with AI assistance. The workflow facts and limits were checked against the current product topic and implementation evidence before registration.

Top comments (0)