video.convert

Re-encode a video into another container at a chosen quality. Pick the container and the codecs come with it — there is no codec field to get wrong.

Config

FieldTypeDefaultNotes
formatmp4 · webm · mov · mkvmp4Output container. Narrower than what can be read — .avi, .mpg, .3gp and friends all decode fine as inputs.
qualitynumber 1–10075Higher is better. Mapped to the codec’s CRF at encode time. Out-of-range values are clamped.

Codecs come from the container

  • mp4 · mov · mkv — H.264 video, AAC audio. The reach-for pairing: every browser, phone, and editor plays it.
  • webm— VP9 video, Opus audio. Smaller at the same quality, and slower to encode. Safari's WebM support is patchy, so reach for mp4 when a browser has to play it.

Quality maps onto each codec's own scale — 1–100 becomes CRF 34–18 for H.264 and CRF 44–24 for VP9. Audio rides along re-encoded at 128 kbps.

mp4 and mov outputs are written with their index at the front (faststart), so a player can start on a partial download instead of waiting for the whole file. That is what makes a signed result URL playable straight from the browser.

In a pipeline

{
  id: 'convert',
  type: 'video.convert',
  config: {
    format: { value: 'webm' },
    quality: { value: 70 },
  },
}

With runQueue

tk.runQueue(files, 'video')
  .maxSize(1280)                                 // shrink first — the encode is the slow part
  .convert({ format: 'mp4', quality: 75 })
  .options({ poll: { timeoutMs: 600_000 } });    // encodes outlast the 120s default wait

Convert pairs with video.resize in a single decode and encode, so shrinking then re-encoding never touches the frames twice. Two converts in one branch is the one case where the last wins: a container is a single property of the encode.

Leave video.convert off a branch and the video keeps its source container (resize still applies) — as long as that container is one of the four above.