ffmpeg-skill 3.2.0 → 3.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/contract.md +2 -2
- package/package.json +1 -1
- package/references/scripts.md +5 -0
- package/scripts/audio.py +4 -3
package/docs/contract.md
CHANGED
|
@@ -21,7 +21,7 @@ The contract is derived from the code that runs, not maintained beside it:
|
|
|
21
21
|
| Field | Meaning | Changes when |
|
|
22
22
|
|---|---|---|
|
|
23
23
|
| `contract_version` | shape of this document (`2.0`) | a key is renamed, removed or changes meaning |
|
|
24
|
-
| `skill.version` | the npm / package.json version (`3.2.
|
|
24
|
+
| `skill.version` | the npm / package.json version (`3.2.1`) | any release |
|
|
25
25
|
|
|
26
26
|
A release that adds a tool or a flag keeps `contract_version`; a breaking change to the
|
|
27
27
|
ToolSpec shape bumps it. Consumers pin on `contract_version` and read `skill.version`
|
|
@@ -149,7 +149,7 @@ JSON would have been rewritten for that. The flat keys, typed per tool in `outpu
|
|
|
149
149
|
"deprecated": [],
|
|
150
150
|
"removed": [{"what": "...", "since": "1.10.0", "replacement": "...", "removed_in": "2.0.0", "where": "cli | json | mcp | behaviour"},
|
|
151
151
|
{"what": "running on FFmpeg 5.x (the requirements.ffmpeg floor)", "since": "2.14.0", "replacement": "FFmpeg 6.1 or later; ...", "removed_in": "3.0.0", "where": "behaviour"}],
|
|
152
|
-
"skill": {"id": "ffmpeg-skill", "version": "3.2.
|
|
152
|
+
"skill": {"id": "ffmpeg-skill", "version": "3.2.1", "execution_mode": "local", "kind": "execution",
|
|
153
153
|
"entrypoints": {"cli": "...", "mcp": "...", "contract": "...", "doctor": "..."},
|
|
154
154
|
"not_provided": ["AI reasoning", "decisions", "production plans", "project IR", "approvals", "network access", "transcription engine"]},
|
|
155
155
|
"requirements": {"python": ">=3.10 (standard library only)", "ffmpeg": ">=6.1", "ffprobe": ">=6.1"},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ffmpeg-skill",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.1",
|
|
4
4
|
"description": "Agent Skill that gives coding agents (Claude Code, Cursor, Codex) a local video editor: 42 FFmpeg tools with a machine-readable contract, contract-derived MCP server, FFmpeg capability detection, probe-first / verify-last workflow. Cut, join, silence removal, fit, captions and karaoke, overlays, motion graphics, HDR to SDR, LUTs, audio clean-up and typed dynamics, sync with drift correction, multicam, loudness, delivery checks, project rendering, batch. No API keys, no cloud, no dependencies.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ffmpeg",
|
package/references/scripts.md
CHANGED
|
@@ -1851,6 +1851,11 @@ audio.py INPUT [--voice [light|medium|strong] | --denoise [--denoise-strength 25
|
|
|
1851
1851
|
[--effects FILE [--effects-volume -14]] [--stereo-widen 0..1]
|
|
1852
1852
|
[--fade-in S] [--fade-out S] [--stereo | --mono | --downmix] [--replace FILE] [-o OUT]
|
|
1853
1853
|
```
|
|
1854
|
+
`--denoise` is `afftdn=nf=-N:tn=1`, where N is `--denoise-strength`, the noise
|
|
1855
|
+
floor in dB below full scale (20..60, default 25). It is the starting floor that
|
|
1856
|
+
`tn=1` then tracks, not an amount removed; ffmpeg's `nf` accepts -80..-20 only, so
|
|
1857
|
+
values under 20 are refused before ffmpeg runs.
|
|
1858
|
+
|
|
1854
1859
|
`--voice` takes a strength; a bare `--voice` is `medium`, the chain it has always
|
|
1855
1860
|
produced. The exact filter chains:
|
|
1856
1861
|
|
package/scripts/audio.py
CHANGED
|
@@ -161,7 +161,7 @@ def main() -> int:
|
|
|
161
161
|
ap.add_argument("-o", "--output", help="output file (default: <name>_audio.<ext>)")
|
|
162
162
|
clean = ap.add_argument_group("clean-up")
|
|
163
163
|
clean.add_argument("--denoise", action="store_true", help="FFT noise reduction (afftdn, adaptive)")
|
|
164
|
-
clean.add_argument("--denoise-strength", type=float, default=25.0, help="noise floor in dB
|
|
164
|
+
clean.add_argument("--denoise-strength", type=float, default=25.0, help="afftdn noise floor in dB below full scale, 20..60 (default 25; ffmpeg accepts nf -80..-20, and tn=1 then tracks the floor from this starting point)")
|
|
165
165
|
clean.add_argument("--voice", nargs="?", const="medium", choices=["light", "medium", "strong"], default=None,
|
|
166
166
|
help="speech preset (default medium when the flag is given bare): light = highpass 80 Hz + gentle compression; "
|
|
167
167
|
"medium = highpass, de-esser, denoise, gentle compression; strong = medium plus a harder de-esser, a second "
|
|
@@ -305,8 +305,9 @@ def main() -> int:
|
|
|
305
305
|
if args.voice:
|
|
306
306
|
fx.append(VOICE_LEVELS[args.voice])
|
|
307
307
|
elif args.denoise:
|
|
308
|
-
|
|
309
|
-
|
|
308
|
+
# afftdn's nf accepts -80..-20 only; 10..19.99 used to pass here and then fail inside ffmpeg.
|
|
309
|
+
if not 20 <= args.denoise_strength <= 60:
|
|
310
|
+
die(f"--denoise-strength must be 20..60 (afftdn noise floor in dB below full scale), got {args.denoise_strength:g}")
|
|
310
311
|
fx.append(f"afftdn=nf=-{args.denoise_strength:g}:tn=1")
|
|
311
312
|
if args.gain:
|
|
312
313
|
fx.append(f"volume={args.gain:g}dB")
|