Show HN: fftool – A Terminal UI for FFmpeg – Shows Command Before It Runs

2026-03-1310:084133bensantora.com

fftool is a terminal UI for ffmpeg written in Go. It wraps 27 common operations across video, audio, image, and generative categories into a navigable menu — and shows you the exact ffmpeg command…

← Posts

ffmpeg is one of the most capable pieces of software on Linux. It can cut, convert, transcode, normalize, stabilize, resize, concatenate, and generate media from scratch. It can also be genuinely hostile to use. The flag ordering matters. The argument syntax is non-obvious. Two-pass workflows require you to chain invocations manually. And if you don’t use it daily, you’re looking things up every time.

fftool solves that without hiding ffmpeg. It’s a terminal UI written in Go — a navigable menu that wraps the common operations and shows you the actual command it’s going to run before it runs it. You pick the operation, fill in the fields, and see the ffmpeg invocation on a confirm screen. Execute it or go back and adjust. Either way, you’re reading real ffmpeg commands, not abstractions.

What Operations Does fftool Cover?

fftool organizes operations into five categories:

Video — Trim, Convert, Resize, Extract Audio, Merge A/V, Concat, Speed, Reverse, Crop, Stabilize (10 operations)

Audio — Convert, Extract, Sine tone, Noise, Normalize, Trim, Mix (7 operations)

Image — Image to Video, Image Sequence to Video, Extract Frame (3 operations)

Generative — Mandelbrot, Test Source, SMPTE Bars, Conway’s Life, Cellular Automaton, Sine Wave, Noise Source (7 operations)

Info / Probe — ffprobe wrapper with formatted output (1 operation)

The Generative category is worth knowing about. Most people don’t realize ffmpeg can produce test patterns, fractal animations, and signal sources entirely from internal filters — no input file needed. fftool surfaces these. They’re useful for testing pipelines, generating placeholders, or just seeing what ffmpeg can do.

What Happens Before fftool Runs a Command?

This is the design decision that makes fftool different from a typical GUI wrapper.

Every operation goes through a confirm screen. Before anything executes, fftool renders the full ffmpeg command with all flags and arguments, formatted with line continuations:

ffmpeg \
  -i input.mp4 \
  -ss 00:01:30 \
  -to 00:02:45 \
  -c copy \
  output.mp4

You can review it, go back to adjust the inputs, or confirm and run. The command isn’t generated behind the scenes and quietly executed — it’s shown to you first. Over time, you stop needing the menus for the operations you use most. That’s intentional.

How Does fftool Handle Multi-Pass Operations?

Some ffmpeg workflows require more than one invocation. fftool handles these transparently.

Stabilize runs two passes: the first analyzes motion and writes a vectors file, the second applies the correction. You fill in one form; fftool runs both commands in sequence.

Normalize is a two-phase loudness operation: the first pass runs ffprobe to measure integrated loudness, true peak, and LRA; the second pass encodes with the measured values substituted in. fftool parses the JSON output from pass one and builds the pass two command automatically.

Extract Audio uses a fallback strategy: it tries the primary codec first, and if that fails falls back to a second invocation. You don’t manage any of this.

The confirm screen shows all passes before execution starts, so you can see the full sequence.

How Does fftool Show Progress?

During encoding, fftool parses ffmpeg’s stderr in real time and displays a live progress line: frame count, FPS, current time position, bitrate, and speed. The UI uses bubbletea and lipgloss for rendering — the progress updates in place rather than scrolling.

When the job finishes, fftool shows a result screen with the exit status and any relevant output. From there you can return to the form to run again with different settings, or go back to the main menu.

Why Go for a Tool Like This?

ffmpeg itself is C. Most existing frontends for it are Python scripts, shell wrappers, or Electron apps. Go gives you a single compiled binary, fast startup, and straightforward concurrency for reading stdout and stderr simultaneously without blocking. The TUI state machine — menus, forms, confirm, run, result — maps cleanly to Go’s type system. Adding a new operation means implementing one interface and registering the preset; nothing else touches.

The binary is self-contained — no runtime, no virtualenv, no dependency manager. It works wherever Go’s output works.

How Does fftool Relate to newtop and netsock?

fftool is part of the same philosophy as newtop and netsock — terminal-native Go tools that do one thing well and stay out of the way. newtop and netsock are systems tools that read the kernel directly. fftool is a different domain — media processing — but the same approach: readable Go, minimal surface area, works in a terminal, no GUI required.

If you spend time on Linux doing any kind of media work, ffmpeg is probably already on your machine. fftool makes it navigable.

The binary and full operation reference are on the fftool tools page.

How Do You Build fftool from Source?

fftool is written in Go and builds to a single static binary. You need Go 1.21 or later.

Download the source: fftool-source.tar.gz | fftool-source.zip

Dependencies:

github.com/charmbracelet/bubbletea v0.26.6
github.com/charmbracelet/bubbles v0.18.0
github.com/charmbracelet/lipgloss v0.11.0

Package structure:

fftool/
  main.go
  model.go
  ffmpeg.go
  progress.go
  ui/
    menu.go, form.go, confirm.go, run.go, result.go, styles.go, clipboard.go
  presets/
    preset.go
    video/    audio/    image/    generative/    info/

Each operation in presets/ implements a single interface defined in preset.go. Adding a new operation means writing one file and registering it — nothing else changes.

go.mod:

