{"record":{"id":"0aa33a8569a6e330","repo":"MathewSachin/Captura","slug":"ffmpeg-could-not-be-found-please-download-using-t-0aa33a","errorCode":null,"errorMessage":"FFmpeg could not be found. Please download using the in-built downloader.","messagePattern":"FFmpeg could not be found\\. Please download using the in-built downloader\\.","errorType":"exception","errorClass":"FFmpegNotFoundException","httpStatus":null,"severity":"error","filePath":"src/Captura.FFmpeg/Video/FFmpegGifConverter.cs","lineNumber":18,"sourceCode":"﻿using System;\nusing System.Threading.Tasks;\nusing Captura.Video;\n\nnamespace Captura.FFmpeg\n{\n    // ReSharper disable once InconsistentNaming\n    class FFmpegGifConverter : IVideoConverter\n    {\n        public string Name => \"Gif (FFmpeg)\";\n\n        public string Extension => \".gif\";\n\n        public async Task StartAsync(VideoConverterArgs Args, IProgress<int> Progress)\n        {\n            if (!FFmpegService.FFmpegExists)\n            {\n                throw new FFmpegNotFoundException();\n            }\n\n            var argsBuilder = new FFmpegArgsBuilder();\n\n            argsBuilder.AddInputFile(Args.InputFile);\n\n            const string filter = \"\\\"[0:v] split [a][b];[a] palettegen [p];[b][p] paletteuse\\\"\";\n\n            argsBuilder.AddOutputFile(Args.FileName)\n                .AddArg(\"filter_complex\", filter)\n                .SetFrameRate(Args.FrameRate);\n\n            var process = FFmpegService.StartFFmpeg(argsBuilder.GetArgs(), Args.FileName, out var log);\n            log.ProgressChanged += Progress.Report;\n\n            await Task.Run(() => process.WaitForExit());\n\n            if (process.ExitCode != 0)","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/MathewSachin/Captura/blob/3fdf41529bf4d50cd7a85aedd856f30e34279a47/src/Captura.FFmpeg/Video/FFmpegGifConverter.cs#L1-L36","documentation":"Thrown by FFmpegGifConverter.StartAsync (src/Captura.FFmpeg/Video/FFmpegGifConverter.cs:18) when FFmpegService.FFmpegExists is false. Identical guard to the audio writer: the GIF conversion path needs an ffmpeg binary before it can build the palettegen/paletteuse filter graph.","triggerScenarios":"Invoking the GIF converter before ffmpeg.exe is available in the configured folder, app/lib dir, or PATH (FFmpegService.FFmpegExists returns false).","commonSituations":"User converts a recording to GIF on a fresh install with no ffmpeg downloaded yet; the FFmpeg folder setting was reset or points at a removed portable folder.","solutions":["Download ffmpeg via the in-built downloader before offering the GIF conversion action.","Verify FFmpegSettings.GetFolderPath() resolves to a real ffmpeg.exe.","Place ffmpeg.exe in the app or lib directory as a fallback."],"exampleFix":"// before\nawait new FFmpegGifConverter().StartAsync(args, progress);\n// after\nif (!FFmpegService.FFmpegExists)\n    await DownloadFFmpeg.Run(); // ensure binary present\nawait new FFmpegGifConverter().StartAsync(args, progress);","handlingStrategy":"validation","validationCode":"if (!FFmpegService.FFmpegExists) await DownloadFFmpeg.Run();\nif (!FFmpegService.FFmpegExists) throw new FFmpegNotFoundException();","typeGuard":null,"tryCatchPattern":"try { await new FFmpegGifConverter().StartAsync(args, progress); }\ncatch (FFmpegNotFoundException) { /* run downloader, then offer retry */ }","preventionTips":["Disable the Convert-to-GIF action until FFmpegService.FFmpegExists is true.","Bundle or auto-download ffmpeg so the converter is always usable.","Re-check FFmpegExists after the FFmpeg folder setting changes."],"tags":["ffmpeg","configuration","dependency-missing","gif","csharp"],"backgroundTag":null,"analyzedSha":"3fdf41529bf4d50cd7a85aedd856f30e34279a47","analyzedAt":"2026-08-13T19:35:27.486Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}