FlashPortrait Feature Extractor
Turning a Driving Video Into a Face Script
- face_align_models
- images
- head_emo_features
- fps
- total_frames
Your reference image gives FlashPortrait the face. This node gives it the acting. The Feature Extractor reads the driving video you feed in, finds the face in every frame, and compresses head pose, eye movement, expression, and mouth motion into a single per-frame feature vector - the "script" the sampler later follows to animate your portrait. It's the quiet middle step, and the one beginners most often skip, because the nodes it sits between are so much more obvious.
Why this split matters
Here's the design decision that makes FlashPortrait work, straight from the paper: it's identity-agnostic. The extractor deliberately does not care whose face is in the driving video. It only pulls out motion and expression. The identity lives entirely in your reference image, which stays on the other side of the workflow. That separation is why the model can hold a face's likeness over hundreds of frames without it drifting into a zombie - the very thing its direct competitors visibly fail at (the release thread's top comment was literally about a rival turning the subject into a zombie by the end).
How it works
The node takes FACE_ALIGN_MODELS from the Loader (the onnx face-detection + landmark files and the PD-FGC model) and runs two passes over your frames: landmark detection and alignment, then expression extraction that produces eye, emotion, and mouth embeddings per frame. Each frame's embeddings get concatenated with a head-pose embedding into one head_emo vector. It also does two bits of bookkeeping you should know about:
- Frames are trimmed so the count satisfies
(N-1) % 4 == 0, which the Wan VAE's 4× temporal compression needs. A 53-frame clip silently becomes 49. - If your clip is shorter than
context_size, it pads by repeating the last frame's features rather than erroring.
Note what it does not do: it extracts features for the whole video up front and hands the full stack to the sampler. The sliding-window stuff - where the "infinite length" actually happens - lives in the sampler, which re-walks these features in overlapping chunks.
The inputs and outputs that matter
- images - your driving video frames. Hook up
Load Video(or any node that outputs anIMAGEbatch) and feed it frames here. This is the motion source; your actual portrait's face never touches this node. - source_fps - default 25. It just gets passed through to the output so whatever saves your video knows the playback rate, but get it roughly right.
- context_size (51) and context_overlap (30) - these define the sliding-window stride (
context_size − context_overlap). Keep them identical to the sampler's - both nodes take these inputs and they're describing the same window, so mismatched values mean the extractor and sampler are walking different chunks of the same video. - Outputs: head_emo_features (
HEAD_EMO_FEAT) → the sampler'shead_emo_featuresinput. fps → downstream video nodes. total_frames → how many frames your animation will be, useful for setting up the save node.
Installing and running it
Same story as the rest of the pack: ComfyUI Manager (search "FlashPortrait") or git clone https://github.com/okdalto/ComfyUI-FlashPortrait into custom_nodes, install requirements.txt, restart. The extractor itself is the lightweight node of the three - the heavy memory lives in the Loader and the Sampler, so this one runs fast once the models are in.
A couple of practical notes: the extractor works on whatever you feed it, so a clean, single-face, well-lit driving clip gets you dramatically better expression capture than a chaotic one. And don't over-think it - for a first run, leave context_size and context_overlap at their defaults and just match the sampler to them. The defaults are the author's tested values, and the model's own config uses them too.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| face_align_models | FACE_ALIGN_MODELS | — | |
| images | IMAGE | — | |
| source_fps | FLOAT | 25.00 | — |
| context_size | INT | 51 | — |
| context_overlap | INT | 30 | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| head_emo_features | HEAD_EMO_FEAT | — |
| fps | FLOAT | — |
| total_frames | INT | — |