jevreel 0.1.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.
jevreel-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Madhav Gupta
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.
jevreel-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,350 @@
1
+ Metadata-Version: 2.4
2
+ Name: jevreel
3
+ Version: 0.1.0
4
+ Summary: Zero-embedding video intelligence: contact sheets + Jev typed decisions, as tools for any coding agent.
5
+ Keywords: video,video-understanding,jev,typesafe,mcp,agent-skills,contact-sheet,zero-embedding
6
+ Author: Madhav Gupta
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Topic :: Multimedia :: Video
17
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
18
+ Requires-Dist: fastmcp[tasks]>=4.1,<5
19
+ Requires-Dist: pillow>=12.3
20
+ Requires-Dist: platformdirs>=4.13
21
+ Requires-Dist: typer>=0.27
22
+ Requires-Dist: typesafe-sdk[zstd]>=0.7.5
23
+ Requires-Dist: jevreel[url,asr] ; extra == 'all'
24
+ Requires-Dist: faster-whisper>=1.2 ; extra == 'asr'
25
+ Requires-Dist: yt-dlp>=2026.8.19 ; extra == 'url'
26
+ Requires-Python: >=3.11
27
+ Project-URL: Homepage, https://github.com/DeepAleph/jevreel
28
+ Project-URL: Repository, https://github.com/DeepAleph/jevreel
29
+ Project-URL: Issues, https://github.com/DeepAleph/jevreel/issues
30
+ Project-URL: Changelog, https://github.com/DeepAleph/jevreel/blob/main/CHANGELOG.md
31
+ Provides-Extra: all
32
+ Provides-Extra: asr
33
+ Provides-Extra: url
34
+ Description-Content-Type: text/markdown
35
+
36
+ # jevreel
37
+
38
+ **A zero-embedding approach to video intelligence, using Jev.**
39
+
40
+ [![CI](https://github.com/DeepAleph/jevreel/actions/workflows/ci.yml/badge.svg)](https://github.com/DeepAleph/jevreel/actions/workflows/ci.yml)
41
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/DeepAleph/jevreel/blob/main/LICENSE)
42
+ ![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue.svg)
43
+
44
+ jevreel lays a video out on labelled contact sheets, one frame per second and sixty frames to an
45
+ image, and has [Jev](https://docs.typesafe.ai), TypeSafe's fast decision model, judge every sheet in
46
+ parallel. The best windows are re-checked on full frames. Your agent (Claude Code, Codex, Cursor,
47
+ Claude Desktop, anything that speaks MCP) gets back moments, times and probabilities, then looks
48
+ closer itself. No vectors are computed or stored anywhere.
49
+
50
+ <a href="https://github.com/DeepAleph/jevreel/blob/main/docs/demo/clips/intro.mp4"><img src="https://raw.githubusercontent.com/DeepAleph/jevreel/main/docs/demo/clips/intro.webp" alt="How jevreel works: a 12-minute film becomes 13 contact sheets, Jev judges them in parallel, the best windows are verified on full frames, and the agent gets timed hits" width="100%"></a>
51
+
52
+ ## See it work
53
+
54
+ Five unedited Claude Code sessions using the jevreel MCP server and skill on Blender's open movie
55
+ [*Tears of Steel*](https://mango.blender.org) (12:14, (CC) Blender Foundation,
56
+ [CC BY 3.0](https://creativecommons.org/licenses/by/3.0/)). Each clip is drawn from its
57
+ recording: the agent's tool calls, what Jev answered for every sheet and frame, the hits, the cost,
58
+ and the agent's own answer, quoted. Click a clip for the full-resolution video.
59
+
60
+ | | Asked | What happened | Jev |
61
+ | - | - | - | - |
62
+ | 1 | Is there a moment where someone drinks from a juice box? | 13 sheets screened, 6 windows verified on full frames, 2 kept: **2:28.5** (p 0.95) and 12:06.5 (0.86) | 19 requests, $0.0054 |
63
+ | 2 | When does Thom apologise to Celia, and what does he say? | Speech mode over the captions: 6:47 *"I'm sorry."* (0.85), and a blurted *"Sorry!"* at 5:02 the agent set aside | 10 requests, $0.0003 |
64
+ | 3 | Somebody reads a newspaper early on. What does the headline say? | First 5 minutes only: verified at **1:20.5** (0.94); the agent read *ROBOTICIST CREATES KILLER ROBOTS* off the frame | 8 requests, $0.0024 |
65
+ | 4 | `captain.jpg` is a character. List every scene he's in. | Search by photo: 8 moments, 6 verified at 0.86–0.97, 2 more confirmed by the agent with `zoom` | 19 requests, $0.0064 |
66
+ | 5 | Map the film: robots, guns, holograms, settings, and what kind of film. | The agent wrote its own 4-question lens, read the per-minute rows back for free, and asked one whole-film question | 14 requests, $0.0051 |
67
+
68
+ ### 1. Find a three-second moment
69
+
70
+ <a href="https://github.com/DeepAleph/jevreel/blob/main/docs/demo/clips/a-juice.mp4"><img src="https://raw.githubusercontent.com/DeepAleph/jevreel/main/docs/demo/clips/a-juice.webp" alt="Use case 1: screening 13 contact sheets for a juice box, verifying the top windows, and the agent's answer" width="100%"></a>
71
+
72
+ ### 2. Search the dialogue
73
+
74
+ <a href="https://github.com/DeepAleph/jevreel/blob/main/docs/demo/clips/b-apology.mp4"><img src="https://raw.githubusercontent.com/DeepAleph/jevreel/main/docs/demo/clips/b-apology.webp" alt="Use case 2: speech-mode search over caption lines, the picked line, and the agent's answer" width="100%"></a>
75
+
76
+ ### 3. Read what's on screen
77
+
78
+ <a href="https://github.com/DeepAleph/jevreel/blob/main/docs/demo/clips/c-newspaper.mp4"><img src="https://raw.githubusercontent.com/DeepAleph/jevreel/main/docs/demo/clips/c-newspaper.webp" alt="Use case 3: finding the newspaper in the first five minutes and the headline the agent read" width="100%"></a>
79
+
80
+ ### 4. Find a person from a photo
81
+
82
+ <a href="https://github.com/DeepAleph/jevreel/blob/main/docs/demo/clips/d-captain.mp4"><img src="https://raw.githubusercontent.com/DeepAleph/jevreel/main/docs/demo/clips/d-captain.webp" alt="Use case 4: searching by a reference photo, verified windows, and every moment on a timeline" width="100%"></a>
83
+
84
+ The reference photo is a crop of the frame at 9:18, so the 9:17 hit is its own source; the other
85
+ seven are what the search found.
86
+
87
+ ### 5. Map a whole film
88
+
89
+ <a href="https://github.com/DeepAleph/jevreel/blob/main/docs/demo/clips/e-map.mp4"><img src="https://raw.githubusercontent.com/DeepAleph/jevreel/main/docs/demo/clips/e-map.webp" alt="Use case 5: an agent-written lens, the per-minute heatmap, the whole-film question, and the agent's map" width="100%"></a>
90
+
91
+ The session starts with two failed calls, left in: a shell command the recording didn't allow, then
92
+ a wrong folder. The error names the folder relative paths resolve from, and the next call works.
93
+
94
+ ## Why a decision model instead of embeddings
95
+
96
+ Multimodal embedding models already search video well: EmbeddingGemma 2 (October 2026) puts text,
97
+ images, video frames and audio in one vector space and runs on a phone. jevreel takes a different
98
+ route to the same goal, with different trade-offs.
99
+
100
+ - **Your question, not a fixed notion of "similar".** An embedding index decides at index time what
101
+ counts as close. A decision model judges the question you ask now, and returns a probability your
102
+ code can threshold, sort and gate on.
103
+ - **Every second, cheaply.** Jev charges for input tokens only, and output is free. A contact sheet
104
+ is sent once and every question about it rides along in the same request, so jevreel screens the
105
+ whole video at one frame per second instead of a handful of keyframes.
106
+ - **Questions are nearly free, so ask many.** Lenses add your own typed questions to every minute
107
+ at almost no extra cost, then filter them as often as you like for nothing.
108
+ - **The expensive model only sees what passed.** Your agent gets the few moments that matter, as
109
+ full-resolution frames, rather than a pile of thumbnails.
110
+ - **Typed answers, not just rankings.** Yes/no with the second it happens, one of your options, or a
111
+ level on your scale, per minute or for the whole video.
112
+
113
+ Embeddings are the better fit for querying a large library over and over: once the vectors exist,
114
+ each search is a lookup that costs nothing, while every jevreel question pays Jev for the minutes it
115
+ screens (about $0.02–0.03 per hour of video). The two combine well: embeddings to shortlist
116
+ videos, jevreel to find, verify and describe the moment.
117
+
118
+ ## How it works
119
+
120
+ ```mermaid
121
+ flowchart LR
122
+ V[video file or URL] --> F["ffmpeg: 1 frame/s"]
123
+ F --> S["contact sheets<br/>60 labelled tiles, 1 minute each"]
124
+ V --> T["captions, or local<br/>speech-to-text"]
125
+ S --> J{{"screen: one Jev request<br/>per sheet, in parallel"}}
126
+ T --> J
127
+ J --> R["verify: top-ranked windows<br/>re-checked on full frames,<br/>every 0.5 s around the pick"]
128
+ R --> H["hits: time, probability,<br/>frame, nearby speech"]
129
+ H --> A["your agent: zoom, locate,<br/>read, cite 12:04"]
130
+ ```
131
+
132
+ 1. **Index.** Sample the video at 1 fps and tile the frames onto 1568 px contact sheets, each tile
133
+ labelled `T01`, `T02`, and so on. Fetch captions, or transcribe locally. Ask every sheet a fixed
134
+ set of questions once (people, on-screen text, cuts, setting, activity, a representative frame)
135
+ plus any **lenses** you add, which gives a typed timeline.
136
+ 2. **Screen.** One request per sheet: a yes/no (Noul) for "is it in this minute" plus a Choice over
137
+ tile IDs for "which second". Screen and speech are separate questions combined in code.
138
+ 3. **Verify.** The top-ranked windows (by rank, not threshold) are re-checked with one yes/no per full
139
+ frame, every half second around the pick. Screening ranks a one-second event correctly even when
140
+ it can't confirm it; verification confirms it, or throws out a false lead.
141
+ 4. **Look closer.** `zoom` re-renders full-resolution frames; `locate` puts a Box around a target in
142
+ one frame and crops it; `whole` answers one question about the entire video from a storyboard,
143
+ the timeline and the transcript.
144
+
145
+ Answers are cached: the same images and questions to the same model never cost twice.
146
+
147
+ This follows TypeSafe's own patterns. Their line-search cookbook pairs a Choice over labelled units
148
+ with a Noul for "is it there at all". Their images guide searches a large image by Choice over tiles
149
+ and looks closer only where needed. Their Box guide gates every box behind a Noul and checks its edges.
150
+
151
+ ## Quickstart
152
+
153
+ You need Python 3.11+, [FFmpeg](https://ffmpeg.org/download.html) on your PATH, and a
154
+ [TypeSafe API key](https://console.typesafe.ai).
155
+
156
+ ```bash
157
+ uv tool install "jevreel[all]"
158
+ export TYPESAFE_API_KEY=...
159
+
160
+ jevreel index talk.mp4 # prints the video id
161
+ jevreel ask talk "a slide with a bar chart" # id, id prefix, path or title all work
162
+ jevreel zoom talk 12:00 12:10 # full-resolution frames to look at
163
+ ```
164
+
165
+ `[all]` adds URL support (yt-dlp) and local speech-to-text (faster-whisper). Without them, jevreel
166
+ indexes local files and uses `.srt` or `.vtt` captions saved next to the video.
167
+
168
+ ## Lenses: your own questions on every minute
169
+
170
+ A lens is a set of typed questions asked of every sheet and kept as timeline columns. Questions can
171
+ be `noul` (yes/no, plus the second it happens), `choice` (one of your options) or `score` (levels,
172
+ lowest first).
173
+
174
+ ```toml
175
+ # examples/lenses/driving.toml
176
+ name = "driving"
177
+
178
+ [[questions]]
179
+ name = "on_bridge"
180
+ type = "noul"
181
+ ask = "Is the car driving on a bridge?"
182
+
183
+ [[questions]]
184
+ name = "weather"
185
+ type = "choice"
186
+ ask = "What is the weather mostly like?"
187
+ options = ["clear", "cloudy", "rain", "snow", "fog"]
188
+
189
+ [[questions]]
190
+ name = "traffic"
191
+ type = "score"
192
+ ask = "How much other traffic is on the road?"
193
+ levels = ["None", "Light", "Moderate", "Heavy"]
194
+ ```
195
+
196
+ ```bash
197
+ jevreel index drive.mp4 --lens driving.toml # rides in the indexing requests: almost free
198
+ jevreel lens drive driving.toml # or run it later: one request per minute of video
199
+ jevreel query drive "on_bridge > 0.7" # filter as often as you like: no requests
200
+ jevreel query drive "weather == snow and traffic >= 2"
201
+ ```
202
+
203
+ ## Use it from your agent
204
+
205
+ The MCP server exposes ten tools. The skill teaches agents the workflow: ask, look before claiming
206
+ anything, cite times.
207
+
208
+ **Claude Code**
209
+
210
+ ```bash
211
+ claude mcp add jevreel -e TYPESAFE_API_KEY=your-key -- uvx --from "jevreel[all]" jevreel mcp
212
+ ```
213
+
214
+ **Codex**
215
+
216
+ ```bash
217
+ codex mcp add jevreel --env TYPESAFE_API_KEY=your-key -- uvx --from "jevreel[all]" jevreel mcp
218
+ ```
219
+
220
+ **Claude Desktop, Cursor and other `mcpServers` clients**
221
+
222
+ ```json
223
+ {
224
+ "mcpServers": {
225
+ "jevreel": {
226
+ "command": "uvx",
227
+ "args": ["--from", "jevreel[all]", "jevreel", "mcp"],
228
+ "env": { "TYPESAFE_API_KEY": "your-key" }
229
+ }
230
+ }
231
+ }
232
+ ```
233
+
234
+ VS Code uses the same entry under `"servers"` with `"type": "stdio"`.
235
+
236
+ **The skill** (Claude Code, Codex and other agents that read Agent Skills):
237
+
238
+ ```bash
239
+ npx skills add DeepAleph/jevreel
240
+ ```
241
+
242
+ Agents without MCP can use the skill with the CLI alone; every command prints JSON.
243
+
244
+ ## Tools
245
+
246
+ | MCP tool | CLI | What it does |
247
+ | - | - | - |
248
+ | `index_video` | `jevreel index` | Sheets, transcript, typed timeline and any lenses. Runs as an MCP background task; repeat calls return the index and only run new lenses. |
249
+ | `ask_video` | `jevreel ask` | Moments matching a description: screened, verified on full frames, with times, probabilities, nearby speech and the frames themselves. `mode`: visual, speech, both. |
250
+ | `find_in_video` | `jevreel find` | Every moment the subject of a reference photo appears. |
251
+ | `locate_in_frame` | `jevreel locate` | Box and crop a target in one full-resolution frame. |
252
+ | `zoom_video` | `jevreel zoom` | Evenly spaced full-resolution frames between two times. |
253
+ | `video_transcript` | `jevreel transcript` | What is said between two times. |
254
+ | `ask_whole_video` | `jevreel whole` | One typed answer (yes/no, choice, or score) about the entire video. |
255
+ | `run_lens` | `jevreel lens` | Ask your own typed questions of every minute of an indexed video. |
256
+ | `query_timeline` | `jevreel query` | Filter the timeline (default answers and lenses). No requests. |
257
+ | `list_videos` | `jevreel list` | Videos indexed on this machine. |
258
+
259
+ `jevreel measure <video>` reports what one contact sheet costs at several grid sizes on your account.
260
+
261
+ ## Python
262
+
263
+ ```python
264
+ import asyncio
265
+
266
+ from jevreel import Reel
267
+
268
+
269
+ async def main() -> None:
270
+ async with Reel() as reel:
271
+ video = await reel.index("talk.mp4")
272
+ result = await reel.ask(video.id, "a slide with a bar chart")
273
+ for hit in result.hits:
274
+ print(hit.time, hit.probability, hit.frame)
275
+ print(reel.query(video.id, "text_on_screen > 0.8").rows)
276
+
277
+
278
+ asyncio.run(main())
279
+ ```
280
+
281
+ ## Configuration
282
+
283
+ | Variable | Default | Meaning |
284
+ | - | - | - |
285
+ | `TYPESAFE_API_KEY` | (required for Jev) | Your TypeSafe key. Indexing without a timeline, zoom, transcripts and queries work without it. |
286
+ | `JEVREEL_HOME` | your user cache folder | Where indexed videos, sheets, frames and the answer cache are kept. `jevreel home` prints it. |
287
+ | `JEVREEL_MODEL` | `jev-1.14.0` | Pinned on purpose: Box and image tiles need 1.14, and aliases move. |
288
+ | `JEVREEL_FPS` | `1` | Frames per second sampled onto sheets (up to 5). |
289
+ | `JEVREEL_TILES_PER_SHEET` | `60` | Frames per sheet. Fewer means larger tiles and more requests. |
290
+ | `JEVREEL_VERIFY_TOP` | `6` | How many top-ranked windows each ask verifies on full frames; `0` turns verification off. |
291
+ | `JEVREEL_CACHE` | `1` | Set to `0` to always ask Jev again. |
292
+ | `JEVREEL_CONCURRENCY` | `16` | Parallel Jev requests. Rate limits are per TypeSafe account. |
293
+ | `JEVREEL_ASR_MODEL` | `small` | faster-whisper model for videos without captions. |
294
+ | `JEVREEL_CAPTION_LANGUAGES` | `en,en-orig,en.*` | Caption languages to fetch for URLs, in order. |
295
+
296
+ ## What it costs
297
+
298
+ Measured on 2026-10-15 with `jev-1.14.0` at $0.042 per million input tokens, on a 10-minute 1080p video:
299
+
300
+ | | Requests | Input tokens | Cost |
301
+ | - | - | - | - |
302
+ | One full contact sheet (any grid from 4×7 to 8×14) | 1 | about 6,000 | $0.00025 |
303
+ | Indexing (11 sheets, 8 default questions each, 14 s wall clock) | 11 | 78,000 | $0.0033 |
304
+ | A lens of 5 questions, run afterwards | 11 | 84,000 | $0.0035 |
305
+ | One `ask`, screened and verified | 13–15 | 97,000–115,000 | $0.004–0.005 |
306
+ | The same `ask` again | 0 | 0 | $0 (cache) |
307
+ | `locate` (Box plus edge check) | 2 | 5,000 | $0.0002 |
308
+ | `whole` (one storyboard request) | 1 | 7,600 | $0.0003 |
309
+
310
+ One question across an hour of video comes to about $0.02–0.03. Asked at index time, lens questions
311
+ ride along with the default ones, which is where the "nearly free" comes from: an 8-question request
312
+ cost about the same as a 2-question one. TypeSafe doesn't document image token counts yet. These
313
+ figures are what the API reported. Check yours with `jevreel measure`.
314
+
315
+ ## Measured on a real video
316
+
317
+ A 10-minute 1080p gameplay capture, no speech, every result checked against the frames by hand:
318
+
319
+ | Query | Result |
320
+ | - | - |
321
+ | "the game's pause menu is open" | All three appearances, each under a second: 0:08.5, 2:19.5, 10:12.5 (p 0.99–1.00). Screening alone scored them 0.36, 0.50, 0.95. Before verification, two of the three were missed. |
322
+ | "the full-screen city map is shown" | 0:10 and 2:21, both map screens. No false hits. |
323
+ | "the car drives across a big steel truss bridge" | 2:07 and 5:05.5, both real bridge crossings. |
324
+ | Lens `driving`: `query "on_bridge > 0.7"` | Exactly the two bridge minutes, at 2:14 and 5:02. |
325
+ | Lens `driving`: `query "menu_open > 0.7"` | Exactly the three menu minutes. |
326
+ | `locate` "the location name caption" at 5:02 | Boxed and cropped; the crop reads "Fathers Bridge". |
327
+ | `whole` "What is this video mostly?" | "a driving sequence in a video game", 0.98. |
328
+
329
+ ## Limits
330
+
331
+ - **Brief events need screening to rank their window.** Verification looks every half second, but
332
+ only in the top-ranked windows (6 by default). An event that screening ranks below that is not
333
+ checked. Raise `JEVREEL_VERIFY_TOP`, or lower `JEVREEL_TILES_PER_SHEET` for larger tiles.
334
+ - **No sound beyond speech.** Audio reaches Jev only as transcript text.
335
+ - **Jev's image support is experimental.** TypeSafe calls images and Box "dreamer-ready", not
336
+ production-ready, and says limits and accuracy can change between releases.
337
+ - **Jev's real image minimum is 280 px per side.** The docs say 256, but the API rejects anything
338
+ smaller than 280 (measured 2026-10-15). jevreel pads every image itself.
339
+ - **Thresholds need tuning on your footage.** 0.5 to report and 0.7 for "strong" follow TypeSafe's
340
+ examples. They held up on the test video, which is one video.
341
+
342
+ ## Contributing
343
+
344
+ Issues and pull requests are welcome. See [CONTRIBUTING.md](https://github.com/DeepAleph/jevreel/blob/main/CONTRIBUTING.md). Coding agents should read
345
+ [AGENTS.md](https://github.com/DeepAleph/jevreel/blob/main/AGENTS.md).
346
+
347
+ ## License
348
+
349
+ [MIT](https://github.com/DeepAleph/jevreel/blob/main/LICENSE). jevreel is an independent project, not affiliated with TypeSafe AI. Jev is
350
+ TypeSafe's model and is used through its public API under TypeSafe's terms.