-
Notifications
You must be signed in to change notification settings - Fork 0
ffmpeg
src/record/ffmpeg_locator.cpp, src/record/ffmpeg_download.cpp
Two things require ffmpeg.exe: recording, and HDR screenshots in AVIF,
which go through libaom.
Nothing else does. SDR screenshots go through Windows Imaging Component precisely so they still work on a fresh machine where nobody has pressed the download button yet, and so does the other HDR format — Windows ships the JPEG XR encoder — so an HDR still can be saved without ffmpeg by choosing that one instead. The preview, the composite filters, deinterlacing and the virtual camera never touch it.
ffmpeg lives at the top of the Encoder tab rather than buried in it, so the option to install it is the first thing visible when it is missing. That placement is deliberate and was restored after being accidentally removed once.
LocateFfmpeg() looks in this order:
- The configured path, if one is set
-
ffmpeg\binnext toCapView.exe -
ffmpegnext toCapView.exe - Next to
CapView.exeitself PATH
Only the path and version are filled in here. The encoder probe is separate, because it takes seconds.
The button in the Encoder tab, or from the command line:
CapView.exe --fetch-ffmpegFfmpegDownloader::Start() runs on a worker thread and does four things:
-
Fetches the checksum first, from
https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-essentials.zip.sha256. First, so that a mismatch is detectable at all — a checksum fetched after the archive from the same compromised source proves nothing. - Downloads the archive, reporting progress where the server supplies a content length and a negative progress where it does not.
-
Verifies SHA-256 with
BCrypt, streaming the file rather than loading it. -
Extracts only
ffmpeg.exeand deletes the archive.
StartVersionCheck() asks the server which version it would deliver without
downloading anything, on the same worker.
The usual Windows builds contain x264 and x265 and are therefore GPL licensed, and whoever hands them on owes the source with them.
Pressing a button that fetches from gyan.dev is not distribution, which keeps CapView's own MIT licence uncomplicated. Calling ffmpeg as a child process is not linking either, so nothing about the GPL reaches this program. Redistributing CapView together with an ffmpeg build is a different matter, and the GPL then applies to what is being distributed.
ffmpeg -encoders is not enough. It lists what the build was compiled with,
not what the hardware can do: a build with h264_nvenc on a machine with an
AMD card lists it happily and then fails at record time.
So each candidate gets a one frame test encode to NUL, which takes a moment
and tells the truth.
Two entry points:
-
ProbeEncoders()— the full list, several seconds. This is the "Test encoders" button, run on demand and never at startup. -
ResolveUsable()— tests only as much as is needed to answer "can I record right now": the requested encoder, or for automatic the preference order until one works. Results are remembered, so a second call costs nothing.
The result is stored in the configuration and reused on subsequent starts.
ApplyProbeResults() fills the list back in from the stored values, so the tab
shows what this machine can actually do without re-running anything.
It is discarded when the graphics adapter or the ffmpeg build changes — both of those invalidate every answer in it.
There is no scoring. Which order applies is the user's choice, because the two goals genuinely conflict: AV1 is the better codec and the one an older television cannot play.
| Mode | Order | Suited to |
|---|---|---|
| Plays anywhere | H.264, H.265, AV1 | Files that open on any phone, television or editor |
| Smaller files | AV1, H.265, H.264 | The same quality at a fraction of the size |
Hardware encoders precede the CPU encoders in both orders. Each mode takes the first entry of its order that passed the test.
RunFfmpeg() captures stdout and stderr together and returns false only when the
process could not be started at all — a non-zero exit is a result, not a failure
to run, and the caller decides what it means.