03:00:0050% OFFClaim

Hands-on recipe

Deliver a landscape clip on a vertical letterbox canvas

Make a vertical review file while preserving the complete landscape composition. The fixture chooses a 160×90 content rectangle with 10-pixel side margins and 115-pixel top/bottom margins.

Includes executed local fixtures, scripts and receipts. These checks do not represent a video-generation service run.

Original task-specific local-fixture diagram
Original edge-marker video, actual vertical MP4 and a custom canvas diagram. The media was locally synthesized and transcoded, not model-generated.

01Prepare environment and inputs

  1. Prepare Node.js and FFmpeg with libx264, scale and pad available; set FFMPEG_BIN when necessary. The recorded environment was Node v24.18.0 and FFmpeg 6.0.
  2. Use the supplied original one-second landscape-source.mp4. It has ten frames, a red left edge and a yellow right edge, and intentionally contains no audio.
  3. Keep the chosen delivery geometry explicit: source 320×180, scaled content 160×90, output 180×320, placement x=10 and y=115. The example uses yuv444p for its small lossless comparison.

02Run the recipe

Run command

node run-recipe.mjs --out ./my-run
  1. Establish composition markers

    The script makes the landscape fixture with visible markers on both source edges. Those markers are acceptance targets: losing either edge during conversion would remove source composition, even if the result still has a valid portrait dimension.

  2. Scale proportionally and add a canvas

    Apply scale=160:90:flags=neighbor,pad=180:320:10:115:color=black,setsar=1. The 160×90 rectangle preserves 16:9 exactly; the outer canvas is 9:16. Its small side margins deliberately avoid rounding the landscape content to a distorted 180-pixel width.

  3. Decode and compare the content rectangle

    Fully decode the exported file into RGB. Compare its 160×90 interior against an independently scaled source frame, using a maximum channel difference tolerance of four. The recorded fixture measured zero. This tolerance and yuv444p fixture are not a general colour-management qualification.

  4. Audit borders and frame count

    Check ten output frames, black top and bottom padding, a red left marker and a yellow right marker. The negative case is a local arithmetic aspect-ratio guard: the deliberately unequal cross-products reject stretching. It does not encode a stretched bad file or exercise a general product validator. Keep the measured offsets and actual max RGB difference in the receipt.

03Check the result

  • The actual output fully decodes to ten 180×320 RGB frames.
  • The outer canvas is 9:16 and the inner 160×90 rectangle remains 16:9.
  • The decoded interior differs by at most four channel values from the separately scaled source; the recorded run measured zero.
  • Top and bottom sampled padding pixels are black within three channel values.
  • The red left and yellow right composition markers remain inside the delivered picture.
  • The local arithmetic guard rejects unequal aspect-ratio cross-products; it is not a test of a stretched FFmpeg output. All eight checks pass.

04Troubleshoot and deliver

The subject fills the portrait frame and both edges disappear.

Change the layout to the documented pad operation and rerun the two edge checks. Cropping is a different delivery decision.

The image looks slightly squeezed.

Change only the content dimensions back to 160×90 before padding; verify the exact 16:9 ratio by cross-multiplication.

Pixel comparison differs after export.

Compare the tool version and pixel format first. Rerun the supplied yuv444p fixture before changing the tolerance for a separate delivery codec.

The measured file proves this layout conversion on the original tiny fixture. Confirm a distribution platform’s codec and resolution requirements separately before using the same geometry for a final upload.

05Download scripts and fixtures