How to install FFmpeg on Windows: a complete guide
To install FFmpeg on Windows, extract a Windows build and add the folder containing ffmpeg.exe
to your PATH. The archive has a versioned folder inside it, so that folder is usually deeper than
C:\FFmpeg\bin. This walkthrough finds the actual path, makes FFmpeg available to your account,
and checks it by creating and inspecting a short video.
Prerequisites
Use Windows 11 on an x64 PC and Windows PowerShell 5.1. You need an internet connection and space for the ZIP and its extracted files. This installation stays under your user profile and changes only your user PATH; it does not require an administrator terminal.
The commands below are for pasting into PowerShell, not Command Prompt. Keep the same PowerShell
window open through installation so that $bin remains available. Stop if a block reports an error.
There is no need to change your script execution policy to paste these commands.
Install the ZIP build
Step 1: Download FFmpeg
Open the official FFmpeg download page and follow “Windows
builds from gyan.dev”. FFmpeg publishes source code; Gyan supplies the compiled Windows programs.
On Gyan’s builds page, find release builds and download
ffmpeg-release-essentials.zip plus the adjacent .sha256 file. Save them in your Downloads folder
with those names, including ffmpeg-release-essentials.zip.sha256. If your browser displays the
checksum as text, save the page as a plain text file with that filename.
If the ZIP download is slow, follow the page’s “mirror @ github” link and select the same release’s
essentials ZIP. Rename that versioned ZIP to ffmpeg-release-essentials.zip for these commands,
and use the checksum for that same version from Gyan’s builds page.
The essentials ZIP includes ffmpeg, ffprobe, and the libx264 encoder used below. The ZIP works
with PowerShell’s built-in extractor, so you do not need 7-Zip. The tested build is Gyan’s
9.0.2-essentials_build; the download link may serve a newer release when you visit it.
The essentials build is static. Keep a shared build’s matching FFmpeg DLLs with its executables if you choose that variant instead. “Full” adds external libraries; it does not mean you need it for ordinary H.264 encoding. Gyan currently requires Windows 10 or later; this walkthrough covers Windows 11 x64, not older Windows versions or native ARM64 builds.
Verify the ZIP and find its bin directory
Paste this block into PowerShell. If you saved the download elsewhere, change $archive first.
It checks the SHA-256 against the publisher’s file, extracts into
%LOCALAPPDATA%\Programs\FFmpeg, and stores the actual executable directory in $bin.
It refuses to use an existing destination, including one left by an interrupted extraction.
Choose another destination instead of overwriting an installation.
$bin = & {
$ErrorActionPreference = 'Stop'
$archive = Join-Path $env:USERPROFILE 'Downloads\ffmpeg-release-essentials.zip'
$destination = Join-Path $env:LOCALAPPDATA 'Programs\FFmpeg'
if (Test-Path -LiteralPath $destination) {
throw 'The installation folder already exists. Choose a new destination.'
}
$expected = (Get-Content -Raw -LiteralPath "$archive.sha256").Trim()
$actual = (Get-FileHash -LiteralPath $archive -Algorithm SHA256).Hash
if ($expected -notmatch '^[0-9a-fA-F]{64}$' -or $actual -ne $expected) {
throw 'SHA-256 mismatch. Download the ZIP and its checksum again.'
}
Expand-Archive -LiteralPath $archive -DestinationPath $destination
$executables = @(Get-ChildItem -LiteralPath $destination -Filter ffmpeg.exe -File -Recurse)
if ($executables.Count -ne 1) {
throw 'Expected one ffmpeg.exe in the extracted archive.'
}
$executables[0].Directory.FullName
}
$bin
For the tested ZIP, the result ends in
Programs\FFmpeg\ffmpeg-9.0.2-essentials_build\bin. The last component must be bin, and that
folder must contain both ffmpeg.exe and ffprobe.exe. Do not add the ZIP, its outer extraction
folder, or the executable filename itself to PATH.
Get-FileHash checks the downloaded bytes against the publisher’s checksum. A match detects a damaged or mismatched download; it is not independent proof that the publisher’s files are trustworthy. Expand-Archive extracts the ZIP while retaining its nested directories.
Add FFmpeg to your user PATH
PATH is a list of directories Windows searches for commands. The following block appends $bin to
your user PATH, preserving its existing entries and avoiding an identical duplicate. The
machine PATH applies to every account and normally needs administrator permission to change;
you do not need to edit it for this installation.
& {
$ErrorActionPreference = 'Stop'
if (-not $bin -or -not (Test-Path -LiteralPath (Join-Path $bin 'ffmpeg.exe') -PathType Leaf)) {
throw 'Run the extraction block successfully before changing PATH.'
}
$userPath = [Environment]::GetEnvironmentVariable('Path', 'User')
if (($userPath -split ';') -notcontains $bin) {
$updatedPath = (@($userPath, $bin) | Where-Object { $_ }) -join ';'
[Environment]::SetEnvironmentVariable('Path', $updatedPath, 'User')
}
}
This saves PATH for your account; it does not refresh programs already running. For this PowerShell window, also prepend the directory to the process PATH:
$env:Path = "$bin;$env:Path"
A child process inherits its parent’s environment. Opening another tab in an existing terminal or editor can therefore retain an old PATH. Close the whole terminal application and reopen it from Start before checking persistence. If it still has the old environment, sign out of Windows and sign back in. Microsoft’s environment-variable documentation explains these process, user, and machine scopes. The temporary prepend above deliberately prefers this copy; a fresh login can still find an older installation earlier in the combined PATH.
Verifying the installation
Check the selected executables as well as their versions. Run this now and again after reopening your terminal:
& {
$ErrorActionPreference = 'Stop'
Get-Command ffmpeg, ffprobe -All | Format-List CommandType, Name, Source
ffmpeg -version
if ($LASTEXITCODE -ne 0) { throw 'ffmpeg could not start.' }
ffprobe -version
if ($LASTEXITCODE -ne 0) { throw 'ffprobe could not start.' }
}
Both paths should point into the extracted bin folder, with matching build versions. If more than
one result appears for a name, the first is the command PowerShell selects. An alias or function can
also take precedence over an executable.
Encode a video and inspect it
In PowerShell, move to a folder where you want to create a small test video, such as Downloads.
This example generates a one-second test pattern, so it needs no input footage or GPU. It writes
ffmpeg-check.mp4 in the current directory. The explicit file check stops a rerun before encoding;
-n also prevents FFmpeg from overwriting an existing file. For a repeat test, move that file aside
or choose another output name in the check and both commands.
& {
$ErrorActionPreference = 'Stop'
if (Test-Path -LiteralPath './ffmpeg-check.mp4') {
throw 'Output already exists. Move it aside or choose a new filename.'
}
ffmpeg -hide_banner -loglevel error -nostdin -n -f lavfi -i "testsrc2=size=320x180:rate=25" -t 1 -c:v libx264 -pix_fmt yuv420p "./ffmpeg-check.mp4"
if ($LASTEXITCODE -ne 0) { throw 'Encode failed. Check the error above before probing the output.' }
ffprobe -v error -select_streams v:0 -show_entries stream=codec_name,width,height,pix_fmt:format=duration -of json "./ffmpeg-check.mp4"
if ($LASTEXITCODE -ne 0) { throw 'ffprobe could not read the output.' }
}
The JSON should identify h264, width 320, height 180, pixel format yuv420p, and a duration
of about 1.000000 seconds. That checks encoding and reading a real MP4, beyond just starting the
programs. FFmpeg documents overwrite control, and
ffprobe’s selected fields make the result easy to inspect.
Troubleshooting common issues
FFmpeg not recognized
Check whether the executable works by its full path. In the original PowerShell session, $bin
still contains that directory; in a new session, set it to the path printed during extraction.
& {
$ErrorActionPreference = 'Stop'
& (Join-Path $bin 'ffmpeg.exe') -version
if ($LASTEXITCODE -ne 0) { throw 'The selected ffmpeg.exe could not start.' }
}
If this works but ffmpeg -version does not, investigate command discovery: the correct bin
entry, the terminal’s inherited PATH, and the Get-Command -All results above. An “Unknown encoder”
error means FFmpeg did start. Check that the selected build contains the encoder you requested;
for example, run ffmpeg -hide_banner -encoders and look for libx264.
Missing DLL errors
Extract the complete archive again into a new folder and confirm which executable PowerShell is
running. A shared build needs its matching DLLs; copying only its .exe files loses that setup.
Do not mix DLLs from different releases or download individual DLLs from unrelated sites.
A static build still depends on Windows system components. Installing the newest Visual C++
Redistributable is not a universal fix for a named missing DLL; follow that build’s documented
runtime requirements.
Permission issues
Keep the installation and test output in folders your account can write to. An access-denied error
under Program Files or while changing the machine PATH is not a reason to run every conversion
as Administrator. If a managed PC blocks executable downloads or launches, use its approved
software-installation process.
Hardware acceleration is a separate check
The example uses CPU encoding. A build listing NVENC, QSV, or another hardware component does not
prove your PC can use it: compatible hardware and drivers must also be available. FFmpeg’s
-hwaccels documentation makes that
distinction. Get the software encode working before diagnosing a GPU encoder.
If you already use a package manager
Gyan’s builds page also lists Chocolatey, Scoop, and WinGet packages. Those are an alternative to this manual installation; use the same manager for updates and removal, and check which build its package installs. Avoid keeping both methods on PATH unless you intend to select between them. Package-manager setup is outside this walkthrough.
Updating FFmpeg
For this manual installation, download the new ZIP and its checksum, then repeat the extraction
block with a different destination, such as Programs\FFmpeg-new. Run the PATH blocks using the
new $bin, and repeat the encode/probe check with a fresh output filename. Keep the previous folder
until the new build works.
Afterward, search Start for “Edit environment variables for your account”, edit Path under
User variables, and remove the exact old bin entry while keeping the new one and all unrelated
entries. Restart the terminal and check Get-Command again before deleting the old installation.
To uninstall a manual copy, remove its user PATH entry and then its extracted folder.
