FaceSwap scripts 包深度解析:faceswap.py 子命令分发与 extract/train/convert/gui 五大入口模块
本文以 FaceSwap 的 Sphinx API 文档 docs/full/scripts.rst 为主体,系统讲解 scripts 包作为整个项目入口的架构设计:从 faceswap.py 如何注册 extract、train、convert、gui 四个子命令,到 scripts/extract.py、scripts/train.py、scripts/convert.py、scripts/fs_media.py、scripts/gui.py 五个模块各自的职责、关键类与底层依赖关系。读完本文,你将能够理解 FaceSwap 命令行与 GUI 两种使用方式如何共享同一套处理管线,并能在源码层面定位每个子命令的入口实现。
一、scripts 包:Faceswap 的统一入口
docs/full/scripts.rst 开篇给出了一句核心定位:
The Scripts Package is the entry point into Faceswap.(scripts 包是进入 Faceswap 的入口)
该文档通过五个 Sphinx automodapi 指令分别展开五个模块的 API 文档:
| RST 指令 | 对应模块 | 职责 |
|---|---|---|
automodapi:: scripts.convert |
scripts/convert.py | 换脸转换主流程(源画面 → 模型推理 → 后处理合成) |
automodapi:: scripts.extract |
scripts/extract.py | 从图片/视频中检测人脸并裁剪出训练样本 |
automodapi:: scripts.fs_media |
scripts/fs_media.py | extract 与 convert 共享的媒体对象(Alignments)及统计输出 |
automodapi:: scripts.gui |
scripts/gui.py | 可选的 tkinter 图形界面 |
automodapi:: scripts.train |
scripts/train.py | 训练人脸交换模型的主流程 |
scripts 目录内除了上述五个文件外还有一个空的 scripts/__init__.py,用于将目录声明为 Python 包。
这里有一个值得注意的文档生成约定:五个模块文件末尾都写有
__all__ = get_module_objects(__name__)
(例如 scripts/gui.py、scripts/fs_media.py)。get_module_objects 来自 lib.utils,它扫描当前模块收集顶层定义写入 __all__。这样做的直接收益是:automodapi 指令配合 :include-all-objects: 选项即可自动把模块内所有公开类/函数纳入 API 文档,无需手工维护对象列表。这也是五个模块能被 docs/full/scripts.rst 一篇 RST 统一覆盖的原因。
二、总入口 faceswap.py:子命令注册与参数分发
虽然 scripts.rst 的主题是 scripts 包本身,但要理解这五个模块如何被调用,必须先看清根目录的 faceswap.py。它的 _main 函数(faceswap.py#L37-L57)完成了三件事:
- 生成配置文件:调用
generate_configs()(来自lib.config)。首次运行任意子命令后,会在config/目录下生成extract.ini、train.ini、convert.ini等插件配置文件——这也是 USAGE.md 中“需要至少运行过一次 Extract 或 GUI 才能看到 ini 文件”这一说法的源码出处。 - 构建参数解析器:使用
cli_args.FullHelpArgumentParser()创建支持完整帮助的解析器,然后通过add_subparsers()注册四个子命令,每个子命令绑定一组参数类和一个处理函数:
subparser = _PARSER.add_subparsers()
ExtractArgs(subparser, "extract", _("Extract the faces from pictures or a video"))
TrainArgs(subparser, "train", _("Train a model for the two faces A and B"))
ConvertArgs(subparser, "convert", _("Convert source pictures or video to a new one with the face swapped"))
cli_args.GuiArgs(subparser, "gui", _("Launch the Faceswap Graphical User Interface"))
_PARSER.set_defaults(func=_bad_args)
arguments = _PARSER.parse_args()
arguments.func(arguments)
注意 _PARSER.set_defaults(func=_bad_args):当用户没有提供有效子命令时,会打印帮助并退出(_bad_args 定义于 faceswap.py#L30-L34)。解析完成后,arguments.func(arguments) 这一行把参数命名空间交给各子命令对应的处理函数,最终分别实例化 scripts 包中对应的 Extract()、Train()、Convert()、Gui() 类并执行——这正是“scripts 包是入口”这句话的完整链路。
- 环境与国际化准备:入口处还通过
System().validate_python()校验 Python 版本,并使用gettext加载locales/下的翻译(对 Windows 平台通过ctypes修补LANG环境变量,见 faceswap.py#L8-L12)。
对应的四个用户侧命令(摘自 USAGE.md):
python faceswap.py extract -i ~/faceswap/src/trump -o ~/faceswap/faces/trump
python faceswap.py train -A ~/faceswap/faces/trump -B ~/faceswap/faces/cage -m ~/faceswap/trump_cage_model/
python faceswap.py convert -i ~/faceswap/src/trump/ -o ~/faceswap/converted/ -m ~/faceswap/trump_cage_model/
python faceswap.py gui
每个子命令都支持 -h 查看完整参数,例如 python faceswap.py extract -h。
三、scripts.extract:人脸检测与训练样本生成
scripts/extract.py 是“从原始素材中提取可用训练样本”的模块。从源码头部导入即可看清它的能力边界与依赖:
from lib.align.aligned_utils import (batch_adjust_matrices, batch_align, batch_resize,
batch_transform, get_adjusted_center, get_sub_crop_size)
from lib.align.constants import EXTRACT_RATIOS, LandmarkType, MEAN_FACE
from lib.infer import Detect, Align, Identity, Mask, File, Profiler
from lib.infer.identity import FilterLoader
from .fs_media import Alignments, finalize
几个关键信息:
- 检测与对齐插件体系:
from lib.infer import Detect, Align, Identity, Mask, File, Profiler表明 extract 阶段的检测器(Detect)、对齐器(Align)、身份过滤(Identity)、分割(Mask)、文件导入(File)与性能剖析(Profiler)均以插件形式注入。其中File插件允许直接复用已有的 alignments JSON 文件,而不是重新检测——这与 scripts/fs_media.py 中plugin_is_file参数的作用相呼应。 - 批处理管线:模块内定义了
BatchInfo数据类,持有当前批次的loader(图片加载器)与alignments(对齐数据),说明 extract 是按批(batch)驱动的检测→对齐→裁剪→保存流程,配合lib.multithreading.FSThread实现多线程处理。 - 几何工具:
batch_align、batch_resize、get_sub_crop_size等批量几何变换函数,对应 USAGE.md 中“识别人脸关键点、把图像裁剪到一致尺寸并保存到输出目录”的描述。
典型用法(来自 USAGE.md):
# 从图片文件夹提取
python faceswap.py extract -i ~/faceswap/src/trump -o ~/faceswap/faces/trump
# 从视频文件提取
python faceswap.py extract -i ~/faceswap/src/trump.mp4 -o ~/faceswap/faces/trump
输出为裁剪好的人脸图片,同时在输入目录生成 alignments.json(faceswap 内部格式为 alignments.fsa),记录每张脸的位置、关键点等信息,供后续 train/convert 阶段使用。官方文档给出的建议是:每个主体收集约 500–5000 张高质量、角度/表情/光照多样的样本,且不要从视频中抽取每一帧(相邻帧高度相似)。插件的细粒度配置项保存在 config/extract.ini(首次运行后生成)。
四、scripts.train:模型训练主循环
scripts/train.py 定义了 Train 类,其 docstring 明确职责:“训练一个模型,使源人脸集合(A)与目标人脸集合(B)之间可以互换”。核心实现要点:
- 训练器与预览:模块从
lib.training导入Trainer、Preview、PreviewBuffer、TriggerType,并引用plugins.train.trainer.base的TrainConfig。也就是说 train 脚本本身是编排层:真正的前向/反向计算发生在插件体系(模型、增强、损失等由config/train.ini选择与配置)中。 - 最低图片数校验:源码中存在类方法
_validate_image_counts,校验每侧文件夹至少有 24 张图片——注释说明这不足以训练出成功模型,但足以让流程不报错地生成预览,属于“快速试跑”兜底。 - GUI 联动触发器:
__init__中会创建lib/gui/.cache下的.preview_mask_toggle与.preview_trigger文件路径,用于 GUI 侧点击按钮后触发“切换 mask / 刷新预览”等事件,体现 CLI 与 GUI 共享同一处理类的架构。 - 优雅停止:模块导入
lib.keypress.KBHit,对应 USAGE.md 说明的“在预览窗口或控制台按 Enter 即可停止训练,模型会保存后退出”;训练模型约每 100 次迭代自动保存一次,loss 下降时还会备份(.bk扩展名),可随时中断并从同一目录恢复训练。
标准命令:
python faceswap.py train -A ~/faceswap/faces/trump -B ~/faceswap/faces/cage -m ~/faceswap/trump_cage_model/
# 加 -p 开启实时预览窗口
python faceswap.py train -A ... -B ... -m ... -p
完整参数列表通过 python faceswap.py train -h 查看;若使用 mask 或 Warp to Landmarks 等功能,需要为每个人脸集合传入对应的 alignments 文件。
五、scripts.convert:推理与后处理管线
scripts/convert.py 是“把训练好的模型应用到源画面”的模块,头部 docstring 即声明其为 convert 流程的主入口。源码结构上有两个值得注意的设计:
ConvertItem数据类——描述一帧画面在整个转换管线中流转时携带的状态:
@dataclass
class ConvertItem:
"""A single frame with associated objects passing through the convert process."""
inbound: FrameFaces
feed_faces: list[AlignedFace] = field(default_factory=list)
reference_faces: list[AlignedFace] = field(default_factory=list)
swapped_faces: np.ndarray = field(default_factory=lambda: np.array([]))
inbound 是从磁盘加载的帧及其 DetectedFace 列表;feed_faces/reference_faces 是送入模型 predict 的输入脸与参考脸;swapped_faces 是模型输出的换脸结果。这个数据类清晰地勾勒出“检测 → 对齐 → 推理 → 后处理”的逐帧流水线。
Convert类与Converter:Convert的 docstring 说明其“负责把源帧的人脸替换为训练模型的输出,并调用一系列用户选定的后处理插件,这些插件由lib.convert.Converter执行”。后处理插件(如肤色匹配、边缘融合等)由plugins/plugin_loader.PluginLoader按config/convert.ini的配置动态加载。
convert 的前置条件是:源视频/图片目录必须已有 alignments 文件(即先用 extract 对源素材跑一遍检测,并建议清理误检与对齐失败的条目),否则 convert 无从知道脸在哪里。标准命令:
python faceswap.py convert -i ~/faceswap/src/trump/ -o ~/frameswap/converted/ -m ~/faceswap/trump_cage_model/
与 extract 一样支持图片目录与视频两种输入,python faceswap.py convert -h 可查看完整参数。
六、scripts.fs_media:extract 与 convert 共享的媒体层
scripts/fs_media.py 的模块 docstring 说明它“持有 Faceswap 两个主要媒体对象(Images 与 Alignments)的类,并提供 convert/extract 的可选前后处理函数”。该文件体量不大但逻辑关键,包含两部分:
1. finalize() 汇总输出(scripts/fs_media.py#L25-L43):extract 与 convert 结束后统一打印统计——
Images found: <处理的图片/帧数>
Faces detected: <检测到的人脸数>
并当有单帧检测到多张脸时提示“Double check your results.”(请仔细核对结果)。
2. Alignments 类(scripts/fs_media.py#L46-L237):继承自 lib.align.Alignments,核心作用是根据命令行参数定制 alignments 文件的加载与保存行为。其构造参数本身就是一个很好的“行为开关”说明书:
| 参数 | 含义 |
|---|---|
location |
alignments 文件完整路径;None 时从源文件位置推导 |
source_location |
源媒体路径(图片文件夹或视频文件) |
is_extract |
调用方是否为 extract 流程 |
skip_existing_frames / skip_existing_faces |
extract 时“跳过已有帧 / 跳过已有脸”两个开关 |
plugin_is_file |
检测/对齐是否选择了 File 插件(即从 JSON 导入) |
save_alignments |
流程结束时是否保存 alignments |
input_is_video |
输入是否为视频 |
命名推导逻辑在 _set_folder_filename(scripts/fs_media.py#L102-L162)中:
- 未显式指定
location且输入是视频:alignments 文件与视频同目录,命名为<视频名>_alignments; - 输入是图片文件夹:文件直接叫
alignments,存放在图片文件夹内; - 指定了
.json后缀但检测/对齐插件并非 File 插件时,直接报错退出(“Json files are only valid with 'File' detect/align plugins”); - 使用 File 插件但找不到对应文件时,同样报错退出并提示检查路径。
JSON 导入逻辑在 _import_from_json(scripts/fs_media.py#L206-L237):当外部 JSON 中某张脸缺少 detected(检测框)字段时,会断言其 landmarks_2d 恰好为 4 个 ROI 关键点,并把检测框直接设为该 ROI 的外接矩形——这对应“仅使用 4 点 ROI 关键点的外部标注”这一使用场景;导入过程中会把每张脸重建为 FileAlignments 对象并写回 AlignmentsEntry。此外,_load 的重写处理了“跳过已有帧/脸”的断点续跑语义,以及在 JSON 导入与已有 .fsa 文件共存时自动备份原文件的保护逻辑(self.backup())。
七、scripts.gui:tkinter 图形界面
scripts/gui.py 实现可选 GUI,仅两个类:
FaceswapGui(tk.Tk)(scripts/gui.py#L17-L183):主窗口。构造时依次完成:加载.ini配置(cfg.load_config)→ 初始化全局常量与字体 → 设置 1200×640 窗口几何 → 清空预览缓存 → 注册WM_DELETE_WINDOW关闭钩子 → 构建界面。build_gui方法(scripts/gui.py#L65-L88)按“TaskBar(任务栏)+ CommandNotebook(命令选项卡,即 extract/train/convert 的选项面板)+ DisplayNotebook(预览显示区)+ ConsoleOut(控制台输出)”四大组件搭建布局,全部组件来自lib.gui(TaskBar、CliOptions、CommandNotebook、ConsoleOut、DisplayNotebook、ProcessWrapper、StatusBar等)。- 配置变更重绘:
rebuild方法在配置变化时保存LastSession会话状态、销毁并重建所有子组件,再恢复会话状态; - 安全关闭:
close_app会在有任务运行时弹出确认框,确认后通过wrapper.task.terminate()终止后台进程,再保存最后会话并退出。
- 配置变更重绘:
Gui(scripts/gui.py#L186-L194):供faceswap.py gui子命令调用的薄封装,__init__创建FaceswapGui,process()进入mainloop()。
GUI 的价值在于把 CLI 的全部参数以可视化选项面板形式呈现(悬停可见帮助文字),并额外提供预览刷新、mask 切换等交互能力——这也解释了 train 模块中 .preview_trigger 等触发器文件为何存在。启动方式:
python faceswap.py gui
八、scripts 包的统一编码约定
对比五个模块,可以归纳出 scripts 包的一贯风格,这对阅读与扩展代码很有帮助:
- 懒类型导入:
if T.TYPE_CHECKING:块内导入argparse.Namespace、ModelBase等仅用于类型注解的类,运行时零开销; - 调试日志规范:每个模块定义
logger = logging.getLogger(__name__),类初始化用lib.logger.parse_class_init(locals())一行记录全部构造参数; - 废弃参数兼容:extract/train/convert 均在构造时调用
handle_deprecated_cli_opts(arguments)(来自lib.utils)迁移旧版命令行参数; - 自包含原则:各 docstring 均声明“self contained and should not be referenced by any other scripts”(自包含、不应被其他脚本引用),模块间唯一的横向依赖是
scripts/fs_media.py被 extract/convert 复用; __all__自动生成:get_module_objects(__name__)统一收尾,支撑 Sphinx 自动文档化。
九、小结:入口、模块与命令的对应关系
| 子命令 | 入口类 | 源码文件 | 共享/支撑组件 |
|---|---|---|---|
extract |
Extract |
scripts/extract.py | lib.infer 插件、scripts/fs_media.py |
train |
Train |
scripts/train.py | lib.training.Trainer、预览触发器 |
convert |
Convert |
scripts/convert.py | lib.convert.Converter 后处理链 |
gui |
Gui / FaceswapGui |
scripts/gui.py | lib.gui 组件族、lib.utils |
docs/full/scripts.rst 的五个 automodapi 指令正是围绕这张分工表展开:scripts 包是 Faceswap 的唯一入口层,faceswap.py 负责参数分发,五个模块分别承接提取、训练、转换、界面四大功能,而 fs_media 作为横切的媒体层保证 alignments 数据的加载、导入与保存行为在 extract 与 convert 之间保持一致。理解了这一分层,再配合 USAGE.md 中的标准工作流(extract → train → convert),即可在源码与命令行两个层面完整把握 FaceSwap 的运行机制。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00