Author: Media Engineering

  • CDN cache keys for transformed media

    CDN cache keys for transformed media

    Cache the right derivative without multiplying variants endlessly.

    Define identity first

    A cache key for transformed media needs the source version and every option that changes bytes: dimensions, crop, format, quality, and sometimes content negotiation. Normalize option order and defaults. Two equivalent requests should hit one cache entry; different outputs must never collide.

    Bound the variant space

    Arbitrary widths and quality values let a single asset produce thousands of expensive misses. Use named presets or round widths to a short approved list. Monitor unique variants per source and the ratio of cache hits to transformation requests.

    Make invalidation explicit

    Immutable versioned URLs are simpler than purging every edge when source bytes or recipes change. If mutable URLs are necessary, document purge timing and stale behavior. Test a replacement end to end on a plain URL after caches have been populated.

    A concrete acceptance test

    Warm a transform in the CDN, request equivalent options in a different order, then publish a new source version. Verify a shared hit for the equivalent URL and fresh bytes for the new version. Run this test with a realistic asset and record the observed state, output URL, and failure reason.

    Implementation check

    • Include every byte-changing option in the cache key.
    • Limit allowed dimensions and quality values.
    • Use source versions to avoid ambiguous purges.

    Related guides

    Primary reference: Official documentation.

    Related field note

    Continue with A migration plan for CDN cache keys.

  • Audio waveform previews without storing giant JSON files

    Audio waveform previews without storing giant JSON files

    Create small, useful amplitude data for audio timelines.

    Decide what the UI needs

    A waveform is a visual summary, not a second audio file. For a timeline, calculate peak or RMS amplitude over fixed time windows and store a compact array or rendered image. Choose the number of samples from the largest expected display width, not the number of source audio samples.

    Generate once per version

    Decode the audio in a background job and associate the output with the exact source version. For stereo, decide whether to show separate channels or a combined magnitude. Normalize carefully: per-file normalization makes quiet files visible but can hide relative loudness differences between files.

    Test seek alignment

    The waveform’s duration and sample count must map to the player’s time axis, including leading silence or trimmed segments. Verify a click at the midpoint seeks to roughly the midpoint. A beautiful waveform that drifts from playback is worse than a plain progress bar.

    A concrete acceptance test

    Use an audio file with leading silence and a loud event near the midpoint. Compare the waveform to playback and test a click at several points along the timeline. Run this test with a realistic asset and record the observed state, output URL, and failure reason.

    Implementation check

    • Set waveform resolution from display width.
    • Keep sample timestamps aligned with playback.
    • Test files with silence and channel imbalance.

    Related guides

    Primary reference: Official documentation.

    Related field note

    Continue with Cost-aware transformations without duplicate files.

  • Choosing a useful video poster frame

    Choosing a useful video poster frame

    Generate a poster that tells viewers what the clip contains.

    Choose meaning, not just a timestamp

    The first frame may be black, a fade, or a title card with no context. Sample candidate frames after probing duration, then reject frames that are blank, blurred, or misleading. For product demos, an editor-selected still is often better than any automatic sample.

    Generate for the actual slot

    Create a poster at the player’s display ratio and an appropriate pixel density. Keep the original frame or source time in metadata so the image can be regenerated. A poster is part of the video asset’s delivery state, not an unrelated decorative upload.

    Check loading behavior

    A poster can be the page’s largest image, so give it the same sizing and priority attention as a hero image. Test the transition from poster to playback and confirm controls remain clear over light and dark frames.

    A concrete acceptance test

    Generate poster candidates for a clip with a black opening frame and a fade. Check the chosen image at mobile size and verify that playback replaces it cleanly. Run this test with a realistic asset and record the observed state, output URL, and failure reason.

    Implementation check

    • Reject blank or misleading candidate frames.
    • Generate at the player slot ratio.
    • Check poster loading priority on the actual page.

    Related guides

    Primary reference: Official documentation.

  • Build a reliable queue for video transcoding

    Build a reliable queue for video transcoding

    Turn expensive video jobs into an observable, retryable pipeline.

    Create a job from an immutable source

    Video conversion can outlast an HTTP request, so create a processing job after upload validation. Include source asset ID, recipe version, desired outputs, and an idempotency key. Workers should write to temporary keys and publish finished outputs only after probing them.

    Control concurrency

    Transcodes consume CPU, memory, disk, and network. Limit worker concurrency by workload, not simply by queue depth. Large 4K inputs may need a different pool from short clips. Record input duration, output size, processing time, and failure reason so capacity decisions use evidence.

    Retry only what can recover

    A transient storage failure may justify a retry; a corrupt input or unsupported codec needs a terminal state and a user-facing explanation. Clean up partial outputs and keep the original available for later reprocessing. Test worker crashes at each stage to ensure duplicate jobs do not publish mixed renditions.

    A concrete acceptance test

    Kill a transcoding worker after it writes one temporary rendition. Restart the job and verify that only complete, probed outputs become visible and no mixed recipe versions appear. Run this test with a realistic asset and record the observed state, output URL, and failure reason.

    Implementation check

    • Use a source-and-recipe idempotency key.
    • Probe output files before publishing URLs.
    • Classify corrupt inputs separately from transient failures.

    Related guides

    Primary reference: Official documentation.

    Related field note

    Continue with How metadata changes queue backpressure.

  • Image metadata: what to preserve and what to strip

    Image metadata: what to preserve and what to strip

    Handle orientation, color, copyright, and location data deliberately.

    Read metadata before transforming

    Orientation and embedded color profiles affect how an image appears. Normalize orientation before sizing or cropping, and test color conversion against representative assets. Dimensions measured before orientation correction can lead to the wrong derivative shape.

    Keep private fields private

    Camera metadata may include location, device, and capture details that a user did not intend to publish. Define a publication policy: retain only fields needed for display or rights management, and strip the rest from public derivatives. The original may need a different retention rule under the product’s own privacy policy.

    Make the policy testable

    Use sample files with orientation, ICC profiles, GPS coordinates, and transparency. Verify both the rendered pixels and metadata of the downloaded derivative. A successful encoder exit code is not proof that color or privacy handling was correct.

    A concrete acceptance test

    Upload samples with rotated orientation, an ICC profile, and GPS data. Download the public derivatives and verify their pixels, color, dimensions, and removed private metadata. Run this test with a realistic asset and record the observed state, output URL, and failure reason.

    Implementation check

    • Normalize orientation before measuring or cropping.
    • Inspect public derivatives for location metadata.
    • Test color profiles against visible reference images.

    Related guides

    Primary reference: Official documentation.

  • Designing an image transformation API

    Designing an image transformation API

    Make resize and format URLs predictable, safe, and cacheable.

    Constrain the recipe

    A transformation URL should identify an immutable source plus a small allowed set of operations: width, height, fit, quality, and format. Normalize equivalent requests to one canonical recipe. Cap output dimensions and pixel count before starting a decoder so one request cannot consume excessive memory.

    Version intentional changes

    When crop behavior, sharpening, or encoder settings change, include a recipe version in the derivative identity. Otherwise a cached URL can mean different bytes before and after deployment. Record transformation errors separately from missing source assets.

    Protect the origin

    If anyone can request any width for any source, a crawler can create thousands of variants. Use named presets for common UI slots, sign private transformations, and rate-limit expensive misses. Warm only genuinely important variants; on-demand generation is useful when the variant space is bounded.

    A concrete acceptance test

    Request the same transform with reordered parameters, then request a disallowed extreme width. The first two URLs should map to one output; the extreme request should fail before expensive decoding. Run this test with a realistic asset and record the observed state, output URL, and failure reason.

    Implementation check

    • Canonicalize equivalent transformation recipes.
    • Reject excessive dimensions before decoding.
    • Version the recipe when output bytes change.

    Related guides

    Primary reference: Official documentation.

  • Responsive images: get srcset and sizes working together

    Responsive images: get srcset and sizes working together

    Give browsers the right candidates and a truthful display size.

    Describe the actual slot

    A width-descriptor srcset lists candidate image widths; sizes tells the browser how wide the image will render at each breakpoint. If sizes claims a full viewport while CSS shows a half-width card, the browser can choose an unnecessarily large file. Write sizes from the layout, not from the source dimensions.

    Separate crop from resolution

    Use srcset for the same composition at several resolutions. Use picture with media conditions when mobile needs a different crop or framing. Keep a fallback img with intrinsic width and height so layout space is reserved before the image loads.

    Inspect the browser’s choice

    Test a real mobile viewport and a high-density desktop display. Look at currentSrc in DevTools and compare the delivered pixels to the rendered slot. A candidate set is useful only if the transformation service produces those widths and the CDN caches them predictably.

    A concrete acceptance test

    Render the same card at narrow and wide widths, then inspect currentSrc and transferred bytes. The chosen resource should have enough pixels for the slot without sending a desktop hero to mobile. Run this test with a realistic asset and record the observed state, output URL, and failure reason.

    Implementation check

    • Match sizes to the actual CSS slot width.
    • Use picture when the crop changes across layouts.
    • Inspect currentSrc on mobile and high-density screens.

    Related guides

    Primary reference: Official documentation.

  • Design object storage keys for a growing media library

    Design object storage keys for a growing media library

    A naming scheme that supports ownership, versions, cleanup, and migration.

    Use opaque identities

    An object key is an address, not a database record or a trustworthy filename. Use an asset ID and a stable prefix such as originals/{asset-id}/source. Keep the user’s filename, title, and owner in application metadata. This avoids collisions and makes renaming an asset independent of moving bytes.

    Separate source from derivatives

    Put generated files under a versioned recipe prefix, for example derivatives/{asset-id}/{recipe-version}/. A new crop rule or encoder can then coexist with the old output during rollout. Record each derivative’s key, dimensions, format, and status so the application never guesses what exists.

    Plan deletion as a workflow

    Removing an asset requires more than deleting one URL. Mark it unavailable, revoke public references, enqueue deletion of source and derivative keys, and confirm completion. Inventory and lifecycle rules help find abandoned uploads, but do not replace an application-level deletion record.

    A concrete acceptance test

    Rename an asset, regenerate one derivative, and delete the asset. Confirm that the opaque source key remains stable through renaming and that deletion removes every recorded derivative. Run this test with a realistic asset and record the observed state, output URL, and failure reason.

    Implementation check

    • Use an opaque asset ID instead of the original filename.
    • Version derivative prefixes separately from source keys.
    • Track every key that deletion must remove.

    Related guides

    Primary reference: Official documentation.

  • A secure validation path for image and video uploads

    A secure validation path for image and video uploads

    Validate uploads in stages before turning untrusted bytes into public assets.

    Check more than an extension

    An extension and browser-supplied Content-Type are hints, not proof. Restrict allowed formats, limit byte size, inspect the file signature, and decode or probe the content with maintained libraries. Apply authorization and quota checks before accepting the upload. Store the original outside a directly executable web path.

    Quarantine before publication

    A useful state sequence is pending, uploaded, validating, processing, ready, and rejected. Keep an untrusted upload private until validation and any required scanning complete. Re-encode images or transcode video into formats you serve rather than passing arbitrary uploaded bytes through to visitors.

    Keep failure messages useful

    Return a clear reason such as unsupported format, corrupt file, or size limit, without leaking internal storage paths. Log the asset ID and validation stage for operators. An upload that passes type checks may still fail dimension, duration, or decoder limits; model those as expected product outcomes.

    A concrete acceptance test

    Rename a text file to .jpg, spoof its MIME header, and send a corrupt image with a valid signature. Each should receive a distinct, safe rejection before becoming publicly readable. Run this test with a realistic asset and record the observed state, output URL, and failure reason.

    Implementation check

    • Inspect actual bytes and decode the claimed format.
    • Keep untrusted files private until checks finish.
    • Give users a safe rejection reason for expected failures.

    Related guides

    Primary reference: Official documentation.

  • A developer’s guide to media pipelines

    A developer’s guide to media pipelines

    A practical map from browser upload to reliable image and video delivery.

    Map the lifecycle

    A media pipeline starts before the file reaches storage. The client needs a safe way to send bytes, the server needs an identity for the asset, workers need repeatable jobs, and delivery needs URLs with predictable behavior. Treat the original as an immutable input. Derivatives are outputs that can be recreated when requirements change.

    Choose boundaries that survive change

    Separate upload authorization, object storage, processing, metadata, and delivery. A product that only accepts small profile photos may process synchronously. Large video uploads, multiple renditions, or moderation usually justify a queue and an explicit processing state. Store the asset ID, owner, source key, checksum, status, dimensions, and derivative references in a database; keep binary bytes in object storage.

    Design for retries

    Give every processing job an idempotency key tied to the asset and recipe version. A retry should find the existing output or safely replace it. Publish an asset only after required derivatives exist, then make the delivery URL visible to the application. Keep failure states observable so a missing thumbnail does not silently become a broken page.

    A concrete acceptance test

    Upload a source image, force one worker failure, and confirm that a retry produces one ready asset with no duplicate derivative. Then change the recipe version and verify that the original remains unchanged. Run this test with a realistic asset and record the observed state, output URL, and failure reason.

    Implementation check

    • Keep the source immutable and give each derivative a recipe version.
    • Move the asset to ready only after required outputs pass validation.
    • Correlate upload, processing, and delivery logs with one asset ID.

    Related guides

    Primary reference: Official documentation.

    Related field note

    Continue with Designing queue backpressure for human and agent operators.