# How the FaceSwap Plugin System Works for Models, Trainers, and Converters

> Discover how FaceSwap's plugin system dynamically loads models, trainers, and converters from the plugins directory. Learn about its convention-based approach for efficient development.

- Repository: [deepfakes/faceswap](https://github.com/deepfakes/faceswap)
- Tags: internals
- Published: 2026-03-06

---

**FaceSwap uses a convention-based `PluginLoader` class in [`plugins/plugin_loader.py`](https://github.com/deepfakes/faceswap/blob/main/plugins/plugin_loader.py) to dynamically import model, trainer, and converter classes from the `plugins/` directory at runtime, mapping hyphenated names to title-cased Python classes using standard import machinery.**

The FaceSwap plugin system provides a flexible architecture for extending deepfake training and conversion capabilities through three distinct extension points: **models**, **trainers**, and **converters**. By leveraging dynamic module importing and strict naming conventions implemented in [`plugins/plugin_loader.py`](https://github.com/deepfakes/faceswap/blob/main/plugins/plugin_loader.py), the system allows developers to add new neural network architectures, training loops, and output formats simply by placing correctly named Python files in designated subdirectories of the `plugins/` folder.

## FaceSwap Plugin Architecture Overview

The FaceSwap plugin system organizes extensions into three categories, each with dedicated directories and abstract base classes that define the contract between the framework and the plugin.

**Models** (`plugins/train/model/`): Neural network architectures that define the autoencoder structure. All models inherit from `ModelBase` defined in [`plugins/train/model/_base/update.py`](https://github.com/deepfakes/faceswap/blob/main/plugins/train/model/_base/update.py). Examples include [`original.py`](https://github.com/deepfakes/faceswap/blob/main/original.py) and [`phaze_a.py`](https://github.com/deepfakes/faceswap/blob/main/phaze_a.py).

**Trainers** (`plugins/train/trainer/`): Training loop implementations that handle batch processing, loss calculation, and optimization. These inherit from `TrainerBase` in [`plugins/train/trainer/_base.py`](https://github.com/deepfakes/faceswap/blob/main/plugins/train/trainer/_base.py). The default implementation resides in [`plugins/train/trainer/original.py`](https://github.com/deepfakes/faceswap/blob/main/plugins/train/trainer/original.py).

**Converters** (`plugins/convert/<category>/`): Post-processing and output modules organized by category (e.g., `writer/`, `mask/`). Writers inherit from the `Output` base class in [`plugins/convert/writer/_base.py`](https://github.com/deepfakes/faceswap/blob/main/plugins/convert/writer/_base.py), with concrete implementations like [`pillow.py`](https://github.com/deepfakes/faceswap/blob/main/pillow.py) providing specific output formats.

## How the PluginLoader Dynamically Discovers Extensions

At the heart of the FaceSwap plugin system is the `PluginLoader` class in [`plugins/plugin_loader.py`](https://github.com/deepfakes/faceswap/blob/main/plugins/plugin_loader.py). This utility implements a convention-based discovery mechanism that maps string names to Python classes without hardcoded imports.

The loader normalizes plugin names by converting hyphens to underscores (`my-model` → `my_model`) to match Python module naming conventions. It then constructs the full module path (e.g., `plugins.model.original`) and uses `import_module` from Python's import machinery to load the file dynamically.

Once imported, the loader retrieves the class by applying title-casing to the module name. For example, [`original.py`](https://github.com/deepfakes/faceswap/blob/main/original.py) contains the class `Original`, and [`phaze_a.py`](https://github.com/deepfakes/faceswap/blob/main/phaze_a.py) contains `PhazeA`. This strict naming convention ensures predictable class resolution.

The `PluginLoader` also provides discovery methods for listing available plugins. `get_available_models()` scans `plugins/train/model/` for non-private Python files (excluding those starting with underscore), while `get_available_convert_plugins(category)` performs similar scans for converter categories like `writer` or `mask`.

## Loading Models, Trainers, and Converters

The FaceSwap plugin system exposes three primary loader methods that scripts use to instantiate the necessary components for training and conversion workflows.

### Loading a Training Model

To load a model architecture, call `PluginLoader.get_model(name)`. This returns the class (not an instance) defined in the corresponding module.

```python
from plugins.plugin_loader import PluginLoader

# Load the Original model class

ModelCls = PluginLoader.get_model("original")

# Returns: <class 'plugins.train.model.original.Model'>

# Instantiate with default configuration

model = ModelCls()

# Access the underlying Keras model via model.model

```

The model instance encapsulates the neural network graph, typically stored in the `model` attribute as a Keras/TensorFlow model object.

### Loading a Trainer

Trainers orchestrate the training loop. Use `PluginLoader.get_trainer(name)` to retrieve the trainer class, then instantiate it with a model instance and training parameters.

```python

# Load the Original trainer

TrainerCls = PluginLoader.get_trainer("original")

# Returns: <class 'plugins.train.trainer.original.Trainer'>

# Instantiate with model and batch configuration

trainer = TrainerCls(model=model, batch_size=8)

```

The trainer implements the `train_batch` method (defined abstractly in `TrainerBase`) to handle forward passes, loss computation, and backpropagation.

### Loading a Converter

Converters handle post-processing and output generation. The loader requires a category (e.g., `"writer"`) and a plugin name.

```python

# Load the Pillow image writer

WriterCls = PluginLoader.get_converter("writer", "pillow")

# Returns: <class 'plugins.convert.writer.pillow.Writer'>

# Instantiate with output directory

writer = WriterCls(output_folder="/tmp/output")

```

Writer plugins inherit from the `Output` base class in [`plugins/convert/writer/_base.py`](https://github.com/deepfakes/faceswap/blob/main/plugins/convert/writer/_base.py) and implement `pre_encode`, `write`, and optional `close` methods.

## Plugin Contracts and Base Classes

Each FaceSwap plugin type enforces a contract through abstract base classes located in `_base` modules. These contracts ensure that the core application can interact with plugins without knowing their specific implementations.

### ModelBase in plugins/train/model/_base/update.py

The `ModelBase` class defines the interface for neural network architectures. Concrete models like `Original` in [`plugins/train/model/original.py`](https://github.com/deepfakes/faceswap/blob/main/plugins/train/model/original.py) and `PhazeA` in [`plugins/train/model/phaze_a.py`](https://github.com/deepfakes/faceswap/blob/main/plugins/train/model/phaze_a.py) inherit from this base. The base class typically specifies methods for building the network graph, saving and loading weights, and configuring input/output shapes.

### TrainerBase in plugins/train/trainer/_base.py

`TrainerBase` establishes the training loop contract. It declares abstract methods such as `train_batch` that subclasses must implement. The `original` trainer in [`plugins/train/trainer/original.py`](https://github.com/deepfakes/faceswap/blob/main/plugins/train/trainer/original.py) provides a concrete implementation handling TensorFlow/Keras training operations, including gradient computation and optimizer steps.

### Output Base Class for Converters

For conversion plugins, the `Output` base class in [`plugins/convert/writer/_base.py`](https://github.com/deepfakes/faceswap/blob/main/plugins/convert/writer/_base.py) defines the interface for output generation. Writers such as [`pillow.py`](https://github.com/deepfakes/faceswap/blob/main/pillow.py) implement `pre_encode` (frame preparation), `write` (actual file output), and `close` (resource cleanup). This structure allows the conversion pipeline to switch between different output formats without modifying the core logic.

## Summary

- The FaceSwap plugin system uses a central **PluginLoader** class in [`plugins/plugin_loader.py`](https://github.com/deepfakes/faceswap/blob/main/plugins/plugin_loader.py) to dynamically import model, trainer, and converter classes at runtime.
- Plugins reside in specific subdirectories: `plugins/train/model/` for architectures, `plugins/train/trainer/` for training loops, and `plugins/convert/<category>/` for post-processing.
- The loader enforces strict naming conventions: hyphenated names normalize to underscores for modules, and class names must be title-cased versions of the module name (e.g., [`original.py`](https://github.com/deepfakes/faceswap/blob/main/original.py) contains class `Original`).
- Each plugin type implements a specific abstract base class—**ModelBase**, **TrainerBase**, or **Output**—ensuring consistent interfaces for the core application.
- Discovery methods like `get_available_models()` and `get_available_convert_plugins()` enable runtime enumeration of available extensions without hardcoding.

## Frequently Asked Questions

### How does FaceSwap discover new plugins without modifying the core code?

FaceSwap discovers plugins by scanning specific filesystem directories at runtime. The `PluginLoader` walks the `plugins/train/model/`, `plugins/train/trainer/`, and `plugins/convert/<category>/` directories, looking for Python files that do not start with an underscore. When a new file following the naming conventions is added to these directories, it becomes immediately available through the loader methods without requiring changes to the central configuration or import statements.

### What naming convention must a FaceSwap plugin follow to load correctly?

A FaceSwap plugin must follow a strict naming convention where the module filename uses lowercase with underscores (e.g., [`my_model.py`](https://github.com/deepfakes/faceswap/blob/main/my_model.py) or [`phaze_a.py`](https://github.com/deepfakes/faceswap/blob/main/phaze_a.py)), and the main class inside that file must be the title-cased version of the filename without the extension (e.g., `MyModel` or `PhazeA`). Additionally, any hyphens in the requested plugin name are normalized to underscores before import (e.g., requesting `"my-model"` loads [`my_model.py`](https://github.com/deepfakes/faceswap/blob/main/my_model.py)).

### Can I use a custom trainer with an existing model in FaceSwap?

Yes, the FaceSwap plugin system decouples models from trainers, allowing you to mix and match compatible implementations. You can load an existing model architecture using `PluginLoader.get_model("original")` and then load a different trainer using `PluginLoader.get_trainer("custom")`, provided the custom trainer inherits from `TrainerBase` in [`plugins/train/trainer/_base.py`](https://github.com/deepfakes/faceswap/blob/main/plugins/train/trainer/_base.py) and implements the required `train_batch` method with the expected signature for the model's data format.

### Where are the base classes defined that FaceSwap plugins must implement?

The base classes that define the plugin contracts are located in `_base` modules within each plugin category. For models, the base class `ModelBase` is defined in [`plugins/train/model/_base/update.py`](https://github.com/deepfakes/faceswap/blob/main/plugins/train/model/_base/update.py). For trainers, `TrainerBase` is located in [`plugins/train/trainer/_base.py`](https://github.com/deepfakes/faceswap/blob/main/plugins/train/trainer/_base.py). For converter writers and other conversion plugins, the `Output` base class is found in [`plugins/convert/writer/_base.py`](https://github.com/deepfakes/faceswap/blob/main/plugins/convert/writer/_base.py). These abstract base classes specify the methods and properties that concrete plugins must implement to integrate with the FaceSwap pipeline.