Skip to content

Fix GIF encoding with lavfi current filters - #231

Merged
ekisu merged 1 commit into
masterfrom
fix/issue-230
Sep 14, 2026
Merged

ekisu merged 1 commit into
masterfrom
fix/issue-230

Conversation

@ekisu

@ekisu ekisu commented Sep 14, 2026

Copy link
Copy Markdown
Owner

Fixes #230.

Problem

Applying a libavfilter bridge filter to playback (e.g. --vf=lavfi-crop=1920:800:0:140) and encoding a GIF with apply_current_filters = true fails:

[ffmpeg] AVFilterGraph: No such filter: 'crop:'
[lavfi] parsing the filter graph failed

apply_current_filters re-serializes the native vf list as name:key=value. mpv reports bridge filters as lavfi-<name> with positional arguments exposed under placeholder keys:

{ name = "lavfi-crop", params = { ["@0"]="320", ["@1"]="100", ["@2"]="0", ["@3"]="40" } }

so it produced lavfi-crop:@0=320:@1=100.... That happens to be accepted by mpv's own option parser (which is why non-GIF formats survived), but the GIF format rewrites every --vf-add=lavfi-* entry into one raw libavfilter graph, where @0= is not valid ffmpeg syntax, so the graph fails to parse.

Fix

Rebuild bridge filters in libavfilter argument syntax before handing them off:

  • lavfi-crop -> lavfi-crop=320:100:0:40 (positional @N sorted)
  • lavfi-eq -> lavfi-eq=contrast=1.5:saturation=1.5 (named keys sorted)
  • lavfi=[graph] -> lavfi=[graph]

Values are emitted unquoted because property expansion (and therefore mpv's %N% raw string syntax) does not run inside the bracketed graph the GIF format builds.

Tests

Added regression coverage in tests/testcases/test_video_filters.py:

  • GIF + lavfi-crop current filter: encodes and the crop is actually applied (288x90)
  • GIF + lavfi=[crop=...] graph current filter: same
  • GIF + lavfi-eq (named args): encodes
  • AVC + lavfi-crop: still applies the crop (320x100), guarding the mpv-option path

Verified the GIF tests fail on the pre-fix build and pass after; full suite: 42 tests, OK (2 pre-existing skips).

mpv reports libavfilter bridge filters such as "--vf=lavfi-crop" with
positional parameters named @0, @1, ... Serializing them as
"lavfi-crop:@0=value" is only understood by mpv's own option parser: the
GIF format rewrites the command line into a raw libavfilter graph, where
the placeholder names are invalid and graph parsing fails.

Rebuild bridge filters in libavfilter argument syntax
("lavfi-crop=w:h:x:y", "lavfi-eq=key=value") and drop mpv's raw string
quoting there, since property expansion does not run inside the
bracketed graph the GIF format builds.
@ekisu
ekisu merged commit 395a583 into master Sep 14, 2026
2 checks passed
@ekisu
ekisu deleted the fix/issue-230 branch September 14, 2026 17:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GIF encoding fails if I use lavfi-crop filter

1 participant