Repository navigation
0.23.0: video-clipping summary template + clips.json cut list - #35
Conversation
|
Related: pretyflaco/vezir#19 (needs this release first), pretyflaco/vezir-android#5. |
…n-finite numbers Addresses the review of #35: - use SummaryConfig.template (arg > MILLET_SUMMARY_TEMPLATE, lowercased) for the artifact name and the clips decision, in both the initial summary and label --apply-json regeneration - write_clips_doc returns the document; the whole clip step is inside the best-effort guard, so it can never fail a saved summary - reject non-finite timestamps/scores, sanitize echoed model values, serialize with allow_nan=False - tests: env-configured template (both names), case normalization, initial-summary integration, failure isolation with/without preset, additional-language coexistence, non-finite inputs, defensive branches
|
Review addressed in 77e5ca1 (a new commit; the reviewed head c74bec8 is unchanged). 1. Medium: an environment-configured template wrote no
2. Low: reading the clips file back could fail a saved summary. Fixed.
3. Low: non-finite numbers broke the JSON contract. Fixed.
Coverage. Changed-line and branch coverage was measured locally with Verification (local, on 77e5ca1): Still unverified independently: the live Tinfoil run. It was author-run on c74bec8 and these fixes don't touch the prompt or the snapping. Noted, not changed: |
A 400-digit JSON integer (or a string timestamp with a huge hour field) made float()/math.isfinite raise OverflowError and aborted build_clips. parse_timestamp and _coerce_score now return None on overflow (and on Python 3.11+'s int_max_str_digits ValueError); _json_safe applies isfinite to floats only and echoes ints that fit in 64 bits, null otherwise.
|
Re-review addressed in 30fcfbe. Low: arbitrarily large JSON integers. Fixed.
Tests (
Every test output is parsed strictly, rejecting any non-standard constant. Verification (author-run, local, on 30fcfbe):
Remote CI: green on 3.10, 3.11 and 3.12. Still unverified: the live Tinfoil run on the current head. The prompt and the snapping logic are unchanged since c74bec8. |
Adds a third summary template,
video-clipping. The model reads a video's transcript and proposes stand-alone clips in two kinds, short (15-60 s) and long (1-3 min). millet turns that list into<base>.clips.json, a cut list an agent can feed to ffmpeg.Part of a three-repo change. Release order: this PR → vezir → vezir-android (vezir's floor becomes
millet-pipeline>=0.23.0).What's in it
millet/prompts/summarize_video_clipping_{system,user}.md):## Overview/## Short Clips/## Long Clips.clips: [{kind, start, end, title, hook, reason, score, tags}].millet/clips.py(stdlib only, no LLM). The LLM's timestamps are second-granular and sometimes mis-copied, so they're treated as cues.build_clips:droppedwith a reason. A broken JSON contract givesclips: []pluserror, so a consumer can tell "nothing worth clipping" from "the model failed".<base>.clips.json(.clips.<lang>.jsonfor a language-override retry).label --apply-jsonsummary regeneration.id,start_s/end_s/duration_s,start_ts/end_ts,segments,speakers, the verbatimtext,wordsrebased to the clip start (for captions), andffmpeg_args(a frame-accurate re-encode with{input}/{output}placeholders).duration, so vezir's duration probe can't mistake the file for the transcript.Fixes along the way
_find_session_filesnow skips.clips.and.meta.JSONs when looking for the transcript.<base>.clips.jsonsorts before<base>.json, and template.meta.jsonsidecars had the same latent problem. It only showed up when the directory name differed from the basename.syncpushes the cut list asclips[.<lang>].json. Before this, it would have claimedtranscript.json.Verification
tests/test_clips.py: 43 tests covering prompt wiring, timestamp parsing, every snapping and drop path, writing, relabel,apply_labelsintegration, the transcript-glob regression, and sync naming. Added to the CI subset.test_summary_template.py: 448 passed.ruff checkis clean.deepseek-v4-1-flash, Tinfoil TEE) with a real 30-minute recording: valid JSON, 11 clips (8 short / 3 long), 0 dropped, every boundary snapped. The first draft treated the 15/8 ceiling as a target and returned exactly 15/8. The prompt now scales the count to the video's length.Worth a reviewer's eye
_snap.ffmpeg_args. Stream copy would cut on keyframes.