Fix: limit FFmpeg crop expression to 20 sample points (was overflowing 4KB limit)

This commit is contained in:
Sebastjan Artič 2026-04-28 16:32:26 +00:00
parent bf7ced5c7b
commit 400f6dbb6d

View File

@ -146,7 +146,9 @@ def build_track_filter(info, x_at, target_w, target_h, fps):
# Vzorčimo x(t) na ~5 fps (dovolj gladko po smoothingu)
duration = info["duration"]
n_samples = max(2, int(duration * 5))
# Limit: max 20 vzorcev, ker FFmpeg ima limit na expression dolžino
# Pri >20 vzorcih FFmpeg crop expression preseže 4096 char limit in zavrže
n_samples = max(2, min(20, int(duration * 0.7)))
times = np.linspace(0, duration, n_samples)
x_centers_norm = [x_at(t) for t in times]
# Pretvori normaliziran center v dejanski levi-zgornji x v skaliranem oknu
@ -156,19 +158,7 @@ def build_track_filter(info, x_at, target_w, target_h, fps):
x_left = max(0, min(max_x, x_left))
x_lefts.append(x_left)
# Sestavi piecewise expression: če (t < t1, x1, če (t < t2, x2, ...))
# FFmpeg ima omejitev na dolžino expression-a, zato uporabimo drugačen pristop:
# Generiramo CSV in uporabimo `sendcmd` filter ali pa preprosto
# nizkofrekvenčno linearno interpolacijo prek `if/lerp`.
# Pragmatično: zgradimo nested if. Pri 5 fps in 60s = 300 vej; deluje.
# Za daljše videe rebajzamo na 2 fps.
if duration > 120:
n_samples = int(duration * 2)
times = np.linspace(0, duration, n_samples)
x_lefts_resampled = []
for t in times:
x_lefts_resampled.append(np.interp(t, np.linspace(0, duration, len(x_lefts)), x_lefts))
x_lefts = x_lefts_resampled
# n_samples je že omejen na 20, expression bo vedno < 2KB
# Linearna interpolacija med vzorci znotraj FFmpeg expression
# Format: če(t<t_i, lerp(x_{i-1}, x_i, (t-t_{i-1})/(t_i-t_{i-1})), nadaljuj)