module bensantora.com/fftool

go 1.21

Build:

go mod tidy
go build -o fftool .

The binary has no runtime dependencies beyond ffmpeg and ffprobe on PATH.

FAQ

Q: What is fftool? A terminal UI for ffmpeg written in Go. It wraps 27 common video, audio, image, and generative operations in a navigable menu, shows you the ffmpeg command before executing, and handles multi-pass workflows like stabilization and loudness normalization automatically.

Q: Does fftool replace ffmpeg? No. It wraps it. ffmpeg does all the actual work; fftool builds the command, shows it to you, and runs it. You can copy any command off the confirm screen and run it directly in your shell.

Q: What ffmpeg operations does fftool support? Trim, convert, resize, extract audio, merge audio/video, concatenate, change speed, reverse, crop, and stabilize for video. Convert, extract, generate tones and noise, normalize, trim, and mix for audio. Image-to-video, image sequence, and frame extraction for images. Seven generative sources including Mandelbrot and Conway’s Life. ffprobe for inspection.

Q: What is the Generative category? ffmpeg includes internal filter sources that generate video without any input file — test patterns, signal sources, fractals, cellular automata. fftool exposes these under the Generative menu. Most ffmpeg users have never encountered them.

Q: Does fftool work with any ffmpeg version? It detects whatever version is on your PATH at startup. Operations use standard flags available in ffmpeg 4.x and later. The version string shows in the UI footer.

Q: Does fftool require root? No. It runs ffmpeg and ffprobe as the current user.

Tested on Debian/CrunchBang++. Requires ffmpeg with ffprobe on PATH. Linux only.


Read the original article

Comments

  • By mr_mitm 2026-03-1311:484 reply

    Am I blind or is there no link to the source? I get that running code from any old repo on github has become normalized, but running random binaries is pushing it. Also, I think when advertising a TUI, you should include an asciinema video (or comparable).

    • By taskset 2026-03-1312:162 reply

      I no longer use GitHub for original projects. Source for fftool isn't public yet but I understand the concern — running an unaudited binary is a real ask. My site leans toward educational, so that people might consider building the tool from the instructions in the article. I'll probably post the source on the site as a zip or tarball at some point so people can more easily build it. The asciinema suggestion is a good one — I'll look into it.

      • By lionkor 2026-03-1312:291 reply

        Weird, I swear the binary debug info says "github.com/bensantora-tech/fftool/main.go", so its just not public? Why?

        • By taskset 2026-03-1312:351 reply

          Right, I missed that — the Go module path in go.mod references GitHub by convention even though the repo isn't there (it's embedded in the binary's debug info). I'll change the module path to something on my own domain. Thanks for spotting that.

          • By lionkor 2026-03-1312:37

            Yeah, I thought about it and remembered that Go assumes GitHub by default for some dumb reason!

      • By mr_mitm 2026-03-1314:551 reply

        I never said you should publish to github. You can put it up on your own site, at least as a tarball. Even better: cgit or stagit

        • By taskset 2026-03-1314:591 reply

          Source is now on the site: [bensantora.com/downloads/fftool-source.tar.gz] and .zip. Build instructions are in the article.

    • By lionkor 2026-03-1312:22

      To be fair, it ships with debug info.

    • By garymoon 2026-03-1312:07

      Same

  • By overflowy 2026-03-1311:422 reply

    > terminal UI written in Go

    > Linux only

    Any particular reason for that? Are you using specific Linux APIs?

    Just to clarify, this looks like a super helpful utility, something that I would personally use. The issue is that I noticed the installation instructions include a link to a prebuilt binary hosted on your website. Without providing access to the source code, you're asking users to trust executing an unknown binary on their system.

    • By taskset 2026-03-1312:243 reply

      I no longer use GitHub for original projects. Source for fftool isn't public yet but I understand the concern — running an unaudited binary is a real ask. My site leans toward educational, so that people consider building the tool from the instructions in the article. I may host the source on the site as a zip or tarball at some point so people can more easily build it.

      As for Linux API - TIOCGWINSZ via syscall.IOCTL to get terminal dimensions.

      Why Linux and Go - Linux is the only OS I use. I like Go because it produces a single static binary with no runtime dependencies. Thanks for your interest.

      • By jbstack 2026-03-1313:291 reply

        I don't understand what this comment is trying to say.

        > ... people consider building the tool from the instructions in the article ... so people can more easily build it

        So what's the "less easy" way that people can build it from the instructions, if there's no source code?

        • By taskset 2026-03-1314:56

          Source code is now on the site: [bensantora.com/downloads/fftool-source.tar.gz] and .zip.

          Build instructions are in the article.

      • By lionkor 2026-03-1312:31

        You use charmbracelet/bubbletea for the TUI, which does seem to support Windows, what am I missing?

      • By wpm 2026-03-1315:02

        TIOCGWINSZ is a standard UNIX syscall, it works on Linux, BSD, and macOS.

    • By taskset 2026-03-1314:58

      Source is now on the site: [bensantora.com/downloads/fftool-source.tar.gz] and .zip. Build instructions are in the article.

  • By kawsper 2026-03-1312:18

    Speaking of ffmpeg tools, someone on HN showed a TUI for ffmpeg that let you trim a video, with a preview in your terminal so you could trim precisely.

    I've tried searching for the comment but without any luck, if anyone have a suggestion for the name, I would be grateful.

HackerNews