Skip to content

Export: start, then poll

Use these three tools to write the timeline to a file from an agent, follow the job and stop it. export doesn’t wait for the file. It checks the request, puts a job on the Export Queue and returns at once, and the agent then asks how the job is going until it ends.

Menu
File ▸ Export…Window ▸ Export Queue
Keys
⌘E
Where
The export sheet's Add to Queue, and each row's Cancel in the Export Queue
Agent tools
exportexport_statuscancel_export
  1. Call export with a preset and a path. It returns straight away.

    { "preset": "h264", "path": "/Volumes/Edits/cut", "size": "1080p" }
    { "export_id": 3, "path": "/Volumes/Edits/cut.mp4", "status": "running" }
  2. Call export_status with that export_id, pause, and call it again until status is done, failed or cancelled.

  3. Read the done result. It says what the file holds, including the loudness it measured and any warnings.

To stop the job, call cancel_export. The job shows in Window ▸ Export Queue like any other, but the window doesn’t open by itself.

export does what File ▸ Export… does with Add to Queue, and it writes the file the same way, so an agent’s file and a person’s match. It takes the export sheet’s controls in the sheet’s own terms, apart from the frame rate, which it doesn’t take, and Quality, which it sets as exact rates.

Argument Type Required What it does
preset string Yes The encoding: a container and a codec. See Presets.
path string Yes Where to write, such as ~/Movies/cut.mp4. See Path handling.
size string or [width, height] No The output size. See Size.
range string No project for the whole timeline, or in_out for the in/out range. See Range.
video_bitrate integer No Target video rate in bits per second. See Exact bitrates.
audio_bitrate integer No Target AAC or Opus rate in bits per second. See Exact bitrates.
loudness_lufs number No Normalise the whole mix to this loudness, −70 to 0. See The loudness report.
peak_dbtp number No The master limiter’s ceiling, −20 to 0. See Peak dBTP.
audio_bits integer No 16 or 24, for WAV and AIFF. See Audio bits.
stems string No tracks or names, to write stems beside an audio mix. See Stems.
burn_in_timecode boolean No Draw the project timecode over the picture, on top of everything. Off by default. See Burn in timecode.
dynamic_range string No hlg, pq or sdr, in an HLG project. See Dynamic range.
encoder_speed string No faster, balanced or smaller, for AV1. See Encoder speed.
project string No The path of the open project to export, as get_project reports it. Without it, the frontmost project.

It returns {export_id, path, status}. path is the file that will be written, with ~ expanded and the extension corrected. status is running if the job started at once, or queued if it’s waiting.

Jobs in the queue run one at a time, behind anything already there. A job writes the project as it stood when export was called, so later edits don’t reach it. Calling export pauses playback in that project’s window.

export takes no scope. With a nest open it still writes the project’s timeline, not the nest’s.

export_status reports how a job is going, as its row in the Export Queue does, and it never waits. Pass the export_id, which is an integer of 1 or more.

Every result carries export_id, status, path and elapsed, the seconds since export was called, or from then to the finish once the job has ended. The rest depends on the status.

status Also carries
queued waiting while an AV1 or VP9 job is held for memory. estimated_seconds on av1, av1_webm, vp9_webm and vp9_alpha_webm.
running progress, from 0 to 1. phase while the job has one: “Preparing…” until the file’s writer exists, while renders, masks and measurements are still being made, and “Measuring loudness…” during the first pass over the mix. estimated_seconds on the same four presets.
done What the file holds, in the next table.
failed reason, the queue row’s sentence.
cancelled reason, the queue row’s sentence.

estimated_seconds is the export sheet’s estimate of the whole export in whole seconds, and it’s only an estimate.

waiting is a sentence such as “Waiting for memory: AV1 and VP9 exports running now hold about 2.1 GB of the 8.0 GB this Mac allows them, and this one needs about 7.0 GB.” AV1 and VP9 exports may hold a quarter of this Mac’s memory between them, though a job with no other running always starts. While one is held, a later job in the queue may run first.

A done result adds these keys.

