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 (defaultTrue) that toggles the feature on or off.interpolation_weight– A float value (default0) 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_interpolationinmodules/globals.py. - The blending occurs in
apply_post_processingwithinmodules/processors/frame/face_swapper.pyusing a weighted average of current and previous frames. - Lower
interpolation_weightvalues (e.g.,0.2) increase smoothing by favoring the previous frame, while values closer to1.0favor the current frame with less smoothing. - GPU acceleration via
modules/gpu_processing.pyensures the blending operation does not bottleneck live streaming performance. - The system maintains state through the
PREVIOUS_FRAME_RESULTglobal 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →