How to merge two videos of different resolutions

Merge two videos of different resolutions by scaling both into one frame: crop, pad, blur, or stretch each clip, then join them with their sound.

5 min readSume
All posts

To merge two videos of different resolutions, pick one frame size for the result, scale both clips to it, and join them end to end. When their shapes differ too, each clip is cropped to fill the frame, padded with bars, or stretched to fit. With Sume, one Timeline 1.0 render scales and joins them: set the output size, give each clip a fit, and pass each clip's detached sound as audio.parts[].

The facts come from the Timeline 1.0 and Audio detach docs and the field descriptions in the Sume API reference, read on 2026-09-27. Anything described as current behavior is read from Sume's code.

How do I merge two clips of different sizes with Sume?

Both clips must already be your workspace's media.sume.com files, such as the outputs of earlier Sume jobs; which URLs each endpoint accepts explains the rule. Then make two kinds of call:

  • Detach each clip's sound with POST /v1/audio-detach. In the current compiler, a render's sound comes only from its audio spine and an optional soundtrack, never from the clips, so this is how each clip keeps its own sound. The default wav is the file a Timeline spine wants, and the result reports its duration_seconds.
  • Render once with POST /v1/timeline-1.0/render: one video[] slot per clip, back to back, and the detached files as audio.parts[] in the same order, joined without gaps. audio.duration_seconds is the output length, so set it to the total. video[0].start must be 0, and each later start is the running total.
curl -X POST https://api.sume.com/v1/timeline-1.0/render \
  -H "Authorization: Bearer $SUME_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: merge-two-clips-001" \
  -d '{
    "output": { "width": 1920, "height": 1080 },
    "audio": {
      "duration_seconds": 50,
      "parts": [
        { "url": "https://media.sume.com/artifacts/artf_demo/landscape.wav", "duration": 30 },
        { "url": "https://media.sume.com/artifacts/artf_demo/portrait.wav", "duration": 20 }
      ]
    },
    "video": [
      { "source_url": "https://media.sume.com/artifacts/artf_demo/landscape.mp4", "start": 0, "duration": 30 },
      { "source_url": "https://media.sume.com/artifacts/artf_demo/portrait.mp4", "start": 30, "duration": 20, "fit": "blur" }
    ]
  }'

Which fit should each clip use?

fit decides what happens when a clip's shape differs from the output frame, and it defaults to cover. In the example, the landscape clip keeps the default, and the portrait clip is padded with a blurred copy of itself instead of losing its top and bottom. A clip smaller than the frame is scaled up, which adds pixels but no detail, so set the output size to the larger clip or to where the video is going.

From Timeline 1.0, the Sume API reference, and Sume's current compiler code, read 2026-09-27.
`fit`What happens to a clip of another shape
cover (default)Scaled until it fills the frame; what overflows is cropped. A portrait clip in a landscape frame loses its top and bottom.
containScaled until it fits inside the frame; the rest is padded with black bars.
blurPadded with a blurred copy of the frame instead of black bars.
stretchScaled to the exact frame size, so its proportions distort.

What happens when the frame rates differ too?

A render has one frame rate. Leave output.fps out and it uses the rate the sources already run at, with the longest video sources deciding, and 30 only when nothing has a rate. A clip at another rate is met by repeating or dropping a frame every few frames, which shows as judder on motion, and the result warns output_fps_resamples_sources with the rate the sources wanted.

To choose the rate yourself, set output.fps to 24, 25, 30, or 60. A clip that doesn't run at that rate is resampled the same way. Change a video's frame rate or resolution covers how the rate is picked in detail.

What are the limits, and what does a merge cost?

  • A render takes 1 to 200 video[] slots and outputs 1 to 1,800 seconds. output.width and output.height are even integers from 256 to 2160; omit them and you get a 1080×1920 portrait frame.
  • audio.parts[] holds up to 20 slices, and declared part lengths that add up to less than audio.duration_seconds are refused with audio_parts_shorter_than_duration. In current code the parts must also share one channel layout, or the render fails with audio_parts_channel_mismatch; if one clip is mono, detach both with channels: "mono".
  • Detach reads sources up to 1,800 seconds, writes at most 900, and fails with detach_source_has_no_audio on a clip that has no audio track. If neither clip has sound, send audio.mode: "silence" instead of parts.
  • The render is listed at $0.10 per output minute on API pricing, reserved as ceil(audio.duration_seconds / 60) minutes, and each detach is a flat per-job rate, each plus a 5.5% agent fee by default; the docs say to confirm both rates in GET /v1/catalog. A plan preflight with POST /v1/timeline-1.0/plan checks the document without billing.

Sources

Related posts

More in Media tools

All Media tools posts

Written by Sume