How Deep-Live-Cam Implements Frame Interpolation for Temporal Smoothing in Live Mode

Deep-Live-Cam reduces flicker in live face-swap streams by alpha-blending each processed frame with the previous one using a configurable weight, implementing this temporal smoothing inside apply_post_processing in modules/processors/frame/face_swapper.py.

Deep-Live-Cam is an open-source real-time deepfake application that streams face-swapped video with minimal latency. To prevent flickering and jitter between frames, the repository implements frame interpolation for temporal smoothing in live mode by maintaining a cached copy of the previous output frame and blending it with the current result. This stateful approach creates a temporal chain that stabilizes the visual output without expensive optical flow calculations.

Global Configuration Settings

The interpolation feature is governed by two global variables defined in modules/globals.py (lines 67-70):

  • enable_interpolation – A boolean flag (default True) that toggles the feature on or off.
  • interpolation_weight – A float value (default 0) between 0 and 1 that controls the blend ratio. Lower values increase smoothing by favoring the previous frame, while higher values prioritize the current frame.

These settings can be modified via the UI or programmatically before processing begins.

The Temporal Smoothing Pipeline

Post-Processing Hook

After face detection and swapping complete in process_frame or process_frame_v2, the system invokes apply_post_processing (located in modules/processors/frame/face_swapper.py, lines 90-105). This function handles optional sharpening and the core interpolation logic. The function receives the current frame and any face bounding boxes, then applies temporal smoothing before returning the final image.

Frame Blending Logic

Inside apply_post_processing (lines 32-48), the code first verifies that enable_interpolation is True and that interpolation_weight falls within the valid range (0, 1). It then checks if a previous frame exists in the global variable PREVIOUS_FRAME_RESULT and confirms that its shape and data type match the current frame.

If these conditions pass, the frames are blended using the weighted average formula:

final_frame = (1 - interpolation_weight) * previous_frame + interpolation_weight * current_frame

The result is clipped to uint8 range to prevent overflow. This operation creates the temporal smoothing effect by ensuring the output never fully jumps to the new frame, reducing perceptible flicker.

GPU Acceleration and Fallback

The heavy addWeighted operation is GPU-accelerated via gpu_add_weighted in modules/gpu_processing.py (lines 18-41). When a CUDA-compatible GPU is available, the function uploads both frames to GPU memory, executes the weighted addition on-device, and downloads the result. If CUDA is unavailable, the system transparently falls back to OpenCV's cv2.addWeighted running on the CPU.

State Management

After blending, the global variable PREVIOUS_FRAME_RESULT is updated with the newly produced frame (lines 53-60). If interpolation is disabled or fails validation, this cache resets to None. This creates a feedback loop where each processed frame becomes the "previous" reference for the next incoming frame, establishing the temporal chain required for continuous smoothing.

Enabling and Tuning Interpolation

The following example demonstrates how to enable temporal smoothing and set a conservative blend weight that favors historical frames for maximum stability:

from modules import globals as cfg
from modules.processors.frame.face_swapper import process_frame_v2

# Enable temporal smoothing

cfg.enable_interpolation = True           # Turn the feature on

cfg.interpolation_weight = 0.2           # 20% current frame, 80% previous frame

# Assume `frame` is a NumPy BGR image captured from a webcam

smooth_frame = process_frame_v2(frame)

# `smooth_frame` now contains the temporally-smoothed output

When interpolation_weight is set to 0.2, the output retains 80% of the previous frame's pixels, effectively creating a motion blur effect that masks jitter between consecutive captures.

Summary

  • Temporal smoothing is optional and controlled by enable_interpolation in modules/globals.py.
  • The blending occurs in apply_post_processing within modules/processors/frame/face_swapper.py using a weighted average of current and previous frames.
  • Lower interpolation_weight values (e.g., 0.2) increase smoothing by favoring the previous frame, while values closer to 1.0 favor the current frame with less smoothing.
  • GPU acceleration via modules/gpu_processing.py ensures the blending operation does not bottleneck live streaming performance.
  • The system maintains state through the PREVIOUS_FRAME_RESULT global variable, creating a feedback loop for temporal consistency across consecutive frames.

Frequently Asked Questions

How do I enable frame interpolation in Deep-Live-Cam?

Set modules.globals.enable_interpolation = True and configure modules.globals.interpolation_weight to a value between 0 and 1 (e.g., 0.2 for heavy smoothing). These settings are typically exposed in the application's UI but can be set programmatically before calling process_frame_v2().

Does frame interpolation require a CUDA-compatible GPU?

No. While the system uses gpu_add_weighted in modules/gpu_processing.py to accelerate blending when CUDA is available, it automatically falls back to cv2.addWeighted on the CPU if no compatible GPU is detected. The temporal smoothing functionality works on both hardware configurations.

What happens when the interpolation_weight is set to 0?

When interpolation_weight is 0, the formula returns 100% of the previous frame and 0% of the current frame. According to the logic in modules/processors/frame/face_swapper.py (lines 32-38), interpolation only proceeds when the weight is between 0 and 1, so a value of 0 effectively bypasses blending or results in no visible update from the current camera capture.

Does enabling interpolation affect the face sharpening feature?

No. The sharpening logic (applied when sharpness > 0) executes before the interpolation step inside apply_post_processing. As implemented in modules/processors/frame/face_swapper.py (lines 97-112), sharpening operates on the face bounding boxes independently of the temporal blending that occurs afterward (lines 39-48). The two features are applied sequentially, not mixed.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →