Transform Media
Use this action when you have an audio or video file in your company storage and want it converted to another format.
Best for
- Re-encoding a video you downloaded or generated into a standard mp4
- Converting an audio file to a specific format — Opus, WAV or FLAC
- Pulling the soundtrack out of a video: point one of the audio presets at a video file and you get its audio
Use something else when
| You want | Use |
|---|---|
| Only to read a file's duration or dimensions | Inspect media — it is cheaper, and free the second time |
| A transcript of speech | Transcribe audio — it already converts the audio for you |
| To resize or convert an image | Execute code, Python. Pillow is available there |
Main fields
| Field | What it does |
|---|---|
| File | The audio or video file to convert, usually step(0).file from an earlier step |
| Bucket and Full path | An alternative to File when you want to point at the object directly |
| Preset | The format to produce — see the table below |
| Purpose | Optional label for what this step is for, shown in the logs |
Presets
| Preset | You get |
|---|---|
mp4 | Video re-encoded to H.264 with AAC audio, ready to play almost anywhere |
ogg_opus | Audio as Opus in an Ogg container — small, good for voice |
wav | Uncompressed audio |
flac_16k_mono | Lossless mono audio at 16 kHz, the shape speech tools usually want |
What later steps can use
| Value | What it is |
|---|---|
step(N).jobId | The transform job's ID |
step(N).jobStatus | The job's status when it was queued — normally pending |
step(N).preset | The preset the job was queued with |
This action queues the job — it does not wait for it
The step hands back a job ID and finishes immediately. Converting a large video can take minutes, so it runs in the background.
That means the converted file is not available to the next step in the same run. Do not try to send step(N).output — there is nothing there yet.
To use the result, check on the job until it is done:
- the
get_transcode_jobtool orGET /v1/transcodes/{id}, using the job ID; or - a scheduled workflow that looks for transform jobs whose status is
done.
When a job is done, output.fullPath and output.bucket are the converted file.
You can also check on a job at any time through the API (GET /v1/transcodes/{id}) or the get_transcode_job tool.
Limits
| Limit | Value |
|---|---|
| File size | 512 MiB (536,870,912 bytes) |
| Length, video presets | 30 minutes |
| Length, audio presets | 4 hours |
| Jobs queued at once | 10 per company |
If you need to check a file's length before converting it, use Inspect media first and branch on step(N).durationSeconds.
Cost
Converting media is billed as transcoding time, against your plan's transcoding allowance. Longer and larger files cost more.
Converting the same file to the same preset again is free. The result is kept and reused, so a workflow that runs repeatedly over the same file only pays once. Changing the file changes the result, so an updated file is converted again.
When a job fails
A failed job carries a reason in doc.errorCode. These are the ones you are most likely to see:
| Code | What happened |
|---|---|
too_large | The file is over 512 MiB |
too_long | The file is longer than the preset allows |
undecodable | The file could not be read as media, or this preset cannot produce it. Retrying will not help |
output_too_large | The converted file came out too big |
storage_quota_exceeded | Your storage allowance would be exceeded, so the converted file could not be stored. Permanent until you free space |
unavailable | The conversion service could not be reached. Worth retrying |
busy | The conversion service stayed at capacity for too long — see below |
max_attempts | The job was picked up and lost, over and over, without ever finishing, so it was given up on |
errorCode on its own is not proof of failure: a job that was simply put back in the queue also carries one — busy, or company_lookup_failed — while its status has gone back to pending. Read status first, and errorCode only to explain it.
The list is not closed, and unavailable covers more than an outage. A refusal the conversion step raises with a code of its own keeps that code. Everything else lands on unavailable — including a plan or credit refusal raised after the job started: the allowance is checked again when the worker picks the job up, just before encoding, so if your transcoding allowance ran out (or a pay-as-you-go wallet reached its floor) after you queued the job, it is recorded as unavailable, not as a billing error. So unavailable is worth retrying only once you have checked you are still inside your transcoding allowance — otherwise the same check refuses the retry outright.
If the conversion service is simply busy, the job is usually not failed — it goes back in the queue with a short delay and runs shortly after, without using up any of its attempts. That holds up to a point, not forever: after 20 requeues the job stops waiting and fails with busy. Those 20 are a shared budget — the same counter is also spent by requeues for unrelated internal reasons — so a job that was already put back once or twice for something else gives up after fewer than 20 busy waits.