Yalantis/uCrop · error · CImgIOException
save_ffmpeg_external(): Failed to save file
Error message
save_ffmpeg_external(): Failed to save file '%s' with external command 'ffmpeg'.
What it means
save_ffmpeg_external() pipes PPM frames to the external 'ffmpeg' binary and rebuilds the video. This error is thrown when the ffmpeg system command returns non-zero, or (second variant) when the output file does not exist afterwards, meaning ffmpeg failed or produced nothing.
Solutions
- Install ffmpeg or point cimg::ffmpeg_path() (CIMG_FFMPEG_PATH env var) to an existing binary
- Run 'ffmpeg -encoders' and pick a codec your build supports (e.g. mpeg4, mpeg2video)
- Check ffmpeg's stderr from the system call for the exact encoding failure
- Verify disk space and write permission on the target path
Example fix
// before
frames.save_ffmpeg_external("out.mp4", 25, "h264"); // no libx264 in ffmpeg build
// after
frames.save_ffmpeg_external("out.mp4", 25, "mpeg4"); // encoder present in stock builds Defensive patterns
Strategy: fallback
Validate before calling
// C++ bool ffmpegOk = cimg::path_exists(cimg::ffmpeg_path()); bool writable = access(dir_of(fname), W_OK) == 0; if (!ffmpegOk || !writable) useInternalWriterInstead();
Type guard
bool ffmpeg_available() { return cimg::path_exists(cimg::ffmpeg_path()); } Try / catch
try { frames.save_ffmpeg_external(fname, fps, codec); }
catch (CImgIOException& e) { fprintf(stderr, "ffmpeg failed: %s", e.what()); frames.save_video(fname, fps, "mp4v"); } Prevention
- Bundle/install ffmpeg or set CIMG_FFMPEG_PATH
- Choose codecs verified with 'ffmpeg -encoders'
- Check disk space before long encodes
- Fall back to cv::VideoWriter-based save_video on headless images
When it happens
Trigger: Calling save_ffmpeg_external() when the ffmpeg executable is missing/not at cimg::ffmpeg_path(), the requested -vcodec is unsupported by the installed ffmpeg, bad bitrate/fps arguments, disk full, or the output path is unwritable so no file appears after the run.
Common situations: Android/CI images without ffmpeg installed; ffmpeg builds lacking the chosen codec (e.g. h264/libx264 unavailable); codec name mismatch after upstream default change ('mpeg2video' fallback); SELinux blocking exec of ffmpeg.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
- load_ffmpeg_external(): Failed to open file
- load_ffmpeg_external(): Specified filename is (null) or…
- save_ffmpeg_external(): Invalid instance dimensions for file
- save_ffmpeg_external(): Specified filename is (null).
- cimg::load_network(): Failed to load file
AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08).
Data as JSON: /api/errors/27a49cd47e942ff1.
Report an issue: GitHub.
Appendix: source
Thrown at ucrop/src/main/jni/CImg.h:68711
cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_%.6u.ppm",filename_tmp._data,frame);
CImg<charT>::string(filename_tmp2).move_to(filenames);
CImg<T> _src = src._depth>1?src.get_slice(z):src.get_shared();
if (_src._width%2 || _src._height%2) // Force output to have an even number of columns and rows
_src.assign(_src.get_resize(_src._width + (_src._width%2),_src._height + (_src._height%2),1,-100,0),false);
if (_src._spectrum!=3) // Force output to be one slice, in color
_src.assign(_src.get_resize(-100,-100,1,3),false);
_src.save_pnm(filename_tmp2);
++frame;
}
}
cimg_snprintf(command,command._width,
"\"%s\" -framerate %u -v -8 -y -i \"%s_%%6d.ppm\" -pix_fmt yuv420p -vcodec %s -b %uk -r %u \"%s\"",
cimg::ffmpeg_path(),
fps,CImg<charT>::string(filename_tmp)._system_strescape().data(),
_codec,bitrate,fps,
CImg<charT>::string(filename)._system_strescape().data());
if (cimg::system(command,cimg::ffmpeg_path())!=0)
throw CImgIOException(_cimglist_instance
"save_ffmpeg_external(): Failed to save file '%s' with external command 'ffmpeg'.",
cimglist_instance,
filename);
if (!cimg::path_exists(filename))
throw CImgIOException(_cimglist_instance
"save_ffmpeg_external(): Failed to save file '%s' with external command 'ffmpeg'.",
cimglist_instance,
filename);
cimglist_for(*this,l) std::remove(filenames[l]);
return *this;
}
//! Serialize a CImgList<T> instance into a raw CImg<unsigned char> buffer.
/**
\param is_compressed tells if zlib compression must be used for serialization
(this requires 'cimg_use_zlib' been enabled).
\param header_size Reserve empty bytes as a starting header.
**/View on GitHub (pinned to f788b534b4)