Faceswap Writer Plugins for Video Output: ffmpeg, gif, and patch Explained
Faceswap delegates all video and image output to modular writer plugins—ffmpeg for high-performance video encoding, gif for animated loops, and patch for face-patch extraction—each implementing the abstract Output class from plugins/convert/writer/_base.py.
The deepfakes/faceswap conversion pipeline relies on a plugin-based architecture to generate final output. When you run the convert command with the -w/--writer flag, the system loads a specific writer plugin via PluginLoader.get_converter("writer", name) to handle frame serialization. These plugins handle everything from high-efficiency video compression to per-face image extraction with transformation metadata.
Writer Plugin Architecture
All output handlers inherit from the abstract Output class defined in plugins/convert/writer/_base.py. This base implements core methods including write(), close(), and frame-ordering logic to ensure sequential output regardless of processing order.
The PluginLoader class in plugins/plugin_loader.py registers each writer under the convert → writer category. When you specify a writer name via CLI, the loader returns the concrete implementation class that matches the requested output format.
Video Output Writer Plugins
Faceswap provides three primary writer plugins for video and sequence output: ffmpeg for standard video containers, gif for animated images, and patch for extracted face data.
ffmpeg Writer
The ffmpeg writer in plugins/convert/writer/ffmpeg.py generates high-performance video output using imageio-ffmpeg. It supports container formats such as MP4, MKV, and WebM with configurable codec selection, CRF values, presets, and tuning options.
Key implementation details include:
- FPS detection: The
_video_fps()method extracts the source video frame rate to maintain temporal accuracy. - Audio handling:
_test_for_audio_stream()checks for audio streams and handles muxing or skipping based on configuration. - Parameter building:
_output_params()constructs the ffmpeg command-line arguments dynamically. - Frame writing: Uses
imageio_ffmpeg.write_framesas a generator to stream frames efficiently.
Configuration options reside in plugins/convert/writer/ffmpeg_defaults.py, exposing helpers like codec(), crf(), and preset() that read from config/convert.ini.
gif Writer
The gif writer in plugins/convert/writer/gif.py produces animated GIFs using the imageio library. It supports configurable FPS, palette sizes, loop counts, and sub-rectangle optimization for reduced file sizes.
After receiving the first frame, the writer lazily initializes the imageio GIF writer and fixes output dimensions via _set_dimensions(). The implementation maintains a frame cache to handle out-of-order processing, appending each frame via self._writer.append_data().
Default values and helper functions are defined in plugins/convert/writer/gif_defaults.py.
patch Writer
The patch writer in plugins/convert/writer/patch.py exports each swapped face as an individual image file (PNG or TIFF) alongside a JSON sidecar containing the transformation matrix. This plugin is essential for downstream pipelines that require re-insertion of processed faces into original frames.
Key features include:
- Individual file output: Saves each face patch separately with configurable naming conventions.
- Metadata preservation: Stores the affine transformation matrix in a companion JSON file when
--patch.json-outputis enabled. - Bit-depth control: Supports 8-bit or 16-bit output depths via
patch_defaults.py.
This writer does not produce video files but generates image sequences with spatial metadata, making it distinct from the ffmpeg and gif video encoders.
Static Image Writers
In addition to video-specific plugins, Faceswap includes pillow and opencv writers for simple static image output.
The pillow writer (plugins/convert/writer/pillow.py) delegates to Pillow's Image.save() method, supporting any format Pillow handles natively. The opencv writer (plugins/convert/writer/opencv.py) uses cv2.imwrite() and provides access to OpenCV-specific encoding flags such as PNG compression levels.
Both inherit the same caching and ordering logic from the base class but lack video-specific options.
Configuration and Defaults
Each writer plugin maintains a corresponding defaults module that interfaces with the global Faceswap configuration:
ffmpeg_defaults.py: Exposescodec(),crf(),preset(), and audio muxing options.gif_defaults.py: Controlsfps(),loop(), andpalettesize()settings.patch_defaults.py: Managesformat(),bit-depth(), and JSON output toggles.
These modules read from config/convert.ini and provide type-safe access to user preferences.
Command Line Usage Examples
Select your output format using the -w or --writer flag followed by plugin-specific arguments.
Encoding to MP4 with ffmpeg
faceswap convert -i input_folder -o output_folder -w ffmpeg \
--ffmpeg.codec libx264 --ffmpeg.crf 23 --ffmpeg.preset medium
This creates *_converted.mp4 with H.264 encoding at CRF 23. Audio automatically muxes from the source unless you specify --ffmpeg.skip-mux.
Creating Animated GIFs
faceswap convert -i frames/ -o gif_output/ -w gif \
--gif.fps 15 --gif.loop 0 --gif.palettesize 256
The output frames_converted.gif loops infinitely at 15 FPS using a 256-color palette.
Extracting Face Patches
faceswap convert -i video.mp4 -o patches/ -w patch \
--patch.format png --patch.bit-depth 16 --patch.json-output true
Each swapped face saves as a 16-bit PNG with a corresponding JSON file containing the transform matrix.
Static Image Output
For simple frame-by-frame output using Pillow:
faceswap convert -i frames/ -o images/ -w pillow
Or using OpenCV with compression flags:
faceswap convert -i frames/ -o images_opencv/ -w opencv \
--opencv.png-compress-level 3
Summary
- Plugin Architecture: All writers inherit from the abstract
Outputclass inplugins/convert/writer/_base.pyand register viaPluginLoader. - ffmpeg: High-performance video encoding with audio muxing, codec selection, and quality controls via
ffmpeg_defaults.py. - gif: Animated GIF generation with configurable looping and palette optimization using
imageio. - patch: Face-patch extraction with transformation matrix metadata for downstream processing pipelines.
- Configuration: Each plugin has a dedicated defaults file (e.g.,
ffmpeg_defaults.py) that reads fromconfig/convert.ini. - CLI Selection: Use
-w plugin_nameto activate a specific writer with--plugin.optionsyntax for parameters.
Frequently Asked Questions
What is the difference between the ffmpeg and gif writers in Faceswap?
The ffmpeg writer generates standard video container files (MP4, MKV, WebM) using imageio-ffmpeg with full audio support and codec customization, while the gif writer produces animated GIF images optimized for web use with limited color palettes and no audio track. Use ffmpeg for high-fidelity video preservation and gif for lightweight, looping previews.
When should I use the patch writer instead of video output?
Use the patch writer when you need to extract individual face images with their transformation matrices for external editing or re-insertion into different backgrounds. Unlike ffmpeg or gif, the patch writer outputs separate PNG/TIFF files and JSON sidecars rather than a single video file, making it ideal for compositing workflows.
How do I configure video codec and quality settings?
Codec selection, CRF values, and encoding presets are configured through the ffmpeg_defaults.py module or via CLI arguments. Pass --ffmpeg.codec (e.g., libx264, libx265), --ffmpeg.crf (0-51, lower is higher quality), and --ffmpeg.preset (e.g., slow, medium, fast) to balance quality versus encoding speed.
Can I use the pillow or opencv writers for video sequences?
While pillow and opencv writers can process video frames, they output individual static images rather than encoded video files. These writers are suitable when you need frame-by-frame access or specific image formats, but they lack the compression efficiency and audio capabilities of the ffmpeg writer.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →