marzeq/vedit
clone
| file | .gitignore |
| file | arena.h |
| file | compiler.c |
| file | compiler.h |
| file | language.h |
| file | LANGUAGE.md |
| file | main.c |
| file | Makefile |
| file | parser.c |
| file | parser.h |
| file | probe.c |
| file | probe.h |
| file | README.md |
| file | strview.h |
| file | tests.c |
| file | typecheck.c |
| file | typecheck.h |
README.md
vedit
vedit is a compact postfix language that compiles linear video edits into one FFmpeg -filter_complex graph.
Build and run
make
make test
./vedit -n example.edit output.mp4 # compile and print only
./vedit example.edit output.mp4 # print, then execute FFmpeg
Override the built-in -c:v libx264 -c:a aac output encoding arguments from the programme itself:
encoding "-c:v libx265 -crf 18 -preset slow -c:a libopus"
ffmpeg-args "-movflags +faststart"
The most recent encoding instruction replaces the complete video/audio encoding vector; calling
it again overwrites the earlier value. Every ffmpeg-args instruction appends more final output
arguments. Argument strings are tokenized without shell evaluation and reproduced by -n;
single-quoted groups preserve spaces inside one FFmpeg argument. Managed subtitle codec arguments
are still generated separately unless appended arguments explicitly override them.
Quoted strings may contain positional substitutions. Given video "$1" in a programme, run:
./vedit edit.txt output.mp4 "some input file.mp4"
Arguments after the output path are exposed as $1, $2, and so on. Substitutions may occur inside
larger strings, such as video "clips/$1.mp4". Values are never interpreted by a shell.
ffprobe and ffmpeg must be available on PATH for normal CLI use.
The command printed by -n is self-contained, including codec-aware subtitle processing, cue
clipping, concat-list creation, chapter metadata generation, and embedded-font extraction. Those
steps appear as private helper invocations using the absolute path of the current
vedit executable, so keep that executable available when running a saved command later.
Language
Sources and literals push values:
video "picture.mov"
audio "dialogue.wav"
combined "clip.mp4"
subtitles "captions.srt"
duration 250ms
duration 01:23.500
scalar 0.7
index 0
burn-style "font=sans-serif; size=42; color=#FFFFFF"
string "Japanese"
attachment "font.ttf"
Paths are quoted and may contain spaces or #. Outside quotes, # begins a comment. There is
one instruction per line.
Stack operations are dup, drop, swap, over, and rot. Media operations are:
get-video get-audio get-subtitles split length
slice take concat delay
mux attach-subtitles video-to-combined burn-subtitles
set-language set-title set-default set-forced set-tag
chapter add-chapter drop-chapter move-chapter
add-attachment drop-attachment move-attachment
volume mix silence
speed fade-in fade-out
The language also provides compile-time Boolean logic, typed scalar/duration arithmetic and
comparisons, structured if/else/end, and bounded begin/while/repeat loops. Loops are
fully unrolled while constructing the FFmpeg graph and are limited to 10,000 iterations.
The separate typecheck pass records each instruction's consumed and produced types without
modifying the parsed instruction array. COMBINED values retain ordered collections of every video,
audio, and subtitle track in their source, as well as chapters, container tags, and attachments.
Indexed operations select, take, drop, append, replace, and reorder tracks. Untouched compatible
subtitle codecs are stream-copied; ASS/SSA styles, font attachments, metadata, dispositions, and
chapters are preserved through Matroska workflows. Compilation requires exactly one final media value.
Source durations come from ffprobe JSON. Stream-specific durations are preferred, with
format.duration as fallback. Results are cached by path. Known durations propagate through the
graph and are used by length and to calculate fade-out start times.
See LANGUAGE.md for all value types, operations, signatures, and stack semantics.