Command, Input, Output and FrameJob fields¶
The declarative job types and every field on them. A Command is plain data: fill the struct
directly, or build it with NewCommand and the functional options — both produce the same value,
and JobSpec() renders either to the JSON the ffmpeg-wasi
engine consumes.
Task-shaped versions of this material live in the how-to guides; this page is the field list.
Command¶
| Field | Builder option | Default | Meaning |
|---|---|---|---|
Inputs |
WithInput, WithConcatInput |
empty | Inputs in order. Index 0 is the first, and that index is what a map specifier like 0:v refers to. |
FilterComplex |
WithFilterComplex |
empty | The whole filter_complex graph as one string, parsed by libav's avfilter_graph_parse2. Omit it to mux or copy without a graph. |
Outputs |
WithOutput |
empty | Outputs in order. |
JobSpec() is pure — no I/O — so it is safe to render and log a job before running it.
RunJob(ctx, fs, cmd) is Run with the rendered spec.
Input¶
type Input struct {
Path string
Concat []string
Seek *Seek
Format string
Options map[string]string
}
| Field | Builder option | Default | Meaning |
|---|---|---|---|
Path |
WithInput(path) |
— | The input path, resolved against the afero.Fs you pass to Run. |
Concat |
WithConcatInput(paths...) |
nil | Like-codec files joined into one continuous input through the concat demuxer (a packet-level join, no re-encode). When set, Path is ignored. Distinct from the concat filter, which decodes and re-encodes. |
Seek |
SeekTo(sec), SeekAccurateTo(sec) |
nil | Start the input at a point instead of decoding from the beginning. |
Format |
InputFormat(name) |
auto-probe | Force the demuxer by name (rawvideo, s16le, mp4, …). Required for headerless input, and for a file whose extension would mislead the probe. |
Options |
DemuxerOption(k, v) |
nil | Demuxer options as an AVDictionary. Raw geometry rides here: video_size, pixel_format, framerate for rawvideo; sample_rate, ch_layout for PCM. |
An option key the demuxer does not consume is an error from the engine, not a silent no-op — a
misspelled pixel_fmt fails the job rather than producing wrong output.
Seek¶
type Seek struct {
Start float64 // seconds
Mode string // SeekFast (default when empty) or SeekAccurate
}
| Mode | Constant | What it does | Cost |
|---|---|---|---|
| fast | SeekFast — the default when Mode is empty |
Demuxer jumps to the keyframe at or before Start; earlier packets are never read. |
cheap |
| accurate | SeekAccurate |
Fast seek, then decode and discard up to the exact frame. | a fraction of a GOP of decoding |
SeekAccurate cannot feed a copied stream. A stream copy can only cut on keyframes, so
Command.JobSpec() rejects the combination before the engine sees it:
afmpeg: output "out.mp4" maps copied stream "0:v" from an accurate-seek input
(copy cuts on keyframes; use SeekFast)
Output¶
type Output struct {
Path string
Map []string
VideoCodec string
AudioCodec string
SubtitleCodec string
Options map[string]string
BitstreamFilters map[string]string
Duration float64
End float64
CopyTS bool
Format string
FormatOptions map[string]string
Metadata map[string]string
Chapters string
StreamMetadata map[string]StreamMeta
}
| Field | Builder option | Default | Meaning |
|---|---|---|---|
Path |
WithOutput(path) |
— | Output path in the afero.Fs. The muxer is guessed from its extension unless Format says otherwise. |
Map |
Map(label), repeated |
nil | What to mux: graph output pads in brackets ([vout]) and/or input streams as in:type[:idx] specifiers (0:v, 0:a:0, 0:s). |
VideoCodec |
VideoCodec(name) |
engine default for the container | The video encoder (libopenh264, libx264, …) or CodecCopy to remux. |
AudioCodec |
AudioCodec(name) |
engine default for the container | The audio encoder (aac, libopus, …) or CodecCopy. |
SubtitleCodec |
— (set the field) | none | Encoder for a subtitle stream mapped as N:s (srt, webvtt, mov_text), or CodecCopy. Works alone (a sidecar .srt) or alongside video and audio (an embedded track). |
Options |
WithOption(k, v) |
nil | Encoder options — crf, preset, b:v, frames:v, … Nothing is filtered out. |
BitstreamFilters |
BitstreamFilter(mapKey, name) |
auto | Override the bitstream filter for one copied stream, keyed by its Map entry. "none" force-disables. Absent, the muxer inserts whatever the container requires. |
Duration |
Duration(sec) |
0 (to the end) | Stop after this many seconds (ffmpeg's -t). |
End |
End(sec) |
0 (to the end) | Stop at this position (ffmpeg's -to). |
CopyTS |
CopyTS() |
false | Keep source timestamps instead of zero-basing the output. Under CopyTS, End is an absolute source position. |
Format |
OutputFormat(name) |
from the path extension | Force the muxer (hls, dash, segment, mpegts, …). |
FormatOptions |
FormatOption(k, v) |
nil | Muxer options passed to write_header — hls_time, hls_segment_filename, movflags, … Distinct from Options, which reach the encoder. |
Metadata |
— (set the field) | nil | Container-level tags on the output (title, artist, …). |
Chapters |
— (set the field) | drop chapters | "copy" carries the first input's chapters across; an input index ("1") picks another; "" or "none" drops them. Authoring chapters inline is not supported. |
StreamMetadata |
— (set the field) | nil | Per-stream language, disposition flags and tags, keyed by the Map entry the stream comes from. |
Fields with no builder option are set on the struct. Both forms are first-class — the builder covers the common ones, the struct covers all of them.
StreamMeta¶
type StreamMeta struct {
Language string // e.g. "eng"
Disposition []string // e.g. {"default", "forced"}
Tags map[string]string // arbitrary per-stream tags
}
Applied to the output stream before the header is written.
CodecCopy¶
afmpeg.CodecCopy is the string "copy". Set it on VideoCodec, AudioCodec or
SubtitleCodec and name the source stream in Map — the packets pass through untouched, with
no decode and no encode.
What Command.JobSpec() rejects¶
Validation happens in Go, before the engine is invoked. Three things fail here:
| Condition | Error |
|---|---|
Duration or End negative |
output "…": Duration and End must be non-negative |
both Duration and End set |
output "…": Duration and End are mutually exclusive |
a copied Map entry whose input has SeekAccurate |
output "…" maps copied stream "…" from an accurate-seek input |
Everything else — an unknown codec, a map entry naming a stream that does not exist, a
filtergraph that will not parse — is the engine's to reject, and comes back as a non-zero
Result.ExitCode with the detail in Result.Stderr.
FrameJob¶
The frames op: pull still images out of one video input, without hand-tuning an fps/select
graph into the image2 muxer.
type FrameJob struct {
Input string
Format string
Options map[string]string
Select FrameSelect
Path string
Codec string
Scale string
Count int
}
| Field | Default | Meaning |
|---|---|---|
Input |
— | The video path. |
Format / Options |
auto-probe | Force and parameterise the demuxer, exactly as on Input. |
Select |
— | Which frames. Exactly one selector, see below. |
Path |
— | Required. Output template with an optional integer token, e.g. out/frame_%03d.png. A template with no token is valid only for a single frame. |
Codec |
png |
Image encoder — png, mjpeg, webp, … |
Scale |
none | ffmpeg scale arguments applied to each frame, e.g. 320:-2. |
Count |
0 (engine default) | Caps how many frames are emitted. |
An empty Path fails before the engine is reached:
afmpeg: FrameJob.Path (output template) is required.
FrameSelect — exactly one¶
type FrameSelect struct {
Timestamp *float64
Timestamps []float64
Interval float64
SceneThreshold *float64
Thumbnail bool
}
| Selector | Picks |
|---|---|
Timestamp |
the single frame at that second (a pointer, so 0 means the first frame rather than "unset") |
Timestamps |
one frame at each listed second |
Interval |
a frame every N seconds across the input (N > 0) |
SceneThreshold |
scene-change frames scoring above the threshold (select='gt(scene,T)') |
Thumbnail |
representative frames via the thumbnail filter |
Setting none or more than one fails in Go:
See also¶
- Compose a command with the builder
- Results, probes and progress values — what comes back
- Limitations — what these types deliberately cannot express