drawvg is a FFmpeg filter, available since 8.1, to render vector graphics on top of video frames.
The render is done by executing a script written in its own language, called VGS (Vector Graphics Script). The script consists of a series of commands to describe 2D graphics, which are rasterized using the Cairo library.
VGS is not intended to be used as a general-purpose language. Since its scope is
limited, it prioritizes being concise and easy to use. The syntax is heavily
inspired by languages like Magick Vector Graphics, or
SVG's <path>. Some features of the syntax (like using whitespaces
to separate arguments) are also present in languages like
TCL or
shell scripts.
Many command names are taken from PostScript. VGS is fully documented in the
language reference.
Scripts can use FFmpeg expressions to describe graphics dynamically, so they can compute coordinates based on frame dimensions, frame metadata, generate random values, read pixel colors, etc.
For example, to draw a blue circle in the middle of a frame:
circle (w / 2) (h / 2) 100
setcolor blue
fill
You can experiment with drawvg scripts in the playground. It also has a gallery of more complex examples, to show most of the capabilities of the interpreter.
There are other examples in the repository's website, to show how drawvg can be combined with other FFmpeg filters to modify video frames.
The implementation is in the drawvg-filter branch of
this repository.
To use the drawvg filter, you have to compile the FFmpeg fork in the
drawvg-filter branch, and configure FFmpeg with
--enable-cairo.
$ git clone --filter tree:0 -b drawvg-filter https://github.com/ayosec/ffmpeg-drawvg.git
$ cd ffmpeg-drawvg
$ ./configure --enable-cairo ...
$ make -j"$(nproc)"
$ ./ffmpeg ...If you have a container runtime (like Docker or Podman) in a x86-64 machine, instead of building it locally, you can use the container image built in this repository:
$ podman pull ghcr.io/ayosec/ffmpeg-drawvg:latest ...For example, to create a video (in the file output.mp4) with a rotating
square in the center:
podman run --rm --volume "$PWD:/mnt" \
ghcr.io/ayosec/ffmpeg-drawvg \
ffmpeg \
-y -f lavfi -i '
color=teal:qhd:60:5,
drawvg=
translate (w/2) (h/2)
rotate t
rect -100 -100 200 200
fill,
format=yuv420p
' \
-c:v libx265 -crf 18 \
/mnt/output.mp4
```