Key What it holds
ok true.
bytes The file’s size.
preset, container, codec What was written.
width, height The file’s size in pixels. These are reported on audio presets too, where they mean nothing.
fps The rate as [num, den], such as [30, 1].
start, duration The part of the timeline written, in ticks.
burn_in_timecode Whether the argument was on.
dynamic_range The picture written: hlg, pq or sdr. Only for a video preset in an HLG project.
encoder_speed The speed used. Only on av1 and av1_webm.
audio_bits The depth written. Only on audio_wav and audio_aiff.
stems [{name, tracks, path}], one per file beside the mix. Only when stems was asked for.
loudness What the mix measured. See The loudness report.
graphic_warnings [{name, frame, message}], each distinct warning a graphic gave while the file was drawn. Collecting stops after 64 distinct reports, so a noisy graphic’s list can be cut short. frame is the graphic’s own frame, or null. Absent when there were none.
cursor_warnings [{media, path, message}], each media whose cursor file couldn’t be drawn. Its clips were written without a cursor. Absent when there were none.

cancel_export stops a job, as the row’s Cancel does, and returns what export_status would. Pass the export_id.

The job is What happens
Queued It’s cancelled before it starts. The result reads cancelled, with the reason “Cancelled before it started.”
Running It stops and its partly written file is removed. The result may still read running until writing has stopped, and export_status then reads cancelled, with the reason “Cancelled.”
Finished It’s left alone, and its file stays. The result is the finished job’s.

An export_id is known until Frame Job quits. Removing a finished row from the Export Queue, or choosing Clear Finished, doesn’t lose it, so an agent can still read how that job ended.

An id belongs to the launch, not to a project, so export_status and cancel_export don’t need project. Only ids that export returned are known. A job a person queued from the sheet has no id an agent can follow. Any other number returns the error “No export this launch has export_id 7 — ids come from export and last until Frame Job quits.”

A problem Frame Job can see from the request comes back from export itself as an error, and nothing is queued.

The request What stops it
An empty timeline “There is nothing on the timeline to export.”
A folder that doesn’t exist “There is no folder at … to write into.” Frame Job never creates the folder.
An unknown preset The error lists all the presets.
An unknown size, or one it can’t read The error lists the sizes. See Size.
range of in_out with no range set “This project has no in/out range — set one with set_range {start, end}, or export with range "project".”
A number out of range, or a word it doesn’t know The error names the argument and the value.
An option the preset doesn’t have See Audio bits, Stems, Dynamic range and Encoder speed.
A graphic clip in the range with no module, or a module that doesn’t compile “The export was not started: the graphic “…” does not compile — …. Fix the module and export again.” A clip with no module reads “has no module in graphics/” in place of “does not compile — …”. It names each graphic and its first error, and it covers graphics inside nests. An audio-only preset draws no graphics, so it isn’t stopped by one.
More than 600 frames on gif or apng “An animated GIF is limited to 600 frames and this range is …. Shorten the range.” There’s no frame-rate argument. See The 600-frame limit.
A size of another shape on a transparent preset “An export that keeps transparency has to have the canvas’s own shape…”. See Transparent presets.

Anything that goes wrong after that comes back from export_status as failed, with the sentence in reason. Check for it even when export answered cleanly.

What went wrong The reason
A stem’s file would be one of the project’s media “The stem “…” would replace media this project uses; export under another name.”
A graphic fails while it’s drawn “The export was stopped at frame … of the graphic “…”: …. No file was written.”
A retimed clip’s sound, an isolated voice or a voice effect couldn’t be rendered The sentence names the clip and the reason.
A Remove Background clip’s masks couldn’t be made “Clip …’s person masks could not be made: ….” A picture set to Foreground says foreground masks.
A clip’s gate, leveller or de-esser needs a loudness that hasn’t been measured “Clip …’s loudness or speech has not been measured yet…”. Wait for the clip’s analysis, then export again.
This Mac has no encoder for the preset “This Mac cannot export with the “…” preset.”

