Write talking-head scripts and produce Instagram reels and YouTube shorts
90
97%
Does it follow best practices?
Impact
64%
1.77xAverage score across 3 eval scenarios
Low
Low-risk findings worth noting
#!/usr/bin/env python3
"""Values that go into an ffmpeg filter graph, made safe first.
A filter graph is parsed twice. The graph parser splits filters on ',' and
';' and options on ':'; then each filter's own option parser splits key=value
pairs on ':' again. Anything a caller supplies that reaches a graph unchecked
is therefore two things at once: a value, and a place to splice in a filter.
Measured on this codebase before this module existed:
capture_window.py --crop "W:H:X:Y,drawtext=text=..." rendered the text.
render_reel.py --lut "/path/a:b.cube" split at the colon
and failed to parse.
Two rules, both from kajisho5/ffmpeg-skill (MIT, see CREDITS.md): a value
that is a FILE PATH is escaped for both parser passes; any other value is
VALIDATED against the shape it must have and refused otherwise. No caller
builds a filter string from an unchecked argument.
Also home to the loudnorm two-pass helpers, since both callers that need them
(export_variants.py, clean_audio.py) already import from here.
"""
import json
import re
import subprocess
import sys
from pathlib import Path
# W:H:X:Y as ffmpeg's crop filter takes them, integers only. Expressions like
# iw/2 are deliberately not accepted here: the one caller that takes a crop
# from argv (capture_window.py) wants a fixed box, and an expression grammar is
# exactly the door the injection walked through.
_CROP_RE = re.compile(r"^\d+:\d+:\d+:\d+$")
def escape_filter_path(path):
"""A file path usable as a filter option value (lut3d=, subtitles=, fontfile=).
Colons are escaped twice so they survive both parser passes; graph-level
characters once. Backslashes become forward slashes first, which ffmpeg
accepts everywhere, so a backslash never needs escaping itself.
"""
p = str(Path(path)).replace("\\", "/")
p = p.replace(":", "\\\\:")
for ch in ("'", ",", ";", "[", "]"):
p = p.replace(ch, "\\" + ch)
return p
def validate_crop(value, flag="--crop"):
"""W:H:X:Y with integers, or exit naming the flag and what it must look like."""
if not _CROP_RE.match(value or ""):
sys.exit(f"{flag} must be W:H:X:Y with whole numbers, e.g. 2992:1660:0:214 "
f"— got {value!r}. Filter expressions are not accepted here.")
return value
def measure_loudness(path):
"""loudnorm's analysis-pass JSON for a file, or None when it cannot be read.
The measured loudness is `input_i`; `output_i` is a prediction for a
hypothetical second pass, not a reading of this file.
"""
r = subprocess.run(
["ffmpeg", "-hide_banner", "-i", str(path), "-af",
"loudnorm=print_format=json", "-f", "null", "-"],
capture_output=True, text=True)
start, end = r.stderr.rfind("{"), r.stderr.rfind("}")
if start == -1 or end == -1:
return None
try:
return json.loads(r.stderr[start:end + 1])
except json.JSONDecodeError:
return None
def loudnorm_filter(target_i, true_peak, lra, measured=None):
"""A loudnorm filter string; two-pass when a measurement is supplied.
Without measured_* values loudnorm runs in dynamic mode, adjusting gain as
it goes, which audibly pumps on speech. With them it applies one linear
gain across the file. Pass the analysis-pass JSON from measure_loudness().
"""
ln = f"loudnorm=I={target_i}:TP={true_peak}:LRA={lra}"
if measured:
ln += (f":measured_I={measured['input_i']}:measured_TP={measured['input_tp']}"
f":measured_LRA={measured['input_lra']}"
f":measured_thresh={measured['input_thresh']}"
f":offset={measured['target_offset']}:linear=true")
return ln.tessl-plugin
skills
reel-builder
assets
references
scripts
yap-writer