Skip to main content

Compress

Reduce file size for images, video, audio, and documents. The SDK picks the right options for the input's media type.

PDF compress is Beta

Documents means Office (DOCX, XLSX, PPTX), OpenDocument, EPUB and — in Beta — PDF. PDF compress shrinks the images inside the document; text and vector content are not re-encoded. See PDF below.

Audio formats​

Accepted
audio/aac · audio/flac · audio/mp4 · audio/mpeg · audio/ogg · audio/wavStable

⚠️ This list is specific to compress. Each operation accepts its own set — merge, for example, does not take audio/mp4. Do not carry a list from one page to another; call getSchema() for the authoritative set at runtime.

File-first with a preset​

When you would rather express intent than tune numbers, use a file-first recipe with an OptimizeFor preset — Size, Balanced, or Quality:

import { gisl, OptimizeFor } from '@giveitsmaller/sdk';

const client = await gisl.create({ apiKey: 'REPLACE_ME_API_KEY' });

const result = await client
.file('./photo.jpg')
.compress(OptimizeFor.Size) // or Balanced / Quality
.run({ maxWait: '5m' });

console.log(result.url);

Per-call options​

To set explicit encode options instead of a preset, pass them to the ergonomic compress(input, options) form. For lossy images, quality is a 1–100 encode quality:

const result = await client
.compress('./photo.jpg', { quality: 80 })
.run({ maxWait: '5m' });

console.log(`${result.artifacts[0].filename} — ${result.artifacts[0].sizeBytes} bytes`);

The exact option keys are media-type specific — and the file-first chain validates them before any upload, so a typo is caught locally rather than as a server 422. In TypeScript the bag is typed CompressOptions on both forms, so a misspelled key in an inline bag is already a compile error. To fetch the authoritative, per-MIME option list at runtime, call getSchema() for the input's media type and operation.

Preset and options together​

On the file-first chain the preset is the first argument and the option bag the second; they combine, and an explicit option wins over the preset's value — TypeScript .compress(OptimizeFor.Balanced, { quality: 80 }), PHP ->compress(OptimizeFor::Balanced, ['quality' => 80]).

For options without a preset, leave the first argument empty — TypeScript .compress(undefined, { quality: 80 }), PHP ->compress(options: ['quality' => 80]). Passing the bag alone (.compress({ quality: 80 })) binds it to the preset argument and is rejected.

Options by media type​

Every option is optional; the default applies when you omit it. Values marked planned are declared in the contract but not yet available — the API refuses them with feature_not_available.

Image​

OptionValuesDefaultNotes
quality1–10080Not on SVG. Ignored when a TIFF stays a TIFF: it is re-encoded losslessly.
encoding_modequality · target_size · auto_qualityqualityJPEG, WebP and AVIF only.
target_size_bytes≥ 1024—With encoding_mode: 'target_size'.
quality_presetbest · good · fair · lowgoodWith encoding_mode: 'auto_quality'.
losslessbooleanfalseJPEG and WebP, quality mode only.
progressivebooleantrueJPEG only.
chroma_subsampling420 · 422 · 444—JPEG only; not with lossless.
avif_speed1–104AVIF only.
metadatastrip · keepstripkeep is not offered for AVIF or SVG.
output_formatoriginal · webporiginalauto and smallest are planned. For any other format, use convert.
width / height1–16384—Resizes the one output; width × height ≤ 16 MP. Not on SVG.
fitmax · crop · scalemaxWhen width or height is set.
color_profilekeep · srgb · stripkeepsrgb is planned for GIF and TIFF input. Not on SVG.
auto_orientbooleantrueNot on SVG.

SVG takes only metadata (strip) and output_format.

Video​

MP4, WebM and QuickTime (MOV) input.

OptionValuesDefaultNotes
codech264 · h265 · vp9 · av1h264Left at the default, the server picks a codec the container can carry (WebM → vp9).
encoding_modecrf · target_sizecrftarget_size is for MP4/MOV output only; WebM, Ogg and long-form video are refused with feature_not_available.
crf0–5123Lower is higher quality. crf mode.
target_size_bytes≥ 1048576 (1 MiB)—target_size mode.
presetultrafast … veryslowmediumEncoder speed against compression.
width / height2–7680 / 2–4320—
fitmax · crop · scale · padmaxWhen width or height is set.
fps1–120—Output frame rate.
faststartbooleantrueMP4/MOV only.
audio_codecaac · opus · vorbis · copycopycopy keeps the source audio stream.
audio_bitrate64 · 96 · 128 · 192 · 256 · 320—kbps; with a re-encoding audio_codec.
trim_start / trim_endseconds, ≥ 0—Seconds cut from the start / from the end.
output_formatoriginaloriginalmp4, webm and ogg are planned; use convert to change container.

