Compress
Reduce file size for images, video, audio, and documents. The SDK picks the right options for the input's media type.
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/wav | Stable |
⚠️ 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:
- TypeScript
- PHP
- Python
- Rust
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);
use Gisl\Sdk\Generated\SdkSpec\Enums\OptimizeFor;
$run = $client->file('./photo.jpg')
->compress(OptimizeFor::Size) // or Balanced / Quality
->run(maxWait: '5m');
echo $run->url;
Not available: the Python SDK is not published and no release is scheduled — see Python.
Not an application SDK: Rust is internal contract types — see Rust.
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:
- TypeScript
- PHP
- Python
- Rust
const result = await client
.compress('./photo.jpg', { quality: 80 })
.run({ maxWait: '5m' });
console.log(`${result.artifacts[0].filename} — ${result.artifacts[0].sizeBytes} bytes`);
use Gisl\Sdk\Ergonomic\RunOptions;
$result = $client
->compress('./photo.jpg', ['quality' => 80])
->run(new RunOptions(maxWait: '5m'));
echo "{$result->artifacts[0]->filename} — {$result->artifacts[0]->sizeBytes} bytes\n";
Not available: the Python SDK is not published and no release is scheduled — see Python.
Not an application SDK: Rust is internal contract types — see Rust.
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
| Option | Values | Default | Notes |
|---|---|---|---|
quality | 1–100 | 80 | Not on SVG. Ignored when a TIFF stays a TIFF: it is re-encoded losslessly. |
encoding_mode | quality · target_size · auto_quality | quality | JPEG, WebP and AVIF only. |
target_size_bytes | ≥ 1024 | — | With encoding_mode: 'target_size'. |
quality_preset | best · good · fair · low | good | With encoding_mode: 'auto_quality'. |
lossless | boolean | false | JPEG and WebP, quality mode only. |
progressive | boolean | true | JPEG only. |
chroma_subsampling | 420 · 422 · 444 | — | JPEG only; not with lossless. |
avif_speed | 1–10 | 4 | AVIF only. |
metadata | strip · keep | strip | keep is not offered for AVIF or SVG. |
output_format | original · webp | original | auto and smallest are planned. For any other format, use convert. |
width / height | 1–16384 | — | Resizes the one output; width × height ≤ 16 MP. Not on SVG. |
fit | max · crop · scale | max | When width or height is set. |
color_profile | keep · srgb · strip | keep | srgb is planned for GIF and TIFF input. Not on SVG. |
auto_orient | boolean | true | Not on SVG. |
SVG takes only metadata (strip) and output_format.
Video
MP4, WebM and QuickTime (MOV) input.
| Option | Values | Default | Notes |
|---|---|---|---|
codec | h264 · h265 · vp9 · av1 | h264 | Left at the default, the server picks a codec the container can carry (WebM → vp9). |
encoding_mode | crf · target_size | crf | target_size is for MP4/MOV output only; WebM, Ogg and long-form video are refused with feature_not_available. |
crf | 0–51 | 23 | Lower is higher quality. crf mode. |
target_size_bytes | ≥ 1048576 (1 MiB) | — | target_size mode. |
preset | ultrafast … veryslow | medium | Encoder speed against compression. |
width / height | 2–7680 / 2–4320 | — | |
fit | max · crop · scale · pad | max | When width or height is set. |
fps | 1–120 | — | Output frame rate. |
faststart | boolean | true | MP4/MOV only. |
audio_codec | aac · opus · vorbis · copy | copy | copy keeps the source audio stream. |
audio_bitrate | 64 · 96 · 128 · 192 · 256 · 320 | — | kbps; with a re-encoding audio_codec. |
trim_start / trim_end | seconds, ≥ 0 | — | Seconds cut from the start / from the end. |
output_format | original | original | mp4, 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.
| Option | Values | Default | Notes |
|---|---|---|---|
output_format | original · mp3 · aac · ogg · opus · flac · wav | original | Changes the format in the same job. |
bitrate | 64 · 96 · 128 · 192 · 256 · 320 | 128 | kbps, lossy output only — an explicit bitrate with FLAC or WAV output is rejected. |
channels | 1–2 | — | Mono or stereo. |
sample_rate | 22050 · 44100 · 48000 | — | Hz. |
normalize | boolean | false | Loudness normalisation to −14 LUFS (EBU R128). |
trim_start / trim_end | seconds, ≥ 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.
| Option | Values | Default | Notes |
|---|---|---|---|
quality | 1–100 | 70 | JPEG quality of the images inside the PDF. |
max_image_dimension | 64–10000 | 1600 | Longest 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:
| Preset | quality | max_image_dimension |
|---|---|---|
Size | 50 | 1200 |
Balanced | 70 | 1600 |
Quality | 85 | 2400 |
- 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
422INPUT_PASSWORD_PROTECTED; a file that reaches the worker encrypted fails withinvalid_format.
- TypeScript
- PHP
- Python
- Rust
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);
use Gisl\Sdk\Generated\SdkSpec\Enums\OptimizeFor;
// A preset…
$small = $client->file('./report.pdf')
->compress(OptimizeFor::Size)
->run(maxWait: '5m');
// …or explicit options, which win over the preset's values.
$tuned = $client->file('./report.pdf')
->compress(OptimizeFor::Balanced, ['quality' => 60, 'max_image_dimension' => 1400])
->run(maxWait: '5m');
echo $tuned->artifacts[0]->alreadyOptimal === true ? "already optimised\n" : "{$tuned->url}\n";
Not available: the Python SDK is not published and no release is scheduled — see Python.
Not an application SDK: Rust is internal contract types — see Rust.
To change what a preset level means for PDF across a whole client, register a client-wide override with the PDF preset builder:
- TypeScript
- PHP
- Python
- Rust
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 }),
});
use Gisl\Sdk\Generated\SdkSpec\Enums\OptimizeFor;
use Gisl\Sdk\Gisl;
use Gisl\Sdk\Preset\DocumentPdfCompressPresetOptions;
use Gisl\Sdk\PresetDefaults;
$client = Gisl::create(
apiKey: 'sk_...',
presetDefaults: PresetDefaults::create()
->pdfCompress(OptimizeFor::Size, new DocumentPdfCompressPresetOptions(
quality: 40,
maxImageDimension: 1000,
)),
);
Not available: the Python SDK is not published and no release is scheduled — see Python.
Not an application SDK: Rust is internal contract types — see Rust.
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.
- TypeScript
- PHP
- Python
- Rust
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`);
}
}
$result = $client->file('./photo.jpg')->compress()->run();
foreach ($result->artifacts as $out) {
if ($out->alreadyOptimal === true) {
echo "{$out->filename} is already optimised\n";
}
}
Not available: the Python SDK is not published and no release is scheduled — see Python.
Not an application SDK: Rust is internal contract types — see Rust.
A batch at once
- TypeScript
- PHP
- Python
- Rust
const many = await client
.files(['./a.jpg', './b.png', './c.webp'])
.compress(OptimizeFor.Balanced)
.run();
$many = $client->files(['./a.jpg', './b.png', './c.webp'])
->compress(OptimizeFor::Balanced)
->run();
Not available: the Python SDK is not published and no release is scheduled — see Python.
Not an application SDK: Rust is internal contract types — see Rust.