frameproof 0.4.0__tar.gz
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.
- frameproof-0.4.0/LICENSE +21 -0
- frameproof-0.4.0/PKG-INFO +201 -0
- frameproof-0.4.0/README.md +175 -0
- frameproof-0.4.0/frameproof/__init__.py +24 -0
- frameproof-0.4.0/frameproof/__main__.py +487 -0
- frameproof-0.4.0/frameproof/analyze.py +293 -0
- frameproof-0.4.0/frameproof/assets/agents/frameproof-adversary.md +66 -0
- frameproof-0.4.0/frameproof/assets/skill/SKILL.md +171 -0
- frameproof-0.4.0/frameproof/budget.py +83 -0
- frameproof-0.4.0/frameproof/extract.py +110 -0
- frameproof-0.4.0/frameproof/fetch.py +147 -0
- frameproof-0.4.0/frameproof/index.py +300 -0
- frameproof-0.4.0/frameproof/ocr.py +126 -0
- frameproof-0.4.0/frameproof/probe.py +81 -0
- frameproof-0.4.0/frameproof/py.typed +0 -0
- frameproof-0.4.0/frameproof/report.py +107 -0
- frameproof-0.4.0/frameproof/select.py +383 -0
- frameproof-0.4.0/frameproof/transcribe.py +226 -0
- frameproof-0.4.0/frameproof/util.py +79 -0
- frameproof-0.4.0/frameproof/verify.py +302 -0
- frameproof-0.4.0/frameproof.egg-info/PKG-INFO +201 -0
- frameproof-0.4.0/frameproof.egg-info/SOURCES.txt +30 -0
- frameproof-0.4.0/frameproof.egg-info/dependency_links.txt +1 -0
- frameproof-0.4.0/frameproof.egg-info/entry_points.txt +2 -0
- frameproof-0.4.0/frameproof.egg-info/requires.txt +10 -0
- frameproof-0.4.0/frameproof.egg-info/top_level.txt +1 -0
- frameproof-0.4.0/pyproject.toml +49 -0
- frameproof-0.4.0/setup.cfg +4 -0
- frameproof-0.4.0/tests/test_budget_and_parsing.py +104 -0
- frameproof-0.4.0/tests/test_packaging.py +46 -0
- frameproof-0.4.0/tests/test_select.py +260 -0
- frameproof-0.4.0/tests/test_verify.py +161 -0
frameproof-0.4.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Edvard Grishin
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: frameproof
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: Агент смотрит видео без слепых зон и доказывает тайм-кодом, что именно он видел
|
|
5
|
+
Author: Edvard Grishin
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/edvardgrishin27/frameproof
|
|
8
|
+
Project-URL: Issues, https://github.com/edvardgrishin27/frameproof/issues
|
|
9
|
+
Keywords: video,claude-code,agent,transcript,keyframes,ffmpeg,whisper
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Topic :: Multimedia :: Video
|
|
15
|
+
Requires-Python: >=3.10
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Requires-Dist: numpy>=1.24
|
|
19
|
+
Provides-Extra: net
|
|
20
|
+
Requires-Dist: yt-dlp>=2024.1.1; extra == "net"
|
|
21
|
+
Provides-Extra: mlx
|
|
22
|
+
Requires-Dist: mlx-whisper>=0.4; extra == "mlx"
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: pytest>=7; extra == "dev"
|
|
25
|
+
Dynamic: license-file
|
|
26
|
+
|
|
27
|
+
# frameproof
|
|
28
|
+
|
|
29
|
+
**Your coding agent did not watch that video. It guessed.**
|
|
30
|
+
|
|
31
|
+
Ask Claude Code to "watch this tutorial" and it samples frames on a scene-change
|
|
32
|
+
threshold. On a screencast that threshold cannot fire. A tool may warn that coverage is
|
|
33
|
+
sparse, but it will not tell you WHERE the hole is — so the agent cannot tell "few frames"
|
|
34
|
+
from "no frames for twenty minutes straight".
|
|
35
|
+
|
|
36
|
+
Measured on a real 38-minute tutorial, the most popular tool in this niche extracted
|
|
37
|
+
**17 frames by default**, with a **20-minute 51-second gap**. `frameproof` extracted 220
|
|
38
|
+
with a **14-second** maximum gap — first command, no flags.
|
|
39
|
+
|
|
40
|
+
The full table, including their best mode where they lead on coverage, is in
|
|
41
|
+
[bench/RESULTS.md](bench/RESULTS.md). Hiding it would be less interesting.
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
pip install frameproof
|
|
45
|
+
frameproof index "https://youtube.com/watch?v=..." --ocr
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Why the threshold cannot work
|
|
49
|
+
|
|
50
|
+
ffmpeg's `scene` filter measures the **mean** delta across the whole frame. Measured on
|
|
51
|
+
ffmpeg 8.0.1 with real terminal colours (`#cccccc` on `#1e1e1e`, 640×360):
|
|
52
|
+
|
|
53
|
+
| what changed on screen | scene score | threshold 0.3 |
|
|
54
|
+
|---|---|---|
|
|
55
|
+
| one full-width line of text | 0.0579 | no |
|
|
56
|
+
| three lines | 0.149 | no |
|
|
57
|
+
| half the screen | 0.745 | yes |
|
|
58
|
+
|
|
59
|
+
Real glyphs cover 10–15 % of a line's area, so a typed command scores around **0.006 —
|
|
60
|
+
off by a factor of about 40**. Lowering the threshold does not help: what rescues a
|
|
61
|
+
screencast buries a fast-cut video under thousands of frames.
|
|
62
|
+
|
|
63
|
+
`frameproof` measures the **fraction of changed pixels per grid cell**, calibrated
|
|
64
|
+
against each cell's own baseline. A cell that moves constantly — the presenter's
|
|
65
|
+
webcam, a running timer, a cursor — is suppressed automatically. A cell that is quiet
|
|
66
|
+
most of the time and then changes is an event.
|
|
67
|
+
|
|
68
|
+
## The guarantee
|
|
69
|
+
|
|
70
|
+
**No stretch of the timeline is left without a frame for longer than `--max-gap`
|
|
71
|
+
seconds** (15 by default). When detectors stay silent, frames are placed on a grid.
|
|
72
|
+
Coverage is not a matter of picking a lucky threshold.
|
|
73
|
+
|
|
74
|
+
And when the guarantee cannot be met, the tool **says so**:
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
покрытие: 97 % — 2 участка без кадров (57 с). НЕ утверждай, что показано на экране в них.
|
|
78
|
+
БЕЗ КАДРА 25:30 – 25:59 (29 с)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Silent blindness is worse than an honest "I did not look here".
|
|
82
|
+
|
|
83
|
+
## Three commands, on purpose
|
|
84
|
+
|
|
85
|
+
| command | what it does | images |
|
|
86
|
+
|---|---|---|
|
|
87
|
+
| `index` | builds the index, prints coverage | none |
|
|
88
|
+
| `search` | searches speech **and on-screen text** | none |
|
|
89
|
+
| `frames` | returns images | yes — the only one |
|
|
90
|
+
|
|
91
|
+
If search could return pictures, the savings would vanish on the first query. A frame
|
|
92
|
+
at 1280×720 costs about 1196 visual tokens; the transcript of an hour is about 50 KB.
|
|
93
|
+
Most questions are answered without loading a single image.
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
frameproof search "openrouter" --out ~/.frameproof/hermes
|
|
97
|
+
# [9:57 / f0050] screen: ... OpenRouter • дешевле напрямую ...
|
|
98
|
+
|
|
99
|
+
frameproof frames --at 18:38 --out ~/.frameproof/hermes
|
|
100
|
+
# [18:38 / f0097] .../frames/f0097.jpg (1196 токенов)
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Two speed tiers
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
frameproof index <url> --fast # 1 second
|
|
107
|
+
frameproof index <url> # 32 seconds, frames land better
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
`--fast` takes candidates from keyframes instead of decoding the whole video.
|
|
111
|
+
Measured on a 38-minute tutorial:
|
|
112
|
+
|
|
113
|
+
| mode | frames | reliable on-screen terms | per frame | time |
|
|
114
|
+
|---|---|---|---|---|
|
|
115
|
+
| `--fast` | 231 | 672 | 2.9 | **1.1 s** |
|
|
116
|
+
| default | 225 | **789** | **3.5** | 32 s |
|
|
117
|
+
|
|
118
|
+
The fast tier returns 85 % of the information for 3 % of the time. The trade is honest:
|
|
119
|
+
frames land where the encoder put a keyframe, not where the thought on screen finished.
|
|
120
|
+
|
|
121
|
+
The frame budget scales with duration instead of being a constant: a one-minute clip
|
|
122
|
+
gets 40, a 38-minute tutorial 231, a three-hour lecture 600.
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
## A citation you can check
|
|
126
|
+
|
|
127
|
+
`[18:38 / f0097]` is not decoration. It points at a row of the index, and arithmetic checks it:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
frameproof verify answer.md --out ~/.frameproof/hermes
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
✗ [20:00 / f9999] The memory architecture diagram is on screen.
|
|
135
|
+
FAIL FRAME_NOT_FOUND: no frame f9999 in the index — the reference is invented
|
|
136
|
+
✗ [5:00 / f0097] Here he opens the router settings.
|
|
137
|
+
FAIL TIME_MISMATCH: the tag says 5:00, frame f0097 was taken at 18:38
|
|
138
|
+
? [29:31 / f0160] A list of ten skills is shown.
|
|
139
|
+
WARN NEVER_OPENED: the frame exists but was never requested —
|
|
140
|
+
the claim was made without looking
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Six checks, zero model calls: does the frame exist · does the timestamp match · does the
|
|
144
|
+
moment fall in a coverage gap · **was the frame ever served to the agent** · does the quoted
|
|
145
|
+
string appear in the frame's OCR · does it appear in nearby speech.
|
|
146
|
+
|
|
147
|
+
## A blind second look
|
|
148
|
+
|
|
149
|
+
Meaning is beyond arithmetic. For that there is a separate subagent that sees **only the
|
|
150
|
+
frame and the claim** — not the user's question, not the author's reasoning, not the rest
|
|
151
|
+
of the answer. Its job is to refute.
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
frameproof verify answer.md --out <index> --plan # tasks carrying no context at all
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
It runs **only when explicitly asked**. Refuted claims are **flagged, not hidden**: measured
|
|
158
|
+
adversarial panels raise false alarms on up to a third of correct claims, so the call stays
|
|
159
|
+
with the human.
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
## Install
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
pip install frameproof # core
|
|
166
|
+
pip install "frameproof[net]" # + yt-dlp for links
|
|
167
|
+
pip install "frameproof[mlx]" # + fast local transcription on Apple Silicon
|
|
168
|
+
|
|
169
|
+
frameproof doctor # check what is available
|
|
170
|
+
frameproof install # install the skill into Claude Code
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
npx skills add edvardgrishin27/frameproof -g # Codex, Cursor, Copilot, others
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
> We have **not** verified this outside Claude Code. The `SKILL.md` format is portable and
|
|
178
|
+
> the manifests are in place, but we will not claim support we did not test — see [CLAIMS.md](CLAIMS.md).
|
|
179
|
+
|
|
180
|
+
Requires `ffmpeg`. Everything else is optional and degrades gracefully.
|
|
181
|
+
**No API keys, ever.** Subtitles come free from `yt-dlp`; when there are none,
|
|
182
|
+
transcription runs locally.
|
|
183
|
+
|
|
184
|
+
## Use in Claude Code
|
|
185
|
+
|
|
186
|
+
After `frameproof install`, just ask: *"watch this video and tell me which command he
|
|
187
|
+
shows at 4:12"*. The skill enforces one rule the agent cannot skip:
|
|
188
|
+
|
|
189
|
+
> Never claim what was on screen without having seen a frame. Every statement about
|
|
190
|
+
> the screen carries a `[MM:SS / fNNNN]` tag so a human can check it.
|
|
191
|
+
|
|
192
|
+
## Honest limits
|
|
193
|
+
|
|
194
|
+
The full list is in [CLAIMS.md](CLAIMS.md). The short version: this tool guarantees
|
|
195
|
+
*coverage*, not that no change was ever missed; OCR is for **finding** frames, not for
|
|
196
|
+
reading code verbatim; and the benchmark is one video of the class where the gap is
|
|
197
|
+
widest.
|
|
198
|
+
|
|
199
|
+
Russian documentation: [README.ru.md](README.ru.md)
|
|
200
|
+
|
|
201
|
+
MIT
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# frameproof
|
|
2
|
+
|
|
3
|
+
**Your coding agent did not watch that video. It guessed.**
|
|
4
|
+
|
|
5
|
+
Ask Claude Code to "watch this tutorial" and it samples frames on a scene-change
|
|
6
|
+
threshold. On a screencast that threshold cannot fire. A tool may warn that coverage is
|
|
7
|
+
sparse, but it will not tell you WHERE the hole is — so the agent cannot tell "few frames"
|
|
8
|
+
from "no frames for twenty minutes straight".
|
|
9
|
+
|
|
10
|
+
Measured on a real 38-minute tutorial, the most popular tool in this niche extracted
|
|
11
|
+
**17 frames by default**, with a **20-minute 51-second gap**. `frameproof` extracted 220
|
|
12
|
+
with a **14-second** maximum gap — first command, no flags.
|
|
13
|
+
|
|
14
|
+
The full table, including their best mode where they lead on coverage, is in
|
|
15
|
+
[bench/RESULTS.md](bench/RESULTS.md). Hiding it would be less interesting.
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install frameproof
|
|
19
|
+
frameproof index "https://youtube.com/watch?v=..." --ocr
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Why the threshold cannot work
|
|
23
|
+
|
|
24
|
+
ffmpeg's `scene` filter measures the **mean** delta across the whole frame. Measured on
|
|
25
|
+
ffmpeg 8.0.1 with real terminal colours (`#cccccc` on `#1e1e1e`, 640×360):
|
|
26
|
+
|
|
27
|
+
| what changed on screen | scene score | threshold 0.3 |
|
|
28
|
+
|---|---|---|
|
|
29
|
+
| one full-width line of text | 0.0579 | no |
|
|
30
|
+
| three lines | 0.149 | no |
|
|
31
|
+
| half the screen | 0.745 | yes |
|
|
32
|
+
|
|
33
|
+
Real glyphs cover 10–15 % of a line's area, so a typed command scores around **0.006 —
|
|
34
|
+
off by a factor of about 40**. Lowering the threshold does not help: what rescues a
|
|
35
|
+
screencast buries a fast-cut video under thousands of frames.
|
|
36
|
+
|
|
37
|
+
`frameproof` measures the **fraction of changed pixels per grid cell**, calibrated
|
|
38
|
+
against each cell's own baseline. A cell that moves constantly — the presenter's
|
|
39
|
+
webcam, a running timer, a cursor — is suppressed automatically. A cell that is quiet
|
|
40
|
+
most of the time and then changes is an event.
|
|
41
|
+
|
|
42
|
+
## The guarantee
|
|
43
|
+
|
|
44
|
+
**No stretch of the timeline is left without a frame for longer than `--max-gap`
|
|
45
|
+
seconds** (15 by default). When detectors stay silent, frames are placed on a grid.
|
|
46
|
+
Coverage is not a matter of picking a lucky threshold.
|
|
47
|
+
|
|
48
|
+
And when the guarantee cannot be met, the tool **says so**:
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
покрытие: 97 % — 2 участка без кадров (57 с). НЕ утверждай, что показано на экране в них.
|
|
52
|
+
БЕЗ КАДРА 25:30 – 25:59 (29 с)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Silent blindness is worse than an honest "I did not look here".
|
|
56
|
+
|
|
57
|
+
## Three commands, on purpose
|
|
58
|
+
|
|
59
|
+
| command | what it does | images |
|
|
60
|
+
|---|---|---|
|
|
61
|
+
| `index` | builds the index, prints coverage | none |
|
|
62
|
+
| `search` | searches speech **and on-screen text** | none |
|
|
63
|
+
| `frames` | returns images | yes — the only one |
|
|
64
|
+
|
|
65
|
+
If search could return pictures, the savings would vanish on the first query. A frame
|
|
66
|
+
at 1280×720 costs about 1196 visual tokens; the transcript of an hour is about 50 KB.
|
|
67
|
+
Most questions are answered without loading a single image.
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
frameproof search "openrouter" --out ~/.frameproof/hermes
|
|
71
|
+
# [9:57 / f0050] screen: ... OpenRouter • дешевле напрямую ...
|
|
72
|
+
|
|
73
|
+
frameproof frames --at 18:38 --out ~/.frameproof/hermes
|
|
74
|
+
# [18:38 / f0097] .../frames/f0097.jpg (1196 токенов)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Two speed tiers
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
frameproof index <url> --fast # 1 second
|
|
81
|
+
frameproof index <url> # 32 seconds, frames land better
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
`--fast` takes candidates from keyframes instead of decoding the whole video.
|
|
85
|
+
Measured on a 38-minute tutorial:
|
|
86
|
+
|
|
87
|
+
| mode | frames | reliable on-screen terms | per frame | time |
|
|
88
|
+
|---|---|---|---|---|
|
|
89
|
+
| `--fast` | 231 | 672 | 2.9 | **1.1 s** |
|
|
90
|
+
| default | 225 | **789** | **3.5** | 32 s |
|
|
91
|
+
|
|
92
|
+
The fast tier returns 85 % of the information for 3 % of the time. The trade is honest:
|
|
93
|
+
frames land where the encoder put a keyframe, not where the thought on screen finished.
|
|
94
|
+
|
|
95
|
+
The frame budget scales with duration instead of being a constant: a one-minute clip
|
|
96
|
+
gets 40, a 38-minute tutorial 231, a three-hour lecture 600.
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
## A citation you can check
|
|
100
|
+
|
|
101
|
+
`[18:38 / f0097]` is not decoration. It points at a row of the index, and arithmetic checks it:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
frameproof verify answer.md --out ~/.frameproof/hermes
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
✗ [20:00 / f9999] The memory architecture diagram is on screen.
|
|
109
|
+
FAIL FRAME_NOT_FOUND: no frame f9999 in the index — the reference is invented
|
|
110
|
+
✗ [5:00 / f0097] Here he opens the router settings.
|
|
111
|
+
FAIL TIME_MISMATCH: the tag says 5:00, frame f0097 was taken at 18:38
|
|
112
|
+
? [29:31 / f0160] A list of ten skills is shown.
|
|
113
|
+
WARN NEVER_OPENED: the frame exists but was never requested —
|
|
114
|
+
the claim was made without looking
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Six checks, zero model calls: does the frame exist · does the timestamp match · does the
|
|
118
|
+
moment fall in a coverage gap · **was the frame ever served to the agent** · does the quoted
|
|
119
|
+
string appear in the frame's OCR · does it appear in nearby speech.
|
|
120
|
+
|
|
121
|
+
## A blind second look
|
|
122
|
+
|
|
123
|
+
Meaning is beyond arithmetic. For that there is a separate subagent that sees **only the
|
|
124
|
+
frame and the claim** — not the user's question, not the author's reasoning, not the rest
|
|
125
|
+
of the answer. Its job is to refute.
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
frameproof verify answer.md --out <index> --plan # tasks carrying no context at all
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
It runs **only when explicitly asked**. Refuted claims are **flagged, not hidden**: measured
|
|
132
|
+
adversarial panels raise false alarms on up to a third of correct claims, so the call stays
|
|
133
|
+
with the human.
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
## Install
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
pip install frameproof # core
|
|
140
|
+
pip install "frameproof[net]" # + yt-dlp for links
|
|
141
|
+
pip install "frameproof[mlx]" # + fast local transcription on Apple Silicon
|
|
142
|
+
|
|
143
|
+
frameproof doctor # check what is available
|
|
144
|
+
frameproof install # install the skill into Claude Code
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
npx skills add edvardgrishin27/frameproof -g # Codex, Cursor, Copilot, others
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
> We have **not** verified this outside Claude Code. The `SKILL.md` format is portable and
|
|
152
|
+
> the manifests are in place, but we will not claim support we did not test — see [CLAIMS.md](CLAIMS.md).
|
|
153
|
+
|
|
154
|
+
Requires `ffmpeg`. Everything else is optional and degrades gracefully.
|
|
155
|
+
**No API keys, ever.** Subtitles come free from `yt-dlp`; when there are none,
|
|
156
|
+
transcription runs locally.
|
|
157
|
+
|
|
158
|
+
## Use in Claude Code
|
|
159
|
+
|
|
160
|
+
After `frameproof install`, just ask: *"watch this video and tell me which command he
|
|
161
|
+
shows at 4:12"*. The skill enforces one rule the agent cannot skip:
|
|
162
|
+
|
|
163
|
+
> Never claim what was on screen without having seen a frame. Every statement about
|
|
164
|
+
> the screen carries a `[MM:SS / fNNNN]` tag so a human can check it.
|
|
165
|
+
|
|
166
|
+
## Honest limits
|
|
167
|
+
|
|
168
|
+
The full list is in [CLAIMS.md](CLAIMS.md). The short version: this tool guarantees
|
|
169
|
+
*coverage*, not that no change was ever missed; OCR is for **finding** frames, not for
|
|
170
|
+
reading code verbatim; and the benchmark is one video of the class where the gap is
|
|
171
|
+
widest.
|
|
172
|
+
|
|
173
|
+
Russian documentation: [README.ru.md](README.ru.md)
|
|
174
|
+
|
|
175
|
+
MIT
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""frameproof — агент смотрит видео и может доказать, что именно он видел.
|
|
2
|
+
|
|
3
|
+
Два обещания, которых нет у аналогов:
|
|
4
|
+
|
|
5
|
+
1. НЕТ СЛЕПЫХ ЗОН. Кадры отбираются по доле изменившихся пикселей в ячейках сетки,
|
|
6
|
+
а не по средней дельте всего кадра, плюс жёсткая страховка «ни одного промежутка
|
|
7
|
+
длиннее N секунд». Наивный `select='gt(scene,0.3)'` на скринкасте промахивается
|
|
8
|
+
примерно в 40 раз и молча пропускает целые минуты.
|
|
9
|
+
|
|
10
|
+
2. ЧЕСТНЫЙ ОТЧЁТ. Инструмент вслух говорит, какое покрытие получилось и где кадров
|
|
11
|
+
нет. В этих участках агенту запрещено утверждать, что было на экране.
|
|
12
|
+
|
|
13
|
+
3. МЕТКА ПРОВЕРЯЕМА. `[MM:SS / fNNNN]` — не оформление, а ссылка на строку индекса.
|
|
14
|
+
Механический аудит без всякой модели ловит выдуманный кадр, разъехавшийся тайм-код,
|
|
15
|
+
утверждение о кадре, который агенту не выдавали, и цитату, которой на экране нет.
|
|
16
|
+
Что механика проверить не может — отдаётся слепому субагенту: он видит только кадр
|
|
17
|
+
и утверждение, без вопроса и без чужих рассуждений.
|
|
18
|
+
|
|
19
|
+
Работает полностью офлайн: yt-dlp + ffmpeg + локальная расшифровка. Ключи не нужны.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
__version__ = "0.4.0"
|
|
23
|
+
|
|
24
|
+
__all__ = ["__version__"]
|