Build diclip
KINDAreplaces $6/mosaves $72/yrback to the verdict
A personal video clipper whose hard problems are producing word-level timings accurate enough to cut on, making the cut land exactly where the transcript said it would, and rendering captions and framing without pretending to do the face tracking that the paid product actually does.
Before step 1
Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.
- installfree
Why Runs the local application and the render queue.
Get it python.org, or your version manager. open ↗
Verify
python3 --version prints 3.12 or higher - installfree
Why Every cut, caption burn and framing operation is an FFmpeg invocation, and the seeking behaviour you depend on is documented there.
Get it Your package manager, or a static build from the project. open ↗
Verify
ffmpeg -version prints a version and the probe tool is on the path - installfree, but the model download is large
Why Word timings are what the cuts are computed from, so a model that only returns sentences is not usable here.
Get it Install the library and download a model size your machine can run.
Verify
A one minute fixture returns words with start and end times - have readyfree if you have the space
Why A long recording plus its renders and intermediates is the constraint that ends most sessions, and it fails in a confusing way.
Get it Point the project directory at a volume with room to spare and set the threshold below it.
Verify
The application reports free space and refuses below the threshold - API keypay per token; a long transcript is a few pence
Why Only the ranking step uses it, and the build is designed to be useful without it.
Get it Any provider, with a spend limit set in their console.
Verify
A ranked candidate list arrives with the source recorded as model
Data model
Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.
- projects(id, source_path, source_sha256, duration_ms, imported_at, transcript_state, render_state) - words(project_id, ordinal, text, start_ms, end_ms, speaker, confidence) · the unit everything else is built from - segments(project_id, ordinal, start_ms, end_ms, speaker, text) · sentences assembled from words, never from the model's own punctuation guesses alone - candidates(id, project_id, start_ms, end_ms, hook_text, score, reason, source, state) · source is model or heuristic, state is pending, accepted or rejected - renders(id, candidate_id, aspect, out_path, started_at, finished_at, ffmpeg_args, actual_start_ms, actual_duration_ms, failure) - captions(render_id, ordinal, start_ms, end_ms, text, speaker) · grouped for reading, not one word per frame - actual_start_ms is measured from the produced file, not copied from the request. The gap between requested and actual is the number this build exists to keep at zero.
Environment variables
These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.
| Variable | Needed | Example | Where the value comes from |
|---|---|---|---|
PROJECT_DIR | required | ~/clips/projects | Project JSON and transcripts. The part worth backing up. |
RENDER_DIR | required | ~/clips/exports | Finished clips. Regenerable, so back it up last. |
MIN_FREE_GB | required | 10 | Renders refuse to start below this. It is the cheapest error message in the build. |
CLIP_MIN_SECONDS | required | 30 | Lower bound for a candidate. |
CLIP_MAX_SECONDS | required | 90 | Upper bound for a candidate. |
RANKER_API_KEYsecret | optional | sk-...redacted | Optional. Absent means the heuristic ranker runs. |
CUT_TOLERANCE_FRAMES | required | 1 | A render whose measured start drifts beyond this fails rather than shipping. |
The build, in order
Import and transcribe, without touching the source
A long file becomes words with timings, and the original is never modified or moved.
A sentence boundary is the wrong resolution for a cut point.
Files
src/transcribe/words.pytests/test_segments.pyThe recording is the one file you cannot regenerate.
Files
src/project/import.pyAn unreadable file should fail in a second, not in an hour.
Files
src/media/probe.py
done when · tick each as it passeswatch out- Storing only sentence timings because they are what the interface shows means every later cut is quantised to a sentence boundary, and the clip that needed to start three words earlier cannot. Store words, derive sentences, and keep the word table as the thing cuts are computed from.
Candidates with a reason you can argue with
Every proposed clip carries a hook line, a score and a stated reason, and the tool works with no model key.
The tool has to work before anyone pays for a token.
Files
src/rank/heuristic.pytests/test_heuristic.pyThe model reads text; the word table knows the time.
Files
src/rank/locate.pyA cut inside a word is audible and unfixable later.
Files
src/rank/snap.py
done when · tick each as it passeswatch out- Letting the model return timestamps directly gives you cut points that are plausible rather than real, because the model is reading text and inventing a time, and the clip then starts mid-word. Have the model return quoted text spans, locate those spans in the word table, and take the timings from the words.
Cuts that land where you asked
A rendered clip starts and ends within a frame of the requested times, and the build proves it.
Argument order is the difference between correct and nearly.
Files
docs/ffmpeg-seeking.mdsrc/render/cut.pyThe only trustworthy timing is the one measured afterwards.
Files
src/render/verify.pytests/test_cut_accuracy.pyEvery strange clip is explained by its own command line.
Files
src/render/record.py
done when · tick each as it passeswatch out- Cutting with a stream copy because it is fast produces clips that begin at the previous keyframe, so a thirty second clip arrives with two seconds of the wrong sentence in front and the start you carefully snapped to a word is gone. Re-encode the cut, or accept keyframe-aligned boundaries explicitly, and in either case probe the output and compare its actual start and duration against what you asked for.
Captions and framing, without pretending to track faces
Burned captions are readable and correctly timed, and the vertical framing is honest about what it is doing.
A fixed word count breaks lines in the wrong places.
Files
src/captions/group.pytests/test_caption_grouping.pyDiscovering the crop after a five minute render is the annoyance.
Files
src/render/preview.pyThe paid product does the other thing and this one does not.
Files
src/web/templates/render.html
done when · tick each as it passeswatch out- Grouping captions by a fixed word count produces lines that break mid-phrase and change at the wrong moment, which reads worse than no captions at all, and it is the first thing a viewer notices. Group by pause and reading speed with a maximum line length, and check the result against a clip where somebody speaks quickly.
Disk, batches and failures you can readproduct builder
A long session does not fill the disk, a batch that fails halfway is resumable, and every failure says what went wrong.
A full disk masquerades as a codec error.
Files
src/render/space.pyThe success path is not where the leftovers come from.
Files
src/render/queue.pytests/test_cleanup.pyUsers need the reason; you need the arguments.
Files
src/web/errors.py
done when · tick each as it passeswatch out- Letting a batch write intermediates until the disk is full produces a failure that looks like a video codec problem and takes an evening to diagnose, and by then the partial files are still there. Check free space before each render, refuse with a clear message, and delete intermediates in a finally block rather than on the success path.
That is the whole plan for diclip. What it deliberately does not cover is below · check the gaps before you call it a replacement.
- Face-aware reframing and speaker tracking.
- A timeline editor with tracks and effects.
- Downloading source video from platforms.
- Cloud rendering.
- face-aware vertical reframing with seat tracking
- full in-browser timeline editor with scenes, tracks, and effects
- container-scale render pipeline and yt-dlp import
- credit-based capacity model and priority processing
- ready-to-post hooks and confidence scoring polished for clips
- A per-project accuracy report of requested against measured cut points, which is the only quality number this build has
- Caption style presets stored per project, so a series of clips looks like a series
- A second pass that trims leading silence using the word table, which costs nothing and improves most clips
Need the files? The project pack on the verdict page hands your agent the whole brief · more audio & video.