Skip to content

Repository files navigation

kve

Edit video by editing the transcript. Drag across words, press backspace, the video loses that moment.

A self-hosted replacement for Descript — which is per seat: $16 Hobbyist, $24 Creator, $50 Business per user per month billed annually. Five people on Business is $3,000 a year for a tool that is, underneath, ffmpeg and a transcript.

Everything runs on your machine. whisper.cpp for the transcript, ffmpeg for the cut. Only the transcript is ever sent to a model, and only when you ask it to make a judgment call.

raw.mp4 ──▶ transcript ──▶ cut by deleting words ──▶ graphics ──▶ captions ──▶ final.mp4
              whisper.cpp        the transcript IS      HyperFrames    word-level     ffmpeg
                                  the timeline          + GSAP         animation

Install

brew install ffmpeg whisper-cpp
npm install
npm run kve -- doctor

Node 20 or newer.

The editor

cd web
npm install
npm run dev        # http://localhost:4325

Point it at a video, wait for the transcript, and start deleting words.

Transcript editing drag to select, to cut, ⌘Z to undo, ⌘F to find
Fix a mishearing double-click any word — timings never move, so nothing resyncs
Remove dead air ffmpeg finds the pauses. No model, no key
Filler words, repeated takes detected and proposed, never auto-applied
"Cut this to 60 seconds" your model, working in sentences
Chapters, clip finding same
Rearrange move a passage earlier; the preview plays the new order
More than one camera cut B-roll and a second angle into the same edit
Icons, images, graphics rendered in the project's theme, previewed live over the video
Subtitles .srt and .vtt, timed to the edit rather than the tape
Audio two-pass loudness to −16 LUFS, denoise, music bed
Export a job with named steps you can watch and stop

The preview plays the edit without rendering it — removed spans are skipped live, so there is nothing between changing your mind and hearing the result.

The command line

The editor is a front-end onto a CLI that does the work, and the CLI is still there:

npm run kve -- new ~/Movies/raw.mp4 --slug myvideo
npm run kve -- roughcut plan myvideo
npm run kve -- roughcut apply myvideo
npm run kve -- graphics gen myvideo g001 --spec '{"type":"stat","value":47,"suffix":"s","label":"From 4:10 of raw tape"}'
npm run kve -- captions build myvideo
npm run kve -- export myvideo

It is also drivable by a coding agent. Open the folder with Claude Code, Kimi CLI or similar and say "start a new project for ~/Movies/raw.mp4 and do the rough cut".claude/skills/ carries the editorial judgment, and nothing in this repo calls an LLM on its own.

Both front-ends write the same edl.json and render through the same pipeline, so a project moves between them freely.

The one idea

The model never touches a frame.

It is shown a numbered list of sentences and answers with integers. Those integers are clamped, straightened, merged, converted to media time, snapped to frame boundaries, and only then handed to ffmpeg. There is nothing a model can say — including a confident hallucination — that produces a broken video. The worst case is an edit smaller than you asked for.

That is also why it works with a 7B model running locally, not just a frontier one.

Your model

Kimi by default, because api.moonshot.ai/v1 is OpenAI-compatible and its cached-input pricing suits the access pattern: the same long transcript gets re-sent to trim it, then chapter it, then pull clips. Paste a key in the app, or use the repo root .env:

MOONSHOT_API_KEY=sk-...

# or anything else that speaks the OpenAI API
LLM_BASE_URL=http://localhost:11434/v1
LLM_MODEL=qwen2.5-coder:7b

A local model needs no key, and then nothing leaves the machine at all.

What it does not do

No voice cloning, no eye-contact correction, no green screen, no screen recording. Each is a separate deep model, and leaving them out is why this exists.

Speaker labels are not built yet, so an interview currently transcribes as one voice.

Tests

npm test                 # engine
cd web && npm test       # editor

The interesting ones run against real 4K footage rather than synthetic words, because the bugs that mattered were invisible to synthetic data: whisper stretches word ends across silence, so word gaps cannot detect dead air; and a keep list reordered to open with the passage at 107s produced a timeline placing its words 71 seconds in.

Licence

MIT.

About

Edit video by editing the transcript. Self-hosted, your own model, your footage never leaves the machine.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages