Inspiration

I record myself a lot. YouTube videos, presentations, hackathon submissions like this one. And the recording is never what takes forever. It's sitting there afterwards scrolling through footage trying to figure out which of my four attempts at the same sentence was the good one.

Every editor removes filler words now. That was never what ate my afternoon. The restarts were.

What it does

Record in the browser or drop in a file, and OneTake hands back the version you meant to record. It cuts four things: retakes (lines you said, didn't like, and said again), stutters, filler words, and dead air.

Then you fix whatever it got wrong by typing at it.

Everything runs on your machine. No API keys, nothing uploads anywhere.

How I built it

  • Frontend: plain HTML, CSS, JS. MediaRecorder captures video, chunks stream to the server over a WebSocket while you're still talking, so the file is whole the second you hit stop.
  • Backend: FastAPI. Analyzing and rendering are separate endpoints on purpose.
  • Speech to text: faster-whisper, local, with word-level timestamps.
  • Detection: difflib sequence matching for retakes, prefix matching for stutters, RMS energy for silence.
  • Rendering: ffmpeg filter_complex with trim and concat for frame-accurate cuts, plus a stream-copy path for fast previews and CMX3600 edit list export.

There's no LLM in this. Once you have timestamped words, a retake is string similarity and finding the part about bananas is a text search. Sending that to a model would mean an API key, a few seconds of latency, and a failure mode where a bad response leaves you with no video.

Challenges I ran into

Whisper deletes the exact thing I was trying to detect. It's trained on clean written transcripts, so it silently drops disfluencies. I'd say "I, um, built this" and get back "I built this." You can't cut a word that was never transcribed. The fix was priming it with an initial_prompt full of deliberate stammering and passing suppress_tokens=[], so it starts expecting more of the same and writes them down.

Cutting every pause made it sound inhuman. My first version closed gaps to zero and the result was a shotgun of syllables with no room to breathe. Every cut now leaves 200ms behind. That one constant is most of the difference between sounding edited and sounding broken.

Every single cut clicked. Splicing raw audio lands mid-waveform almost every time and you hear it on every edit. An 8ms fade on both ends of every segment fixed it. Not in any tutorial I found.

Silence isn't a fixed number. A treated room and a laptop mic in a kitchen aren't close in dB. A hardcoded threshold worked in one and failed completely in the other. The noise floor is now measured from the 20th percentile of each recording's own energy.

Accomplishments that I'm proud of

Retake detection working on real footage. It's the feature that actually saves the hour and I haven't seen another tool do it.

Also the feedback loop being instant. Transcription is cached, so typing "keep the ums" only re-runs the detectors, which takes milliseconds. The expensive step never happens twice. That's the only reason editing by description feels like undo instead of a second render.

What I learned

  • WebSockets and streaming uploads
  • ffmpeg filter graphs, and why they have to be written to a file once there are enough segments
  • ASR models make editorial decisions about your audio and you have to fight them
  • Audio splicing is mostly about the parts you leave in

What's next for OneTake

  • Sentence embeddings so "remove the part about fruit" finds "bananas"
  • Multiple speakers
  • Subtitles burned from the transcript that already exists

Built With

Share this project:

Updates

Submission history