A graphic’s warnings are different: they don’t stop the export, and they arrive as graphic_warnings in the done result.

There are 15 presets, one per encoding. A preset says nothing about size. These are the rows of the sheet’s Format control, described in Choose a format. A wrong id’s error lists them all.

Preset In the sheet File Picture Sound
h264 H.264 (MP4) .mp4 8-bit. The sheet’s first row. AAC
hevc HEVC (MP4) .mp4 8-bit AAC
hevc_alpha HEVC with Alpha (MOV) .mov 8-bit with transparency. Safari’s transparent movie. AAC
hevc_10bit HEVC 10-bit (MP4) .mp4 10-bit AAC
av1 AV1 (MP4) .mp4 10-bit AAC
av1_webm AV1 (WebM) .webm 10-bit Opus
vp9_webm VP9 (WebM) .webm 8-bit (Profile 0) for an SDR picture, 10-bit (Profile 2) for HLG and PQ. One speed. Opus
vp9_alpha_webm VP9 with Alpha (WebM) .webm Always 8-bit, with transparency. The transparent movie Chrome and Firefox play. Opus
prores_422 ProRes 422 (MOV) .mov 10-bit. An editing master. 16-bit LPCM
prores_4444 ProRes 4444 (MOV) .mov 12-bit with transparency. A master. 16-bit LPCM
audio_m4a Audio only (M4A) .m4a None AAC
audio_wav Audio only (WAV) .wav None 48 kHz LPCM, 16 or 24 bits
audio_aiff Audio only (AIFF) .aiff None 48 kHz LPCM, 16 or 24 bits
gif Animated GIF .gif 256 colours. Fits inside 480 × 270 unless size says otherwise. None
apng Animated PNG .png Lossless, with transparency. Fits inside 960 × 540 unless size says otherwise. None

Macs before M3 can’t play av1 and av1_webm back.

There’s no frame-rate argument, so the sheet’s frame rate control has no agent equivalent. An export runs at the project’s rate, gif at 12.5 fps and apng at 25 fps. The done result’s fps says which, with 12.5 fps as [25, 2].

The folder must exist. A ~ at the start is expanded, and an existing file at the path is replaced. It’s removed as writing starts, so a job that fails or is cancelled from then on leaves neither file. Anything earlier, such as a refused call or a cancel while the job is measuring loudness, leaves it as it was.

The file always ends in the preset’s extension.

path preset Writes Why
cut.mp4 h264 cut.mp4 The extension is already right.
cut h264 cut.mp4 With no extension, it’s added.
cut.mov h264 cut.mp4 A different media extension is replaced.
Talk v1.2 h264 Talk v1.2.mp4 Any other suffix stays part of the name.
cut.webm h264 cut.mp4 So is .webm.
cut.mp4 av1_webm cut.webm The same the other way round.

The extensions it replaces are .mov, .mp4, .m4v, .m4a, .mp3, .wav, .aif, .aiff, .caf, .framejob, .srt, .vtt, .png, .jpg, .jpeg, .heic, .gif and .webm. The returned path is always the file that gets written.

size is the sheet’s Size control. See Export size for what the sizes mean to a person.

size In the sheet What it writes
document Document size The project’s own size. The default on every movie preset.
2160p 4K A short edge of 2160 pixels.
1440p 1440p A short edge of 1440 pixels.
1080p 1080p A short edge of 1080 pixels.
720p 720p A short edge of 720 pixels.
preset GIF default, APNG default The format’s cap. gif and apng only, where it’s the default.
[width, height] Custom… Exactly this size, from 16 to 8192 pixels on each edge.

The number is always the short edge, and the long edge follows the project’s shape, rounded to an even number. A vertical project’s 1080p is 1080 × 1920. Every size means the same on every project, so a 1920 × 1080 project’s 1080p is its own size, and a size larger than the project scales it up.

