How Deep-Live-Cam Optimizes Face Detection on Apple Silicon (M1-M5) with Adaptive Detection Rates

Deep-Live-Cam limits face detection to 30 FPS on Apple Silicon Macs by using platform-specific detection and time-based caching, significantly reducing CPU/GPU load while maintaining smooth real-time face swapping.

Deep-Live-Cam implements a dedicated Apple-Silicon-aware pipeline to optimize face detection on M-series Macs. The optimization centers on adaptive frame-skipping and result caching, ensuring that the computationally expensive detection model runs at most once every 33 milliseconds regardless of the camera's actual frame rate.

Platform Detection and Adaptive Interval Setup

The optimization begins at module import time, where the code determines whether it is running on Apple Silicon and configures the throttling parameters.

Detecting Apple Silicon Architecture

In modules/processors/frame/face_swapper.py, the code checks the platform and machine architecture to set a global flag:

IS_APPLE_SILICON = platform.system() == 'Darwin' and platform.machine() == 'arm64'

This boolean determines whether the adaptive caching logic activates. On non-Apple-Silicon systems, the pipeline falls back to standard detection on every frame.

Configuring the Detection Interval

The module defines a constant that governs the minimum time between fresh detection passes:

DETECTION_INTERVAL = 0.033  # approximately 30 FPS

This value ensures that even if the camera delivers 60 or 120 FPS, the face detection model only executes at most 30 times per second.

The get_faces_optimized Function

The core optimization lives in the get_faces_optimized function, which wraps the standard detection calls with a caching layer.

Cache-Based Fast Path

The function maintains two global state variables to track recent results:

LAST_DETECTION_TIME = 0
FACE_DETECTION_CACHE = {}

When get_faces_optimized(frame, use_cache=True) is called on Apple Silicon, it first calculates the elapsed time since the last detection:

current_time = time.time()
time_since_last = current_time - LAST_DETECTION_TIME

if time_since_last < DETECTION_INTERVAL and FACE_DETECTION_CACHE:
    return FACE_DETECTION_CACHE.get('faces')

If the interval has not elapsed and cached faces exist, the function returns the cached result immediately, bypassing the model entirely.

Fresh Detection and Cache Update

When the interval expires or the cache is empty, the function executes a fresh detection using the underlying analyzers:

LAST_DETECTION_TIME = current_time

if modules.globals.many_faces:
    faces = get_many_faces(frame)
else:
    faces = get_one_face(frame)

FACE_DETECTION_CACHE['faces'] = faces
FACE_DETECTION_CACHE['timestamp'] = current_time

return faces

This updates the global timestamp and stores the new results for subsequent frames.

Integration with the Processing Pipeline

The optimized detection integrates into the live processing loop via modules/ui.py. The _detection_thread_func runs continuously, filling a shared detection_result dictionary. While the standard implementation calls get_many_faces or get_one_face directly, builds targeting Apple Silicon can substitute get_faces_optimized to leverage the adaptive rate limiting:


# In modules/ui.py, _detection_thread_func

if modules.globals.many_faces:
    many = get_faces_optimized(frame)  # Adaptive path for Apple Silicon

    detection_result['many_faces'] = many
else:
    face = get_faces_optimized(frame)
    detection_result['target_face'] = face[0] if face else None

This ensures that the UI thread receives face coordinates at the camera frame rate, but the underlying model only executes at the throttled 30 FPS rate.

Code Examples

Basic Usage on Apple Silicon

To use the optimized detection in a custom processor:

from modules.processors.frame.face_swapper import get_faces_optimized
from modules.typing import Frame

def process_frame(frame: Frame):
    # Automatically uses caching on M1-M5 Macs

    faces = get_faces_optimized(frame, use_cache=True)
    if faces:
        # Proceed with face swapping or enhancement

        pass

Patching the UI Thread

To enable adaptive detection in the live camera view:


# Inside modules/ui.py, within _detection_thread_func:

if modules.globals.many_faces:
    many = get_faces_optimized(frame)   # Replaces get_many_faces

    detection_result['many_faces'] = many
else:
    face = get_faces_optimized(frame)     # Replaces get_one_face

    detection_result['target_face'] = face[0] if face else None

Inspecting Cache State

For debugging performance on Apple Silicon:

from modules.processors.frame.face_swapper import (
    FACE_DETECTION_CACHE,
    LAST_DETECTION_TIME
)

print(f"Cached faces: {FACE_DETECTION_CACHE.get('faces')}")
print(f"Last detection: {LAST_DETECTION_TIME}")

Summary

  • Platform-aware activation: Deep-Live-Cam detects Apple Silicon via platform.system() == 'Darwin' and platform.machine() == 'arm64' in modules/processors/frame/face_swapper.py.
  • Adaptive throttling: A DETECTION_INTERVAL of 0.033 seconds (30 FPS) limits how often the face detection model runs, regardless of camera frame rate.
  • Result caching: The FACE_DETECTION_CACHE dictionary stores recent detection results, allowing instantaneous retrieval for frames arriving within the throttle window.
  • Performance impact: By skipping redundant inference on M1-M5 Macs, the pipeline reduces CPU/GPU utilization and maintains smoother real-time face swapping.

Frequently Asked Questions

What is the detection interval used in Deep-Live-Cam?

The detection interval is set to 0.033 seconds (approximately 30 FPS) via the DETECTION_INTERVAL constant in modules/processors/frame/face_swapper.py. This value ensures that the face detection model executes at most 30 times per second, even if the camera captures video at 60 FPS or higher.

How does the cache improve performance on Apple Silicon?

The FACE_DETECTION_CACHE dictionary stores the most recent detection results and timestamp. When subsequent frames arrive within the 33-millisecond window, get_faces_optimized returns the cached face coordinates instantly without invoking the neural network. This adaptive frame-skipping dramatically reduces compute load on M-series chips while maintaining visual continuity.

Can I disable the adaptive detection on Apple Silicon?

Yes. The get_faces_optimized function accepts a use_cache parameter that defaults to True. Passing use_cache=False bypasses the Apple-Silicon-specific logic and forces a fresh detection call to get_one_face or get_many_faces on every frame, effectively disabling the adaptive rate limiting.

Where is the face detection logic implemented?

The core optimization resides in modules/processors/frame/face_swapper.py, specifically within the get_faces_optimized function (lines 54–87). The underlying face analysis utilities (get_one_face, get_many_faces) are defined in modules/face_analyser.py, and the UI integration occurs in modules/ui.py within the _detection_thread_func function.

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 →