Expand description
Export: render the timeline with the CPU Compositor + Mixer and pipe it into ffmpeg.exe
(-f rawvideo -pix_fmt rgba -s WxH -r fps -i pipe:0 + pre-mixed temp WAV), encoder chosen by the
output extension / settings. Plus the lossless -c copy fast path for pure cuts of one source.
Runs on a background thread; the UI polls Progress.
StructsΒ§
- Export
Options - GpuFrame
Request - One frame the export thread wants composited on the GPU. The UI thread owns the GL context, so it
picks these up in
App::update, renderslayersand sends the pixels back. - GpuScratch π
- Decoder state for the GPU export path: the same layer decoding the player does, on this thread.
- Progress
- Temp
File π - Deleted on drop (a no-op once
committed into place).
EnumsΒ§
- Frame
Source - Where an export gets its pictures.
ConstantsΒ§
- AUDIO_
EXTS - CANCELLED π
- MIX_
BLOCK π - Audio mix block (frames). Same as
playback::BLOCKon purpose:mixer::resample_addsamples clip gains at the block ends and lerps between them, so a longer block here would smear fades, volume keyframes and audio crossfades shorter than the block β export must ramp like playback does.
StaticsΒ§
- ENCODERS π
FunctionsΒ§
- codec_
args - ffmpeg output arguments (codec/quality) for an extension, given the userβs encoder preference and the
available encoders. βautoβ: mp4/mov/mkv/m4v β libx264 (+aac), webm β libvpx-vp9 (+libopus),
gif β gif, avi β mpeg4 (+mp3), audio-only β sensible codec for the container. The preference is
overridden where the container forbids it (webm: vp9/av1 only; mov: no vp9/av1).
Hardware encoders (nvenc/qsv/amf) use
-cq/-global_quality/-qpinstead of-crf. - cpu_
gaps π - What this export cannot render, as a suffix for the progress line (empty when nothing is dropped).
- detect_
encoders - Encoder names ffmpeg reports (
ffmpeg -hide_banner -encoders), cached after the first call. Empty if ffmpeg is missing. - ext_of π
- lossless_
segments - If the project is a pure cut of exactly one video source (every clip from the same asset, audio clips
exactly mirroring their linked video clipβs timing on each audio stream (muted tracks may be dropped),
no gaps between clips, no text/image/sequence clips, no effects/retime/pan/fades, volume 1, all clips
enabled, no transitions, no burnt-in subtitles), return the segments as (src_in, duration) in timeline
order. Such a project can be written with
-c copy. - mix_
to_ πwav - Mix the whole timeline into a temp WAV (f32 stereo 48 kHz). Progress 0..0.1.
- parse_
encoders π - run_
export π - run_
lossless π - spawn_
job π - Run
jobon a named thread; any Err (or panic) lands inProgress::finish. - start_
export - Start a full (re-encoding) export on a background thread. Frames are rendered at project size
with
Compositorand audio mixed withMixerinto a temp WAV first (fast), then video frames are piped to ffmpegβs stdin. Progress 0..1; cancel kills ffmpeg and removes the partial file. Audio-only extensions (mp3, wav, m4a, flac, ogg, aac, opus) skip video (-vn); gif skips audio. - start_
lossless_ cut - Lossless cut:
ffmpeg -ss in -t dur -i src -c copy -avoid_negative_ts make_zeroper segment (with-mapdropping muted audio streams), then concat demuxer when there is more than one segment. Cuts land on keyframes (not frame-accurate) β thatβs the trade for being instant. - stderr_
tail π - Drain ffmpegβs stderr on a helper thread; returns the last ~2000 chars.
- temp_
output π - Hidden sibling of
out(same folder, same extension so ffmpeg still picks the muxer by name) that ffmpeg writes into; it is renamed overoutonly on success, so a cancel or failure never truncates or deletes an existing destination β or the source, when cutting in place. - wait_
ffmpeg π - Wait for ffmpeg, killing it if the job is cancelled. Non-zero exit β Err(stderr tail).
- wav_
header π - 44-byte RIFF/WAVE header: IEEE float 32-bit, stereo, 48 kHz,
framessample frames.