A movie is written at exactly the size asked for. If the shape differs from the project’s by more than a pixel, the picture is letterboxed. Within a pixel, it fills the frame instead.

  • Even edges. Every preset but prores_4444, gif and apng needs even dimensions, so an odd width or height is written one pixel smaller. That covers document on a project with an odd edge. The done result’s width and height are the file’s.
  • GIF and APNG. A size is a box the picture is fitted inside, keeping its shape and never scaling up. A vertical 1080 × 1920 project’s GIF default comes out at 152 × 270.
  • Audio presets. A size has no effect, and preset isn’t one of their sizes.
  • Transparent movies. A [width, height] of another shape is an error. See Transparent presets.

An unknown size returns an error with the list, for example “No export size is called “480p” for h264. The sizes are: document, 2160p, 1440p, 1080p, 720p — or pass [width, height].” A custom size outside 16 to 8192 pixels is an error too. It isn’t clamped.

range is the sheet’s Range control. project, the default, writes the whole timeline. in_out writes the range set with set_range, and export returns an error when there’s no range. See Export a range.

The range is snapped to the export’s frame grid and kept inside the project. A range that comes to nothing is an error too.

burn_in_timecode shows project time even in a range export, so a file written from 00:00:10:00 begins at 00:00 with a burn-in that reads 00:00:10:00.

The sheet offers quality tiers. An agent sets the rates directly, in bits per second, so 8 Mbps is 8000000. Each must be a whole number from 1 to 4,294,967,295.

video_bitrate is the target video rate. Without it, Frame Job works out a rate from the frame size and frame rate. ProRes, GIF and APNG ignore it, because ProRes is fixed by its profile and the other two have no bitrate.

On the AV1 and VP9 presets it works differently:

  • av1 and av1_webm. It’s a soft cap. The encoder works at a constant quality matched to HEVC at that rate, and the file usually comes in well under it. Very detailed footage can go up to about 1.25 times over. Without it, the quality is matched to HEVC at 0.07 bits per pixel per frame.
  • vp9_webm. It’s a soft cap too, matched to HEVC, or HEVC 10-bit in an HDR export. Up to about 1.15 times over was measured.
  • vp9_alpha_webm. It’s the same soft cap on the picture’s stream alone. The transparency’s stream comes on top, at a constant quality.

audio_bitrate is the AAC or Opus rate, 192 kbps when absent. Opus takes the nearest rate its encoder offers. ProRes, WAV and AIFF ignore it, because they write LPCM.

Every export with sound measures its own mix and reports it as loudness in the done result, normalised or not. GIF and APNG have no sound, and a timeline with no sound has nothing to measure, so loudness is absent from both.

loudness_lufs normalises the whole mix to an integrated loudness, from −70 to 0. The sheet’s Loudness rows are −14 for streaming, −16 for podcasts and −23 for EBU R 128 broadcast, and an agent can ask for any value, such as −14.5. The export measures itself first, then applies one gain to everything, through the master limiter. The file lands on the target with its loudest peaks limited, rather than the whole mix held down. GIF and APNG ignore it.

Key What it holds
summary The same line the queue row and the progress sheet show, such as “Peak −1.0 dBTP · −16.0 LUFS”, with “ · peaks limited by 8.6 dB” when the limiter took 0.05 dB or more.
integrated_lufs The file’s integrated loudness. Absent when it has none, and summary then says “loudness not measurable”.
true_peak_dbtp The file’s true peak. null when it’s silent.
sample_peak_dbfs The file’s sample peak, never above the true peak. null when it’s silent.
gain_db The gain applied to reach the target.
ceiling_dbtp The master limiter’s ceiling.
limited_db How far the limiter turned the loudest peak down.
capped_by_gain true when the +40 dB limit on the gain decided it, so the file may be short of the target.
target_lufs The loudness_lufs asked for. Absent when none was.

A programme shorter than one 400 ms measuring block, or one too quiet to pass the standard’s gate, has a peak and no integrated loudness. Digital silence reads “Silent” in summary.

Every export with sound goes through a master limiter, so the file’s true peak stays at or under a ceiling. peak_dbtp sets that ceiling, from −20 to 0. It’s −1 when absent, which is the sheet’s fixed value. 0 is the loosest, and there’s no way to turn the limiter off.