speed is planned. With crf on MP4/MOV output the file size is still bounded by a ceiling of about 60% of the source video bitrate, so already-efficient sources do not grow; it is skipped when the source bitrate cannot be read.

Audio​

MP3, AAC, Ogg, FLAC, WAV and MP4 audio input.

OptionValuesDefaultNotes
output_formatoriginal · mp3 · aac · ogg · opus · flac · wavoriginalChanges the format in the same job.
bitrate64 · 96 · 128 · 192 · 256 · 320128kbps, lossy output only — an explicit bitrate with FLAC or WAV output is rejected.
channels1–2—Mono or stereo.
sample_rate22050 · 44100 · 48000—Hz.
normalizebooleanfalseLoudness normalisation to −14 LUFS (EBU R128).
trim_start / trim_endseconds, ≥ 0—

Documents​

Office (DOCX, XLSX, PPTX), OpenDocument (ODT, ODS, ODP) and EPUB take quality (1–100, default 50). Their other declared options are all planned.

PDF (Beta)​

application/pdf input, up to 200 MiB. Both options act on the images inside the PDF; text and vector content are not re-encoded.

OptionValuesDefaultNotes
quality1–10070JPEG quality of the images inside the PDF.
max_image_dimension64–100001600Longest side, in pixels, of each image inside the PDF; larger images are scaled down keeping their shape, smaller ones are left as they are. Both SDKs also accept maxImageDimension.

The OptimizeFor presets resolve to:

Presetqualitymax_image_dimension
Size501200
Balanced701600
Quality852400
  • A result that is not smaller comes back as the original file, marked alreadyOptimal — see below.
  • A signed PDF comes back unchanged, also marked alreadyOptimal.
  • An encrypted (password-protected) PDF fails. When the upload has been probed as password-protected, creating the job is refused with a 422 INPUT_PASSWORD_PROTECTED; a file that reaches the worker encrypted fails with invalid_format.
import { gisl, OptimizeFor } from '@giveitsmaller/sdk';

const client = await gisl.create({ apiKey: 'REPLACE_ME_API_KEY' });

// A preset…
const small = await client
.file('./report.pdf')
.compress(OptimizeFor.Size)
.run({ maxWait: '5m' });

// …or explicit options, which win over the preset's values.
const tuned = await client
.file('./report.pdf')
.compress(OptimizeFor.Balanced, { quality: 60, maxImageDimension: 1400 })
.run({ maxWait: '5m' });

console.log(tuned.artifacts[0].alreadyOptimal ? 'already optimised' : tuned.url);

To change what a preset level means for PDF across a whole client, register a client-wide override with the PDF preset builder:

import { gisl, OptimizeFor, presetDefaults } from '@giveitsmaller/sdk';

const client = await gisl.create({
apiKey: 'REPLACE_ME_API_KEY',
presetDefaults: presetDefaults()
.pdfCompress(OptimizeFor.Size, { quality: 40, maxImageDimension: 1000 }),
});

When the file cannot get smaller​

A compress that keeps the file's format and cannot make it any smaller returns the original file, unchanged, and the run still succeeds. That output is marked alreadyOptimal: true, so show it as "already optimised" rather than as a failure or a size that did not move. alreadyOptimalKind says why: not_smaller means the file was compressed and the result was not smaller. It is the only kind today; treat any other value, or none, as a plain "already optimised".

Both fields are absent — undefined in TypeScript, null in PHP — on an ordinary output; absent and false mean the same thing. Video and audio over 5 minutes (the long-form tier) are not covered yet: a long-form compress that cannot shrink the file still fails with output_too_large.

const result = await client.file('./photo.jpg').compress().run();
for (const out of result.artifacts) {
if (out.alreadyOptimal) {
console.log(`${out.filename} is already optimised`);
}
}

A batch at once​

const many = await client
.files(['./a.jpg', './b.png', './c.webp'])
.compress(OptimizeFor.Balanced)
.run();

See also​