CLI video editors for product demos
A product demo is an unusual editing job. It is short, it is mostly screen recording, it gets remade every time the UI changes, and the person making it is a developer who would rather write it down than drag it around. That combination is what makes a command-line workflow worth the setup: the edit becomes a script in the repository, and regenerating it after a redesign costs a rerun rather than an afternoon.
What a demo edit has to do
Before comparing tools, it is worth being precise about the jobs, because they are not equally hard and the honest answer differs per job. A demo edit is some subset of these eight.
- Trim. Cut the fumbling at the start and the stop at the end. Solved, and solved by ffmpeg in one line.
- Remove or compress dead time. Page loads, typing, the spinner. The largest single improvement to most demos and the one people skip.
- Jump cuts. Cutting between moments without the joins looking like errors. Needs a visual device, usually a punch-in.
- Captions. Burned in, because demos play muted almost everywhere.
- Narration. Recorded or synthesised, mixed over the recording with its own audio ducked.
- Music. A bed under the narration, low enough to be unnoticed and gone before the end.
- Aspect and framing. A 16:9 cut for the site, a separate vertical cut if you post to a feed.
- Compress and deliver. An MP4 small enough to autoplay, and a GIF when a README needs one.
Seven of those eight are mechanical. The jump-cut one is partly taste. And the job that is not on the list at all, deciding which thirty seconds of your product are worth showing, is the one that determines whether the demo works.
ffmpeg on its own
Every tool below is ffmpeg underneath, so the real question is how much abstraction you want over it. For a single operation the answer is usually none. Installing a dependency to trim a clip is a worse trade than remembering one command.
# trim, no re-encode
ffmpeg -ss 00:00:04 -to 00:01:12 -i raw.mp4 -c copy demo.mp4
# find the dead air, then cut against the reported ranges
ffmpeg -i demo.mp4 -af silencedetect=noise=-30dB:d=0.8 -f null - 2>&1 | grep silence_
# speed the whole thing up 1.5x, video and audio together
ffmpeg -i demo.mp4 -filter_complex "[0:v]setpts=PTS/1.5[v];[0:a]atempo=1.5[a]" -map "[v]" -map "[a]" faster.mp4
# vertical cut, centre crop then pad
ffmpeg -i demo.mp4 -vf "crop=ih*9/16:ih,scale=1080:1920" -c:a copy vertical.mp4
# README gif, two passes so the palette is generated from the clip
ffmpeg -i demo.mp4 -vf "fps=12,scale=720:-1:flags=lanczos,palettegen" palette.png
ffmpeg -i demo.mp4 -i palette.png -lavfi "fps=12,scale=720:-1:flags=lanczos[x];[x][1:v]paletteuse" demo.gifWhere this stops being pleasant is composition. One filter is readable. A dozen clips with overlays, a ducked voiceover and a music bed is a filtergraph several hundred characters long that you will not be able to modify in a month, and neither will anyone reviewing it. The failure mode is not that ffmpeg cannot do it. It is that the edit stops being legible, so nobody changes it, so the demo goes stale.
Declarative tools
The editly class of tool answers exactly that problem. You describe the finished video as a config of clips, layers and transitions, and the tool builds the ffmpeg invocation. The edit becomes a file you can diff, review and regenerate, which is the property that makes a demo maintainable rather than a one-off.
The trade is a ceiling. A config expresses what its schema expresses, and the first thing you want that it does not cover sends you back to raw ffmpeg for that step, which means your pipeline is now two tools. Several of these projects are also lightly maintained, and a video tool pinned to an old ffmpeg or an old Node is a build that breaks on a machine you did not test. Check the commit history before you build a release process on one.
The thinner wrappers, the various video-cli packages, sit between the two: friendlier flags for common operations, no project model. They save you looking up filter syntax and nothing more, which is a real but small benefit. If your demo is three operations long, that is probably the right size of tool.
Then there is the headless-browser class, Remotion and its relatives, which render video from React components. For an animated explainer built from data this is genuinely the best option available. For a demo that is mostly a recording of your actual product it is the wrong shape, because your source material is a video file, not a component tree, and you spend the whole time fighting that.
The two jobs no command-line tool does for you
First, the edit decisions. Which feature leads, how long before the viewer sees something work, what to leave out. Tools that pick highlights automatically are reading a transcript or a set of frames and guessing; useful as a first pass on a long recording, not a substitute for knowing which part of your product is the point.
Second, safe zones. Where should captions sit in a vertical demo? In the middle band of the frame. TikTok, Reels and Shorts each draw their own interface over the bottom of the video and account chrome near the top, so captions at the conventional bottom position are partly covered by the like button and the caption box. No command-line tool knows where those overlays fall, so this is a setting you choose rather than something a flag detects. Treat any tool that claims to handle it automatically with suspicion, and check the output in the app you are posting to.
What runs locally and what does not
Does a command-line video tool upload my recording? It depends entirely on which step you run, and the honest answer is that most tools mix local and hosted work without saying which is which. Trimming, cutting, captions burned from a local transcript and compression are all local ffmpeg. Anything that describes your footage, writes a script from it or picks highlights is sending frames or a transcript to a hosted model. Check which of your steps crosses that line before you demo something under NDA.
Text-to-speech deserves the same question and rarely gets it. Several widely used free engines are free because they are a hosted service with no key, which means your narration script leaves the machine even though nothing was installed and nothing asked you to sign in. Local neural voices exist and are good, and they cost a model download. Neither is wrong; knowing which one you are running is the point.
How Vidlet does it
Vidlet is a CLI built for this specific workflow, so it is one command per job rather than a filtergraph, and a project file when the edit needs composition.
npm i -g @spark-apps/vidlet
vidlet jumpcut raw.mp4 # cut silence, punch-in zoom on each cut
vidlet removesilence raw.mp4 # cut the dead air only
vidlet speedup raw.mp4 # faster, pitch preserved
vidlet cleanvoice raw.mp4 # neural denoise on a real mic take
vidlet caption demo.mp4 # local transcribe, burn styled captions
vidlet voiceover script.txt --video demo.mp4 # narrate, auto-duck
vidlet compress demo.mp4
vidlet togif demo.mp4
vidlet render demo.vidlet # compose a multi-clip projectMapped onto the eight jobs above: dead time, jump cuts, captions, narration, compression and GIF delivery each have a command. render takes a .vidlet project file of clips, overlays, audio and subtitles, which is the declarative answer to the composition problem, and uses NVENC when a card is present. There is also an MCP server in the same package, so an assistant can drive the toolkit rather than a person typing the commands.
What it does not have, since this page is about choosing honestly. There is no standalone trim command and no music command in the CLI: both exist as MCP tools and as project fields, so from a shell you trim with ffmpeg and add a music bed through the project file or the MCP server. Captions are English only, because the three bundled whisper models are all English variants and the language is pinned in the call. The prebuilt whisper binary is Linux x64 and arm64, so Windows means WSL and macOS means building whisper.cpp yourself. The free tier meters MCP calls per day, and the CLI itself is ungated and needs no account.
On the local question, applied to itself. Captions, jump cuts, silence removal, speed, compression, GIF and render are local ffmpeg and whisper.cpp, and your footage is not uploaded. Three paths do leave the machine and all three are opt-in, behind your own API key or an explicit consent flow. vidlet short sends the transcript text to a hosted model to pick highlights. vidlet demo goes further and sends up to five downscaled keyframes as well, so on that one command your footage does leave the machine, which matters if the recording shows real customer data. The default voiceover engine is a hosted neural voice, so the narration text goes out unless you use the local cloning engines. Publishing to YouTube is a separate command behind Google consent. Nothing is sent by a command you did not run.
For the captions half of this in detail, including the raw ffmpeg commands and their traps, see burning captions in from the command line. For the whole recording-to-demo sequence see turning a screen recording into a demo video. Web app tiers are on the pricing page.
FAQ
Can you edit a product demo video entirely from the command line?
Yes, for everything mechanical: trimming, concatenating, removing silence, speeding up dead time, burning captions, mixing narration and music, cropping to a vertical aspect and compressing. What the command line does not do is decide what to show and in what order. That judgement is the actual work of a demo, and no flag replaces it.
Is ffmpeg enough on its own for demo videos?
For single operations, yes, and reaching for a wrapper to do one trim is the wrong trade. Where ffmpeg alone becomes painful is composition: once an edit has a dozen clips, overlays, a ducked voiceover and a music bed, you are hand-writing a filtergraph that nobody including you will be able to change next month. That is where a declarative project file earns its place.
What does editly do that raw ffmpeg does not?
It lets you describe the finished video as a JSON or JavaScript config of clips, transitions and layers, then builds the ffmpeg invocation for you. The win is that the edit becomes a readable file you can diff and regenerate, rather than a shell command. The cost is another dependency and a ceiling: anything the config cannot express you drop back to ffmpeg for anyway.
How do I remove silence and dead time from a screen recording?
ffmpeg's silencedetect filter reports the silent ranges to stderr, and you cut and concatenate against those timestamps. For a demo the better instinct is usually to speed dead time up rather than cut it out, because a hard cut over a UI that is still loading reads as a glitch, whereas a four times speed ramp reads as deliberate.
What aspect ratio should a product demo be?
16:9 for a landing page, a README or a docs embed, which is where a demo earns its keep. Produce 9:16 only when you are posting to a vertical feed, and treat it as a separate cut rather than a crop, because a centre crop of a desktop UI throws away the half of the screen the cursor is usually in.
Do I need a microphone to narrate a product demo?
No. Text-to-speech is good enough for a product walkthrough now, and a script you can edit is worth more than a take you have to re-record. Write the narration as text, generate the audio, and mix it over the video with the recording's own audio ducked underneath. If you do record a real voice, denoise it before anything else.
Where should captions sit in a vertical demo?
In the middle band of the frame. TikTok, Reels and Shorts each draw their own interface over the bottom of the video and account chrome near the top, so captions at the conventional bottom position are partly covered by the like button and the caption box. No command-line tool knows where those overlays fall, so this is a setting you choose rather than something a flag detects.
Can a CLI video tool run in CI?
Yes, and a demo that regenerates from a checked-in script is the main reason to use one. Two things break it in practice: fonts, because a minimal container image often ships none and libass silently substitutes rather than failing, and any step that calls a hosted model, which needs a key in the runner and turns a deterministic build into a network-dependent one.
Does a command-line video tool upload my recording?
It depends entirely on which step you run, and the honest answer is that most tools mix local and hosted work without saying which is which. Trimming, cutting, captions burned from a local transcript and compression are all local ffmpeg. Anything that describes your footage, writes a script from it or picks highlights is sending frames or a transcript to a hosted model. Check which of your steps crosses that line before you demo something under NDA.