You can pass it with or without loudness_lufs. limited_db in the report says how far the limiter turned the loudest peak down.

audio_bits is the sheet’s Bit depth control: 16, the default, or 24. It’s rounded once from the mix and never dithered, and the done result repeats it.

It works on audio_wav and audio_aiff only. On any other preset export returns the error “h264 has no bit depth; audio_bits applies to audio_wav and audio_aiff”, naming the preset. ProRes keeps 16-bit sound. Any other number is an error, whatever the preset.

stems also writes stems beside the mix, on audio_m4a, audio_wav and audio_aiff. It’s the sheet’s Stems control.

stems What it writes
tracks One file per heard track.
names One file per track name. Heard tracks whose names match, ignoring case, share a file, and an unnamed track gets its own.

A track is heard when it has sound in it and isn’t muted or silenced by another track’s solo. Each stem is named <file> - <track name>.<ext>, beside the mix, so mix.wav and a track called Voice give mix - Voice.wav. An unnamed track is Track N, and Stem file names has the other cases.

A stem holds its tracks’ sound before the master, with no loudness gain and no limiter, so the stems add up to the mix wherever the master changed nothing. Any file already at a stem’s name is replaced.

The done result lists each one as stems [{name, tracks, path}]. tracks holds the ids of the timeline tracks in that stem.

  • On any other preset export returns the error “h264 has no stems; stems applies to audio_m4a, audio_wav and audio_aiff”, naming the preset.
  • With no track heard, the error is “stems: no track is heard, so there is no stem to write”.
  • If a stem’s file would be one of the project’s media, the job fails before any stem is written, and export_status gives the reason.
  • A failed or cancelled job leaves neither the mix nor any stem it wrote. A file it hadn’t yet replaced stays.

dynamic_range chooses the picture an HLG project writes. It’s the sheet’s Dynamic Range control.

dynamic_range What it writes
hlg BT.2100 HLG, with no Dolby Vision. The default on the presets that carry HDR.
pq HDR10: BT.2100 PQ at 1,000 cd/m², with a P3-D65 mastering display of 0.005–1,000 cd/m², MaxCLL 1,000 and MaxFALL 0.
sdr The project’s SDR version.

The presets that carry HDR are hevc_10bit, av1, av1_webm, vp9_webm, prores_422 and prores_4444. Every other video preset in an HLG project writes the SDR version, vp9_alpha_webm included, and audio presets ignore the argument.

  • hlg or pq on another video preset returns the error “h264 is 8-bit and writes the SDR version; export dynamic_range “pq” as hevc_10bit, av1, av1_webm, vp9_webm, prores_422 or prores_4444”.
  • hlg or pq in an SDR project returns the error “dynamic_range “pq” needs an HLG project; set_canvas output “hlg” first”.
  • sdr in an SDR project changes nothing.

Once a job is done, dynamic_range in the result names the picture that was written. An SDR project’s result has no such key.

encoder_speed trades export time for file size on av1 and av1_webm. It’s the sheet’s Speed control, and the done result names the one used.

encoder_speed SVT-AV1 preset What it does
faster 8 The quickest.
balanced 6 The default.
smaller 4 The smallest file for the picture, and the slowest.

On every other preset export returns the error “h264 has no encoder speed; encoder_speed applies to av1 and av1_webm”, naming the preset. That includes vp9_webm and vp9_alpha_webm, which have one speed.

Four presets keep a transparent canvas transparent: prores_4444, hevc_alpha, vp9_alpha_webm and apng. See Transparent exports. A GIF can show a fully transparent pixel, but it has no alpha channel, so nothing partial survives.

On the three movie presets, a [width, height] of a different shape from the canvas can’t be written, because the padding would destroy the alpha channel. export returns an error that names both sizes, and nothing is queued. The shape is judged after an odd edge is evened, and within a pixel the picture fills the frame, so a size in the canvas’s own proportions always works, at any scale. Every named size already has the canvas’s shape.

apng fits its picture inside the size instead, so this doesn’t apply to it.