1st movie clip!
Hmm… Although this seems to be a known issue that occasionally occurs in practice, isolating the problem is essential to finding a solution:
What I think is happening
This no longer looks like a simple “wrong FPS” problem.
It looks much more like a frame-sequence integrity problem, with ReActor face-tracking/detection weakness layered on top.
The clearest current match is this ReActor discussion:
- Frame skipping issues #150 - Gourieff/ComfyUI-ReActor
That thread is very close to your symptom:
- face swap can look fine at first
- then frames get skipped/cut
- especially when the face turns or becomes harder to detect
And the practical advice there is important:
split the video into frames, do face swap as a batch image process, then reconstruct the video.
That is not just theory. It is the most relevant “similar case → recommended workflow change” I found.
There is also this feature request:
- Face Tracking when position changes throughout video #130 - Gourieff/ComfyUI-ReActor
That matters because it tells you directly that stable face-lock over time is still a weak point in this toolchain.
Why changing FPS does not fix the jump
This part actually makes sense once you separate frame loading from video playback.
According to the VideoHelperSuite docs:
force_ratecan discard or duplicate framesframe_load_capsets the maximum number of frames returnedskip_first_framesoffsets the startselect_every_nthintentionally skips framesVideo Combine.frame_rateonly changes how many input frames are shown per second
Relevant sources:
- ComfyUI-VideoHelperSuite README
- VHS_LoadVideo docs
- ComfyUI-VideoHelperSuite detailed guide
So if the sequence is already damaged before Video Combine, then changing output FPS will only:
- speed it up
- slow it down
- shorten it
- lengthen it
It will not recreate missing motion continuity.
That is why your tests feel maddening:
- the face swap can still look correct
- but the motion still jumps
- and FPS only changes playback speed
That behavior is exactly what the docs would predict.
The two most likely causes in your case
Cause 1 — ReActor is not handling all frames equally well
This is most likely when:
- the face turns
- the face gets smaller
- the face blurs
- the face shifts position
- the face becomes partially occluded
That is the closest match to the ReActor frame-skipping discussion.
Cause 2 — the workflow is not feeding the exact frame batch you think it is
This is most likely when:
frame_load_capis too lowskip_first_framesis not what you thinkselect_every_nthis not1force_rateis changing cadence- preview and output do not match
This is not hypothetical. There is a current VideoHelperSuite issue specifically about preview/output mismatch when select_every_nth and skip_first_frames are used:
- “select_every_nth” and “skip_first_frames” mismatch #497
So you can absolutely end up debugging the wrong segment if the frame-loading settings are not clean.
The core rule for debugging
Treat the workflow as three separate jobs :
- Load the correct frames
- Swap the faces on those frames
- Play those frames back as video
Right now, job 3 is probably not the main problem.
Jobs 1 and 2 are.
That is why the best next step is not “try more FPS values.” It is “prove the frame sequence is intact.”
The anchor number you should keep in mind
A clip that is:
- 6 seconds
- at 12 FPS
should contain about:
- 72 frames
That is the number to keep checking against.
Your main question for every test is:
did roughly 72 frames enter the graph, and did the same number survive?
Revised workflow plan
Do these in order.
Do not jump ahead.
Do not change extra settings while testing.
Test 1 — Full-clip truth test
Goal
Prove whether the simplest path
Load Video -> ReActor -> Video Combine
can preserve the full clip cleanly.
Use this exact graph
- Load reference image
- Load video
- ReActor
- Video Combine
For this test:
- No RIFE
- No MetaBatch
- No extra repair nodes
- No extra helpers
Keep it as plain as possible.
Exact settings
| Node | Setting | Value to test first | Why |
|---|---|---|---|
Load Video |
force_rate |
0 or 12 |
0 keeps source cadence; 12 is okay if you want to lock to source. Avoid forcing some other rate while debugging. |
Load Video |
frame_load_cap |
0 or 72+ |
You do not want to accidentally cap a 72-frame clip below full length. |
Load Video |
skip_first_frames |
0 |
No offset. Start at the beginning. |
Load Video |
select_every_nth |
1 |
This means “use every frame.” |
Load Video |
Advanced Preview |
ON |
VHS docs say Advanced Preview reflects settings like skip_first_frames and frame_load_cap. |
ReActor |
face-swap settings | leave unchanged | First prove sequence stability before retuning the swap. |
Video Combine |
frame_rate |
12 |
Match the source/loaded sequence. |
What to look for
After running Test 1, check:
- Does the Load Video preview look like the full expected clip?
- Does the output feel like the full 6 seconds?
- Or does it already feel like only part of the motion survived?
How to interpret it
If Test 1 is already jumpy:
- the problem is already present in the basic path
- so it is not mainly RIFE
- and it is not mainly final playback FPS
That points to:
- face detection/tracking weakness
- frame-load mismatch
- or both
If Test 1 is smooth:
- your simplest path is okay
- later helpers or chunk boundaries are the more likely problem
Test 2 — Tail-only chunk test
Goal
Find out whether the workflow is length-sensitive.
This is the most useful test for your use case, because you only need to repair the broken tail of the clip anyway.
The VideoHelperSuite docs explicitly support processing videos in parts using:
frame_load_capskip_first_frames
Relevant source:
- ComfyUI-VideoHelperSuite README
Keep the graph the same
Still use only:
- Load reference image
- Load video
- ReActor
- Video Combine
Still:
- No RIFE
- No MetaBatch
Test 2A — Last 24 frames
| Node | Setting | Value |
|---|---|---|
Load Video |
force_rate |
0 or 12 |
Load Video |
frame_load_cap |
24 |
Load Video |
skip_first_frames |
48 |
Load Video |
select_every_nth |
1 |
Load Video |
Advanced Preview |
ON |
ReActor |
face-swap settings | unchanged |
Video Combine |
frame_rate |
12 |
Test 2B — Last 36 frames
| Node | Setting | Value |
|---|---|---|
Load Video |
force_rate |
0 or 12 |
Load Video |
frame_load_cap |
36 |
Load Video |
skip_first_frames |
36 |
Load Video |
select_every_nth |
1 |
Load Video |
Advanced Preview |
ON |
ReActor |
face-swap settings | unchanged |
Video Combine |
frame_rate |
12 |
Test 2C — Last 48 frames
| Node | Setting | Value |
|---|---|---|
Load Video |
force_rate |
0 or 12 |
Load Video |
frame_load_cap |
48 |
Load Video |
skip_first_frames |
24 |
Load Video |
select_every_nth |
1 |
Load Video |
Advanced Preview |
ON |
ReActor |
face-swap settings | unchanged |
Video Combine |
frame_rate |
12 |
What you are trying to learn
You are asking:
- Can ReActor handle the last 24 frames cleanly?
- Can it handle the last 36 frames?
- Does it begin failing again at 48?
How to interpret it
If 24 works, 36 works, and 48 fails:
- the workflow is probably length-sensitive
- not fundamentally broken
If even 24 fails:
- the problem is more likely tied to:
- face detection in that part of the clip
- preview/output mismatch
- or remaining runtime fragility
This test is extremely useful because it turns a vague “sometimes it jumps” problem into a measurable one.
Test 3 — Frame-batch repair workflow
Goal
Stop hiding the real unit of work.
This is the biggest workflow improvement I would consider if Test 2 still shows instability.
The most direct ReActor advice for frame skipping is:
split the video into frames, do face swap as a batch image process, then reconstruct the video
Source:
- Frame skipping issues #150 - Gourieff/ComfyUI-ReActor
Why this helps
Because it makes everything explicit:
- you can inspect the actual frames
- you can see exactly where the swap starts failing
- you can rerun only a bad chunk
- you remove a lot of uncertainty about whether the loader/combine changed the sequence
Revised graph
- Load reference image
- Load video
- ReActor on the image batch
- Save the swapped frames
- Rebuild / combine video
- Only later, optionally add interpolation
Exact settings for the first frame-batch test
Use the safest tail chunk first:
| Node | Setting | Value |
|---|---|---|
Load Video |
force_rate |
0 or 12 |
Load Video |
frame_load_cap |
24 |
Load Video |
skip_first_frames |
48 |
Load Video |
select_every_nth |
1 |
Load Video |
Advanced Preview |
ON |
ReActor |
face-swap settings | unchanged |
Save Image |
output | save the swapped frame batch |
Video Combine |
frame_rate |
12 |
What to do
- Process the last 24 frames.
- Save the swapped images.
- Inspect them as images.
- Check:
- are all frames present?
- do they look sequential?
- does the face break at one specific frame?
- does the frame count look right?
- If that is good, try 36 , then 48.
Why this is so useful
This tells you directly:
- whether the loader is giving the right frames
- whether ReActor is breaking on specific frames
- whether the jump is already present before final video combine
That is why this workflow is often more reliable than direct video-in/video-out when temporal instability appears.
After the three tests
Add overlap instead of a hard join
Once one workflow is stable, process more frames than the absolute minimum you think you need.
Example:
- if you think you only need the last 12 frames repaired,
- actually process the last 24–36 frames,
- then keep the cleanest part in the final assembly if needed
Why: continuation discussions around Wan/VACE say that overlap helps preserve motion continuity better than a hard boundary, with one reply suggesting about 15 frames depending on motion.
Relevant discussion:
- Wan 2.2 - Best practices to continue videos
For your workflow, the lesson is simple:
- hard joins are fragile
- overlap is safer
Reintroduce RIFE only after the raw sequence is stable
Do not use RIFE as the first rescue tool while the raw swapped sequence is still unstable.
There is a current VideoHelperSuite issue showing that RIFE + MetaBatch can lose one frame per batch, shortening the output and causing desync, and that the correct fix there is 1-frame overlap between batches.
Source:
- RIFE + MetaBatch drops one frame per batch #625
Even if you are not using MetaBatch right now, the lesson still matters:
- interpolation is another temporal process
- so only add it after the raw swapped frames are already stable
The order should be:
- stable raw swapped frames
- stable raw swapped clip
- then interpolation for polish
One-page copy-paste checklist
TEST 1 — FULL CLIP
Source clip: 6 sec @ 12 FPS (~72 frames)
Load Video:
- force_rate = 0 or 12
- frame_load_cap = 0 or >=72
- skip_first_frames = 0
- select_every_nth = 1
- Advanced Preview = ON
ReActor:
- leave current face-swap settings unchanged
Video Combine:
- frame_rate = 12
Goal:
- prove full-sequence stability
TEST 2A — LAST 24 FRAMES
Load Video:
- force_rate = 0 or 12
- frame_load_cap = 24
- skip_first_frames = 48
- select_every_nth = 1
- Advanced Preview = ON
ReActor:
- leave current face-swap settings unchanged
Video Combine:
- frame_rate = 12
Goal:
- test short tail stability
TEST 2B — LAST 36 FRAMES
Load Video:
- force_rate = 0 or 12
- frame_load_cap = 36
- skip_first_frames = 36
- select_every_nth = 1
- Advanced Preview = ON
ReActor:
- leave current face-swap settings unchanged
Video Combine:
- frame_rate = 12
Goal:
- test medium tail stability
TEST 2C — LAST 48 FRAMES
Load Video:
- force_rate = 0 or 12
- frame_load_cap = 48
- skip_first_frames = 24
- select_every_nth = 1
- Advanced Preview = ON
ReActor:
- leave current face-swap settings unchanged
Video Combine:
- frame_rate = 12
Goal:
- test longer tail stability
TEST 3 — FRAME-BATCH VERSION
Load Video:
- force_rate = 0 or 12
- frame_load_cap = 24 (start here)
- skip_first_frames = 48
- select_every_nth = 1
- Advanced Preview = ON
ReActor:
- leave current face-swap settings unchanged
Save swapped frames:
- inspect as individual images
Video Combine:
- frame_rate = 12
Goal:
- inspect exact frames and remove video-sequence ambiguity
Final recommendation
If this were my setup, I would do this in order:
- Run Test 1 exactly as written
- Run Test 2 in this order:
- last 24 frames
- last 36 frames
- last 48 frames
- If direct video swap still jumps, move immediately to Test 3
- Once one path is stable, add overlap
- Only then add RIFE
That is the most grounded, least wasteful path I can justify from the current docs and issue threads.
It is also the best way to stop guessing.
Discussion in the ATmosphere