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

> Discover how Deep-Live-Cam optimizes face detection on Apple Silicon Macs M1-M5 with adaptive detection rates. Reduce CPU load and enjoy smooth real-time face swapping.

- Repository: [Kenneth Estanislao/Deep-Live-Cam](https://github.com/hacksider/Deep-Live-Cam)
- Tags: performance
- Published: 2026-03-01

---

**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`](https://github.com/hacksider/Deep-Live-Cam/blob/main/modules/processors/frame/face_swapper.py), the code checks the platform and machine architecture to set a global flag:

```python
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:

```python
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:

```python
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:

```python
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:

```python
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`](https://github.com/hacksider/Deep-Live-Cam/blob/main/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:

```python

# 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:

```python
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:

```python

# 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:

```python
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`](https://github.com/hacksider/Deep-Live-Cam/blob/main/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`](https://github.com/hacksider/Deep-Live-Cam/blob/main/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`](https://github.com/hacksider/Deep-Live-Cam/blob/main/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`](https://github.com/hacksider/Deep-Live-Cam/blob/main/modules/face_analyser.py), and the UI integration occurs in [`modules/ui.py`](https://github.com/hacksider/Deep-Live-Cam/blob/main/modules/ui.py) within the `_detection_thread_func` function.