CtrlK
BlogDocsLog inGet started
Tessl Logo

gamussa/reels-producer-skill

Write talking-head scripts and produce Instagram reels and YouTube shorts

90

1.77x
Quality

97%

Does it follow best practices?

Impact

64%

1.77x

Average score across 3 eval scenarios

SecuritybySnyk

Low

Low-risk findings worth noting

Overview
Quality
Evals
Security
Files

ffsafe.pyskills/reel-builder/scripts/

#!/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

.mcp.json

tile.json