nilaoda/N_m3u8DL-RE · error · FileNotFoundException
ResString.ffmpegNotFound
Error message
ResString.ffmpegNotFound
What it means
DoWorkAsync pre-checks that an ffmpeg binary is available before doing work: it tries option.FFmpegBinaryPath, then GlobalUtil.FindExecutable("ffmpeg") on PATH. If none resolves to an existing file it throws FileNotFoundException with the localized 'ffmpeg not found' resource string. Merging/muxing and some decryption paths require ffmpeg.
Solutions
- Install ffmpeg or place ffmpeg(.exe) on PATH
- Pass the explicit binary location via --ffmpeg-binary-path (e.g. C:\tools\ffmpeg\bin\ffmpeg.exe)
- Verify the path with: ffmpeg -version in a terminal
- In Docker, use an image that includes ffmpeg or add it in the Dockerfile
Example fix
// before N_m3u8DL-RE "URL" -M // after (custom path) N_m3u8DL-RE "URL" -M --ffmpeg-binary-path "/usr/local/bin/ffmpeg"
Defensive patterns
Strategy: validation
Validate before calling
var ffmpeg = GlobalUtil.FindExecutable("ffmpeg");
if (ffmpeg == null || !File.Exists(ffmpeg))
throw new FileNotFoundException("install ffmpeg or pass --ffmpeg-binary-path"); Type guard
static bool FfmpegAvailable(CLIOptions o) => (o.FFmpegBinaryPath != null && File.Exists(o.FFmpegBinaryPath)) || GlobalUtil.FindExecutable("ffmpeg") != null; Try / catch
try { await DoWorkAsync(option); }
catch (FileNotFoundException ex) when (ex.FileName == null && ex.Message.Contains("ffmpeg"))
{
Console.Error.WriteLine("ffmpeg not found: install it or set --ffmpeg-binary-path");
} Prevention
- Install ffmpeg before first use and keep it on PATH
- Pin the binary path via --ffmpeg-binary-path in scripts for reproducibility
- Verify with `ffmpeg -version` in the same environment/user that runs the tool (PATH differs per user)
When it happens
Trigger: ffmpeg is not installed, not on PATH, the custom --ffmpeg-binary-path points to a nonexistent file, or FFmpegBinaryPath was set to a bad value programmatically.
Common situations: Fresh systems/dockers without ffmpeg; Windows users who never added ffmpeg to PATH; typo'd custom binary path; renamed binaries.
Related errors
- ResString.mkvmergeNotFound
- MuxAfterDone disabled, MuxImports not allowed!
- ResString.shakaPackagerNotFound
- Key must be 12 or 8 bytes!
- Download init file failed!
AI-assisted analysis of nilaoda/N_m3u8DL-RE@e113dee70c (2026-09-13).
Data as JSON: /api/errors/3622b0e2a9fb2818.
Report an issue: GitHub.
Appendix: source
Thrown at src/N_m3u8DL-RE/Program.cs:135
if (option.UseShakaPackager)
{
option.DecryptionEngine = DecryptEngine.SHAKA_PACKAGER;
}
// LivePipeMux开启时 LiveRealTimeMerge必须开启
if (option is { LivePipeMux: true, LiveRealTimeMerge: false })
{
Logger.WarnMarkUp("LivePipeMux detected, forced enable LiveRealTimeMerge");
option.LiveRealTimeMerge = true;
}
// 预先检查ffmpeg
option.FFmpegBinaryPath ??= GlobalUtil.FindExecutable("ffmpeg");
if (string.IsNullOrEmpty(option.FFmpegBinaryPath) || !File.Exists(option.FFmpegBinaryPath))
{
throw new FileNotFoundException(ResString.ffmpegNotFound);
}
Logger.Extra($"ffmpeg => {option.FFmpegBinaryPath}");
// 预先检查mkvmerge
if (option is { MuxOptions.UseMkvmerge: true, MuxAfterDone: true })
{
option.MkvmergeBinaryPath ??= GlobalUtil.FindExecutable("mkvmerge");
if (string.IsNullOrEmpty(option.MkvmergeBinaryPath) || !File.Exists(option.MkvmergeBinaryPath))
{
throw new FileNotFoundException(ResString.mkvmergeNotFound);
}
Logger.Extra($"mkvmerge => {option.MkvmergeBinaryPath}");
}
// 预先检查
if (option.Keys is { Length: > 0 } || option.KeyTextFile != null)
{View on GitHub (pinned to e113dee70c)