ffmpeg-skill 2.15.0 → 2.16.0
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 +4 -3
- package/scripts/render.py +7 -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 (`1.0`) | a key is renamed, removed or changes meaning |
|
|
24
|
-
| `skill.version` | the npm / package.json version (`2.
|
|
24
|
+
| `skill.version` | the npm / package.json version (`2.16.0`) | 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`
|
|
@@ -131,7 +131,7 @@ JSON would have been rewritten for that. The flat keys, typed per tool in `outpu
|
|
|
131
131
|
"deprecated": [{"what": "running on Python 3.9 (the requirements.python floor)", "since": "2.10.9", "replacement": "Python 3.10 or later; ...", "removed_in": "3.0.0", "where": "behaviour"},
|
|
132
132
|
{"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"}],
|
|
133
133
|
"removed": [{"what": "...", "since": "1.10.0", "replacement": "...", "removed_in": "2.0.0", "where": "cli | json | mcp | behaviour"}],
|
|
134
|
-
"skill": {"id": "ffmpeg-skill", "version": "2.
|
|
134
|
+
"skill": {"id": "ffmpeg-skill", "version": "2.16.0", "execution_mode": "local", "kind": "execution",
|
|
135
135
|
"entrypoints": {"cli": "...", "mcp": "...", "contract": "...", "doctor": "..."},
|
|
136
136
|
"not_provided": ["AI reasoning", "decisions", "production plans", "project IR", "approvals", "network access", "transcription engine"]},
|
|
137
137
|
"requirements": {"python": ">=3.9 (standard library only; 3.9 deprecated since 2.10.9, removed in 3.0.0; 3.10+ recommended)", "ffmpeg": ">=5.0 (5.x deprecated since 2.14.0, removed in 3.0.0; 6.1+ recommended)", "ffprobe": ">=5.0"},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ffmpeg-skill",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.16.0",
|
|
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
|
@@ -717,15 +717,16 @@ render.py project.json [--fast] [--dry-run] [--stop-after STAGE] [--work DIR --k
|
|
|
717
717
|
render.py project.json --cache DIR [--from STAGE] # reuse identical stages from a previous run
|
|
718
718
|
render.py plan.json [--audit-log FILE] # execute a plan written by <tool> --plan plan.json
|
|
719
719
|
render.py project.json --export-timeline edit.fcpxml|edit.edl|edit.otio # the cut for an editor, nothing rendered
|
|
720
|
-
render.py project.json --intermediate-preset medium # the stages' own encoder preset instead of
|
|
720
|
+
render.py project.json --intermediate-preset medium # the stages' own encoder preset instead of superfast
|
|
721
721
|
```
|
|
722
|
-
`--intermediate-preset` (2.15
|
|
722
|
+
`--intermediate-preset` (2.15; default `superfast` since 2.16, `veryfast` in 2.15): when the project has an export stage that
|
|
723
723
|
re-encodes (any preset but `copy`) and the run goes that far (no `--stop-after` before it), the
|
|
724
724
|
stages before it that encode with x264 or x265 (clips, fit, join, silence, captions, graphics,
|
|
725
725
|
overlays, audiogram; x265 on the HDR path) encode with this preset instead of `medium`. export.py re-encodes their output and its own
|
|
726
726
|
preset sets the delivered quality, so the earlier `medium` passes cost time the file does not
|
|
727
727
|
keep: a 30 s 1080p reels render took 41.7 s instead of 51.8 s on FFmpeg 8.0.1 (SSIM 0.997
|
|
728
|
-
between the two deliveries)
|
|
728
|
+
between the two deliveries); `superfast` (2.16) took it to 30 s from veryfast's 33 s on 8.0.1, the
|
|
729
|
+
same time on 6.1, at the same quality. `medium` restores the stages' default; `--fast` still overrides
|
|
729
730
|
everything; a stage given its own `--preset` keeps it. The result names it as
|
|
730
731
|
`intermediate_preset` (`null` when not applied).
|
|
731
732
|
`--export-timeline FILE` (2.1) writes the project's cut as an editor timeline instead of
|
package/scripts/render.py
CHANGED
|
@@ -640,7 +640,11 @@ CACHE: Dict[str, Any] = _fresh_cache()
|
|
|
640
640
|
# re-encodes their output, so their own `medium` pass bought nothing the delivery keeps. Measured
|
|
641
641
|
# on a 30 s 1080p reels render (4 cores): fit 18 s and captions 27 s of a 70 s run at `medium`;
|
|
642
642
|
# `veryfast` at the same CRF encodes in about half the time (SSIM 0.997 against `medium`) and
|
|
643
|
-
# the export, still `medium`, sets the delivered quality.
|
|
643
|
+
# the export, still `medium`, sets the delivered quality. 2.16: `superfast` (the default since): on
|
|
644
|
+
# FFmpeg 8.0.1 the same render took 30 s instead of 33 s with veryfast, SSIM against a lossless
|
|
645
|
+
# reference 0.9868 vs 0.9863 (the export decides what is kept); on 6.1 the two took the same time.
|
|
646
|
+
# `ultrafast` was faster still (26 s) but measurably worse (0.9814). `--intermediate-preset medium`
|
|
647
|
+
# restores the stages' own default.
|
|
644
648
|
_X264_STAGES = frozenset({"cut.py", "fit.py", "join.py", "silence.py", "caption.py", "graphics.py", "overlay.py", "waveform.py"})
|
|
645
649
|
INTERMEDIATE: Dict[str, Any] = {"preset": None, "applied": False}
|
|
646
650
|
|
|
@@ -1066,8 +1070,8 @@ def main() -> int:
|
|
|
1066
1070
|
help="append the audit records of this run (a refused plan, a lock taken over, ...) to FILE as JSON lines; "
|
|
1067
1071
|
"default for a refused plan: <plan>.audit.jsonl next to it. A record that cannot be written is a "
|
|
1068
1072
|
"warning, never a failure")
|
|
1069
|
-
ap.add_argument("--intermediate-preset", default="
|
|
1070
|
-
help="x264/x265 preset of the stages before an encoding export (default
|
|
1073
|
+
ap.add_argument("--intermediate-preset", default="superfast", choices=X264_PRESETS,
|
|
1074
|
+
help="x264/x265 preset of the stages before an encoding export (default superfast: the export "
|
|
1071
1075
|
"re-encodes them, and its own preset sets the delivered quality); medium = the stages' own default. "
|
|
1072
1076
|
"Not used without an export stage, with --stop-after before it, with --fast, or for a copy export")
|
|
1073
1077
|
ap.add_argument("--stop-after", choices=["clips", "join", "silence", "fit", "captions", "graphics", "overlays", "audio", "loudness", "export"], help="stop after this stage (for iterating)")
|